前言
工业数据采集和监控这活儿,说难不算难,说简单也不简单。难点不在于Modbus协议有多复杂,而在于一套系统要把串口通信、界面刷新、数据存储、报警处理这些事情都理顺,还不能互相拖后腿。
最近在做一个工业冷却系统的上位机项目,正好走了一遍从硬件通信到界面展示的完整流程。这套方案基于WPF,通过Modbus RTU协议跟下位机设备打交道,采集到的数据实时展示在界面上,同时存进SQL Server。文章整理了项目中的一些设计和实现细节,供有类似需求的同行参考。
项目介绍
一个基于WPF的SCADA类数据采集与监控系统,主要面向工业冷却场景。系统通过Modbus RTU协议与下位机设备通信,实时采集温度、压力、流量等运行参数,在WPF界面中动态展示,并将数据存入SQL Server数据库以便后续查询和分析。
项目结构采用了分层设计,分为通信层(SerialPort通信与Modbus协议封装)、数据访问层(DAL)、业务逻辑层(BLL)、视图层(View)和视图模型层(ViewModel),以及自定义控件库。
项目功能
Modbus RTU数据采集:通过串口与下位机通信,读取保持寄存器中的数据,支持浮点数解析(大端AB CD格式)
实时数据监控:在WPF界面中动态更新设备参数,包括温度、压力、流量等关键指标
自定义图形控件:冷却塔、冷却水泵、管道流动画等工业设备图形组件,直观呈现设备状态
阈值报警机制:当监控数值超过上下限时,界面自动触发报警信息并记录
数据持久化:将实时数据存入SQL Server数据库,支持历史数据追溯
设备与点位管理:通过数据库表管理设备信息、监控点位和存储区配置
日志记录:记录系统运行日志和报警信息,便于问题排查
项目特点
分层架构清晰:按MVC模式变体组织,通信层、业务层、视图层职责分明,易于扩展和维护
实时性较好:通过独立线程或定时器驱动采集循环,界面数据刷新流畅
报警机制完备:数值越限时自动触发报警并记录,支持报警状态显示与历史查询
自定义控件复用:冷却塔、水泵、管道等图形控件封装良好,可复用于不同项目
配置化设计:串口参数、从站地址、寄存器映射等信息通过配置文件或数据库管理,减少硬编码
工业场景适配:面向冷却系统、水处理等典型工控场景,非通用业务系统
项目技术
技术项 | 选型 | 说明 |
开发语言 | C# | .NET平台主流语言 |
UI框架 | WPF | 桌面端图形界面开发 |
通信协议 | Modbus RTU | 工业串行通信标准协议 |
数据库 | SQL Server 2026 | 数据持久化存储 |
数据库 | SQL Server Management Studio 2022 | 数据库管理与查询 |
架构模式 | 分层架构(类似MVVM) | 界面与业务逻辑分离 |
开发环境 | Visual Studio | 集成开发环境 |
项目代码
目录结构
项目按功能模块组织,层次清晰:
├── Communication/ # 类库:串口通信层│ ├── Modbus/RTU.cs # Modbus RTU协议实现│ └── SerialInfo.cs # 串口配置模型├── Controls/ # 类库:自定义控件│ ├── CircularProgressBar.xaml(.cs) # 环形进度条控件│ └── Components/│ ├── ComponentBase.cs # 设备组件基类│ ├── CoolingTower.xaml(.cs) # 冷却塔图形组件│ ├── CoolingPump.xaml(.cs) # 冷却水泵图形组件│ └── Pipeline.xaml(.cs) # 管道流动画组件└── DataAcquisitionAndMonitoringSystem/ # WPF主项目 ├── /Base/ # 基础设施 │ ├── CommandBase.cs # ICommand实现 │ ├── NotifyPropertyBase.cs # INotifyPropertyChanged实现 │ ├── GlobalMonitor.cs # 全局监控核心循环 │ └── Converter/ # 值转换器 ├── /Model/ # 数据模型 │ ├── DeviceModel.cs # 设备模型 │ ├── MonitorValueModel.cs # 监控点位模型 │ └── LogModel.cs # 日志模型 ├── /DAL/ # 数据访问层 │ └── DataAccess.cs # SQL Server数据操作 ├── /BLL/ # 业务逻辑层 │ ├── IndustrialBLL.cs # 业务逻辑处理 │ └── DataResult.cs # 通用结果包装 ├── /ViewModel/ # 视图模型 │ ├── MainViewModel.cs # 主窗口VM+导航 │ └── SystemMonitorViewModel.cs # 系统监控页VM └── /View/ # 视图 ├── SystemMonitor.xaml(.cs) # 系统监控主界面 └── ReportManagement.xaml(.cs) # 报表页(预留)核心代码说明
Modbus RTU通信层
通信层封装了Modbus RTU协议的读写操作,包括功能码3(读保持寄存器)的实现。串口通信采用超时控制,单次请求超时不影响后续轮询。
// 串口配置模型public class SerialInfo{ public string PortName { get; set; } public int BaudRate { get; set; } public int DataBits { get; set; } public StopBits StopBits { get; set; } public Parity Parity { get; set; }}全局监控核心循环
GlobalMonitor类负责驱动整个采集循环,按配置的间隔轮询各从站设备,读取寄存器数据并触发界面更新和报警检查。
字节转浮点扩展
下位机返回的数据是字节数组,需要根据Modbus的数据格式转换为浮点数。项目中实现了大端AB CD格式的浮点数转换方法。
数据库设计
系统使用三张核心表:
devices:设备表,存储冷却塔等设备的基本信息
monitor_values:监控信息表,存储各设备的实时监控数据
storage_area:存储区表,配置各从站的寄存器映射关系
项目效果
在实际运行中,这套系统的使用流程大致是这样的
先用VSPD虚拟串口工具创建一对串口(比如COM1和COM2),程序这边连COM1,Modbus Slave模拟软件那边连COM2。在Modbus Slave中把从站ID设为1,存储区设置为03保持寄存器,起始地址0,长度36。
启动程序后,界面会显示冷却塔的图形组件和各监控参数。往Modbus Slave的寄存器里填数值(浮点数格式选大端AB CD),程序就能实时读取并更新界面上的温度、压力等数据。当数值超过设定的上下限时,界面下方会自动出现报警信息,比如“冷却塔1的入口压力极高。当前值:100”。 项目源码
当前仓库包含完整的解决方案文件、通信层类库、自定义控件库和WPF主项目。代码已实现基础的Modbus RTU通信、数据采集、界面展示和报警功能,数据库部分预留了接口,可按实际需求扩展。
为了防止丢失,可以在评论区留言关键字「工业SCADA系统」,即可获取完整源码地址。
总结
这套数据采集与监控系统解决了一个很实际的问题:如何用一套清晰的架构把Modbus通信、界面展示、数据存储和报警处理串起来。它没有把全部代码塞进MainWindow.xaml.cs里,而是通过分层设计让各个模块各司其职——通信层专心跟串口打交道,业务层处理数据转换和逻辑判断,界面层只负责展示和用户交互。
对于正在做工控上位机项目的人来说,这个项目的参考价值在于看到一种可行的分层方式。Modbus RTU协议本身不难,难的是当设备数量增加、数据量变大、报警逻辑变复杂的时候,代码还能不能保持清晰可维护。这套方案在冷却系统场景中跑通了,稳定可靠。
关键词
最后
如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。也可以加入微信公众号[DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!
作者:小码编匠
出处:gitee.com/smallcore/DotNetCore
声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!
方便大家交流、资源共享和共同成长
纯技术交流群,需要加入的小伙伴请扫码,并备注【加群】
推荐阅读
觉得有收获?不妨分享让更多人受益
关注「DotNet技术匠」,共同提升技术实力
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!