前言
这两年我们在自动化产线项目里用 WPF 做了一套上位机监控系统,通过 Modbus RTU 协议跟 PLC 通信,实时采集灌装设备的温度、液位、阀门状态、生产节拍这些关键参数。整个过程走下来感觉这个组合还挺顺手的,这里把设计和实现过程做个记录。
项目介绍
智能灌装生产监控系统是一套基于 WPF + .NET 8 开发的工业自动化上位机软件。它通过 Modbus RTU 协议与产线 PLC 保持实时通信,对灌装设备的运行状态、填充精度、温度液位、阀门动作等关键参数进行毫秒级采集与可视化展示。
项目采用 CommunityToolkit.Mvvm 作为 MVVM 框架,配合 FreeSql 做数据持久化,图表部分用 LiveCharts 呈现生产过程趋势。
项目功能
设备状态实时监控:通过 Modbus RTU 协议采集 PLC 寄存器数据,实时显示灌装设备的运行模式、启停状态、故障代码等信息
关键工艺参数展示:温度、液位、压力、填充精度等模拟量数据以数值和仪表盘形式呈现,更新频率可配置
生产节拍统计:实时计算并展示当前产线的生产速度、累计产量、批次完成进度
阀门与执行器动作监控:显示各灌装阀、清洗阀、进料阀的开关状态及动作次数
实时趋势曲线:基于 LiveCharts 绘制温度、液位、填充量等参数的变化曲线,支持多测点叠加对比
数据存储与回放:通过 FreeSql 将采集数据写入本地数据库,支持历史数据查询和曲线回放
异常告警机制:当参数超限或设备状态异常时,界面闪烁提示并记录告警日志
项目特点
基于 Modbus RTU 工业标准协议,兼容主流 PLC 品牌
毫秒级数据采集与刷新,满足产线实时监控需求
采用 MVVM 架构,界面与业务逻辑分离,后期维护和功能扩展成本低
深色主题 UI,适合工业现场长时间盯屏的操作环境
模块化设计,采集、存储、界面各层解耦,方便替换或升级局部组件
轻量化部署,一台工控机即可覆盖单条产线的监控需求
支持自定义采集周期和报警阈值,适应不同产线的工艺要求
项目技术
技术组件 | 用途说明 |
.NET 8 | 运行时框架 |
WPF | 桌面 UI 框架,支持 XAML 样式定制和数据绑定 |
CommunityToolkit.Mvvm | MVVM 框架,负责 ViewModel 和命令绑定 |
FreeSql | ORM 工具,用于采集数据的本地持久化存储 |
Serilog | 结构化日志记录,便于问题排查 |
Modbus RTU | 与 PLC 通信的工业总线协议 |
LiveCharts | 实时趋势曲线绘制 |
项目代码
主窗口采用上下和左右混合布局,顶部是标题栏和状态区,左侧是导航菜单,右侧 ContentControl 承载各功能页面视图。
<Window x:Class="SmartFillMonitor.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:UserControls="clr-namespace:SmartFillMonitor.UserControls" Title="智能灌装生产监控系统" Height="720" Width="1280" Background="{StaticResource AppBgDark}" WindowStyle="None" AllowsTransparency="True"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="100"/> <RowDefinition Height="*"/> <!--Grid.RowDefinitions--> <Grid.ColumnDefinitions> <ColumnDefinition Width="220"/> <ColumnDefinition Width="*"/> <!--Grid.ColumnDefinitions--> <!-- 左侧导航菜单 --> <UserControls:NavigationMenu Grid.Column="0" Grid.RowSpan="2"/> <!-- 顶部标题栏 --> <Border Grid.Column="1" Grid.Row="0" Background="{StaticResource AppBgHeader}"> <Grid Margin="20,0"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> <!--Grid.ColumnDefinitions--> <!-- 当前批次信息 --> <TextBlock Grid.Column="0" Foreground="{StaticResource AppTextMuted}" VerticalAlignment="Center"> <Run Text="当前生产批次:"/> <Run Text="{Binding CurrentBatchNo}" FontWeight="SemiBold"/> <!--TextBlock--> <!-- 状态指示器 --> <StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center"> <UserControls:StatusIndicator StatusText="PLC在线" IsOnline="{Binding IsPlcConnected}" Margin="0,0,20,0"/> <TextBlock Text="{Binding CurrentTime}" Foreground="{StaticResource AppTextMuted}" FontFamily="Consolas" FontSize="14" VerticalAlignment="Center" Margin="0,0,20,0"/> <UserControls:StatusLight State="{Binding MainContent.IndicatorState, Mode=TwoWay}" Margin="0,0,20,0" VerticalAlignment="Center"/> <!--StackPanel--> <!--Grid--> <!--Border--> <!-- 主内容区 --> <ContentControl Grid.Column="1" Grid.Row="1" Background="{StaticResource AppBgDark}" Margin="20" Content="{Binding MainContent}"/> <!--Grid--><!--Window-->顶部状态栏包含了当前批次号、PLC 连接状态、运行时间以及一个自定义状态指示灯。
这里用了一个小技巧:MainContent.IndicatorState 这个绑定路径表示先在 MainWindowViewModel 中找 MainContent 属性,再在 MainContent 返回的对象里找 IndicatorState 属性。
MainContent 通过依赖注入初始化为 DashBoardViewModel 的实例,这样状态指示灯的颜色就能跟随仪表盘页面的采集质量动态变化。
Modbus RTU 通信部分封装在独立的服务类中,负责维护串口连接、读写寄存器和异常处理。
public classModbusRtuService : IModbusService{ private SerialPort _serialPort; private ILogger _logger; public bool Connect(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits) { try { _serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits); _serialPort.Open(); _logger.Information($"Modbus RTU 连接成功:{portName}"); returntrue; } catch (Exception ex) { _logger.Error(ex, $"Modbus RTU 连接失败:{portName}"); returnfalse; } } public ushort[] ReadHoldingRegisters(byte slaveId, ushort startAddress, ushort length) { // 实际项目中通过 NModbus 库实现 // ... }}项目效果
主界面采用深色主题,适合工业现场低照度环境。左侧导航菜单包含"仪表盘""设备监控""数据查询""报警记录"等入口,切换流畅。
仪表盘页面集中展示了灌装设备的核心参数:温度、液位、填充量等模拟量用仪表盘控件呈现,数值变化时指针平滑转动;设备状态区域用不同颜色的指示灯标识运行、待机、故障三种模式;底部是实时趋势曲线,温度、压力等参数随时间变化一目了然。
顶部状态栏的 PLC 在线指示灯和数据库写入状态让操作人员随时了解系统健康度,右侧的登录和退出按钮方便不同班次的人员切换操作权限。
项目源码
运行前需要在 appsettings.json 中配置 Modbus RTU 的串口参数(端口号、波特率、校验位等),以及数据库连接字符串。
总结
这套灌装监控系统从立项到上线大概用了两个月,最花时间的反而不是界面,而是 Modbus 通信的稳定性和数据解析的准确性——工业现场的各种干扰和异常情况比实验室里复杂得多。
好在 WPF 的数据绑定机制让界面和逻辑能拆得比较干净,后续设备增删测点或者调整采集逻辑的时候,不用大动干戈。如果大家也在做类似的上位机项目,可以试试这套技术组合。
关键词
最后
如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。也可以加入微信公众号[DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!
作者:小码编匠
出处:gitee.com/smallcore/DotNetCore
声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!
觉得有收获?不妨分享让更多人受益
关注「DotNet技术匠」,共同提升技术实力
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!