C#电量采集系统源码:MODBUS 485通信读取70块中电品牌电量表电度数,10分钟存盘至数量库
C#编写电量采集系统MODBUS 485通信读取70块电量表电度数(电表品牌:中电)里面有完整的采集源码采集数据10分钟存盘一次存至数量库随时可查看或计算区间电量。 提供运行稳定不受使用时间限制完整的协议代码非DLL,容易理解便于修改稍作修改就能移植到自己的项目最近在工业园区的配电房改造项目中接触到了中电HDZY-3系列电表。现场70块表计需要通过MODBUS 485总线采集数据用C#撸了个稳定运行的电量采集系统。实测连续运行两个月无宕机这里分享几个关键实现点。先看硬件拓扑485总线手拉手连70块表每块表配置了不同的设备地址1-70。采用轮询方式采集通过USB转485转换器接入工控机。这里有个坑——485总线长度超过800米时需加中继器不过这次运气好布线在500米内搞定了。C#编写电量采集系统MODBUS 485通信读取70块电量表电度数(电表品牌:中电)里面有完整的采集源码采集数据10分钟存盘一次存至数量库随时可查看或计算区间电量。 提供运行稳定不受使用时间限制完整的协议代码非DLL,容易理解便于修改稍作修改就能移植到自己的项目核心代码部分先从MODBUS协议解析开始。自己撸的协议解析器比调用DLL灵活得多特别是处理不同电表型号时//MODBUS RTU请求帧生成 byte[] BuildReadRequest(byte slaveId, ushort startAddress, ushort length) { var frame new Listbyte { slaveId, 0x03 }; frame.AddRange(BitConverter.GetBytes(startAddress).Reverse()); frame.AddRange(BitConverter.GetBytes(length).Reverse()); var crc CalcCRC(frame.ToArray()); frame.AddRange(crc); return frame.ToArray(); } //CRC校验算法这才是协议栈的灵魂 ushort CalcCRC(byte[] data) { ushort crc 0xFFFF; foreach (byte b in data) { crc ^ b; for (int i 0; i 8; i) { crc (crc 1) ! 0 ? (ushort)((crc 1) ^ 0xA001) : (ushort)(crc 1); } } return (ushort)((crc 8) | (crc 8)); //注意字节序 }电表数据的解析需要特别注意IEEE754浮点数的处理。中电的表计返回4字节数据但字节顺序和常规写法不同float ParseEnergyValue(byte[] data) { // 示例数据0x43 0x9E 0x00 0x00 实际对应312.0度 if (data.Length ! 4) throw new ArgumentException(电度数据长度异常); // 中电表计的浮点排列是Big-endian Array.Reverse(data); //转换为小端模式 return BitConverter.ToSingle(data, 0); }采集任务调度采用定时器异步模式避免界面卡顿。这里用了个取巧的队列机制防止设备响应超时// 轮询控制器 class PollingScheduler { private ConcurrentQueueint _deviceQueue new ConcurrentQueueint(Enumerable.Range(1, 70)); private System.Timers.Timer _timer new System.Timers.Timer(200); //200ms间隔 public void Start() { _timer.Elapsed async (s, e) { if(_deviceQueue.TryDequeue(out int deviceId)) { var result await ReadEnergyAsync(deviceId); SaveToBuffer(result); _deviceQueue.Enqueue(deviceId); //重新入队循环 } }; _timer.Start(); } }数据存储方面用SQLite做本地缓存10分钟触发一次批量写入。这里有个性能优化点——采用WAL写入模式// 定时存盘 using (var conn new SQLiteConnection(Data Sourceenergy.db;Journal ModeWAL)) { conn.Open(); using (var trans conn.BeginTransaction()) { var cmd conn.CreateCommand(); cmd.CommandText INSERT INTO records(dt,device_id,kwh) VALUES(dt,id,kwh); foreach (var data in _buffer) { cmd.Parameters.Clear(); cmd.Parameters.AddWithValue(dt, data.Timestamp); cmd.Parameters.AddWithValue(id, data.DeviceId); cmd.Parameters.AddWithValue(kwh, data.Kwh); cmd.ExecuteNonQuery(); } trans.Commit(); } }系统还做了几个增强稳定性的处理串口异常时自动重连机制设备连续三次无响应后自动跳过记录故障日志电压/电流等非必要参数采集开关配置采集间隔动态调整夜间负载低时加快采集频率这套系统在部署时遇到过一个坑现场有变频器干扰导致偶发通讯失败。后来通过修改485终端电阻加120Ω电阻和调整波特率从9600降到4800解决。代码层面增加了错误数据过滤规则比如排除负电量和突变值。想移植到自己项目的话重点改这几个地方设备地址范围和轮询顺序DeviceQueue生成逻辑数据解析方法不同厂家字节顺序可能不同存盘时间间隔和数据库类型支持切MySQL只需改连接字符串增加Modbus TCP支持协议帧头调整即可源码里最值得参考的是协议层实现完全从字节层面处理避免了第三方库的依赖。实测在Intel NUC工控机上CPU占用长期低于3%内存稳定在50MB左右真正做到了7x24无监护运行。