这个项目实现了一个工业级数据监控方案,通过C#开发的上位机程序与Modbus TCP设备通信,实时采集数据并动态绘制曲线图表。我在自动化生产线调试中多次使用类似方案,其核心价值在于将枯燥的寄存器数据转化为直观的可视化趋势图,帮助工程师快速发现设备异常波动。
系统采用经典的三层架构:底层通过Modbus TCP协议与PLC/传感器通信,中间层处理数据解析与缓存,上层使用WinForms或WPF实现动态图表展示。相比传统组态软件,这种自主开发的方案具有更高的定制灵活性,能够根据产线特点调整采样频率、图表样式和报警阈值。
采用开源的NModbus4库作为通信基础(NuGet包可直接安装),相比自行实现协议栈有以下优势:
典型寄存器读取代码示例:
csharp复制var factory = new ModbusFactory();
using(var master = factory.CreateMaster(tcpClient)){
ushort[] holdingRegisters = master.ReadHoldingRegisters(slaveId, startAddress, numRegisters);
}
关键参数说明:slaveId需与设备配置一致(默认247),startAddress要注意Modbus地址偏移问题(设备手册标注400001对应编程地址0)
推荐使用ScottPlot或LiveCharts这两个轻量级图表库:
动态更新曲线的核心逻辑:
csharp复制// 初始化
var plot = formsPlot1.Plot;
double[] dataX = new double[1000];
double[] dataY = new double[1000];
var scatter = plot.AddScatter(dataX, dataY);
// 定时器更新
void TimerElapsed(object sender, EventArgs e){
Array.Copy(dataY, 0, dataY, 1, dataY.Length-1); // 数据左移
dataY[0] = latestValue; // 新数据插入首位
formsPlot1.Refresh();
}
为避免界面卡顿,必须采用生产者-消费者模式:
csharp复制// 通信线程
void ReadThread(){
while(!token.IsCancellationRequested){
var data = ReadModbusData();
dataQueue.Enqueue(data);
Thread.Sleep(interval);
}
}
// UI定时器
void Timer_Tick(object sender, EventArgs e){
while(dataQueue.TryDequeue(out var point)){
chart.AddData(point);
}
}
| 故障现象 | 可能原因 | 解决方案 |
|---|---|---|
| 连接超时 | 网络配置错误 | 检查IP/端口,关闭防火墙测试 |
| 数据全零 | 寄存器地址错误 | 确认地址偏移量(+1或+400001) |
| 曲线抖动 | 采样不同步 | 启用设备时间戳功能 |
| 内存泄漏 | 未释放资源 | 使用using语句包裹TcpClient |
建议采用SQLite+CSV双备份策略:
csharp复制// SQLite操作
using(var conn = new SQLiteConnection("Data Source=log.db")){
conn.Execute("INSERT INTO data(timestamp,value) VALUES(@t,@v)",
new { t=DateTime.Now, v=currentValue });
}
// CSV追加写入
File.AppendAllText("backup.csv", $"{DateTime.Now},{value}\n");
通过SignalR将数据推送到网页端:
csharp复制public class DataHub : Hub {
public async Task SendData(float value) {
await Clients.All.SendAsync("ReceiveData", value);
}
}
采样周期设置原则:
界面设计技巧:
部署注意事项:
这个项目我在多个汽车焊装线上成功应用,最关键的经验是:一定要在开发阶段模拟各种异常工况(网络中断、数据溢出、设备重启),完善的异常处理比美观的图表更重要。曾遇到因未处理连续超时导致线程锁死的情况,后来增加了看门狗机制才彻底解决。