『7x24小时有问必答』

前言

工业数据采集和监控这活儿,说难不算难,说简单也不简单。难点不在于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
声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!

END

方便大家交流、资源共享和共同成长
纯技术交流群,需要加入的小伙伴请扫码,并备注加群

推荐阅读

觉得有收获?不妨分享让更多人受益
关注「DotNet技术匠」,共同提升技术实力

收藏
点赞
分享
在看

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

上一主题上一主题         下一主题下一主题
QQ手机版小黑屋粤ICP备17165530号

关于我们·投诉举报· 用户帮助· 联系我们 · 本站服务 · 版权声明· 隐私政策 · 投搞指南

法律保护:PLC技术网,plcjs.com,plcjs.net等字样
Copyright 2010-2030. All rights reserved. 


微信公众号二维码 抖音二维码 百家号二维码 今日头条二维码哔哩哔哩二维码