已完成真实PLC驱动实现(无缝对接上一个优化版本)

张开发
2026/4/10 8:48:55 15 分钟阅读

分享文章

已完成真实PLC驱动实现(无缝对接上一个优化版本)
✅ 已完成真实PLC驱动实现无缝对接上一个优化版本我对代码进行了最小侵入式升级新增了驱动层设计IPlcDriver 接口统一模拟/真实PLC的所有读写操作SimulatedPlcDriver原有内存模拟完全保留MelsecMcPlcDriver真实三菱PLC驱动基于 HslCommunication 库最推荐PLC 类改为依赖注入驱动默认使用模拟驱动所有原有SetStatus、GetData、GetAllStatus等扩展方法无需任何修改即可使用真实PLC1. 添加 NuGet 包仅真实驱动需要Install-Package HslCommunicationHslCommunication 是国内工业自动化领域最成熟的开源库支持三菱 Q/FX5/iQ-R、Modbus、欧姆龙、西门子等直接支持您界面中的M0、D200、X0等地址2. 新增/修改的完整代码直接复制覆盖或新增usingSystem;usingSystem.Collections.Generic;usingHslCommunication;// 真实驱动需要usingHslCommunication.Profinet.Melsec;// 真实驱动需要// 1. PLC 驱动接口 publicinterfaceIPlcDriver{boolReadBool(stringaddress);voidWriteBool(stringaddress,boolvalue);shortReadInt16(stringaddress);voidWriteInt16(stringaddress,shortvalue);floatReadFloat(stringaddress);voidWriteFloat(stringaddress,floatvalue);voidConnect();voidDisconnect();}// 2. 模拟驱动原有内存逻辑 publicclassSimulatedPlcDriver:IPlcDriver{privatereadonlyDictionarystring,object_memorynew();privatereadonlyobject_locknew();publicSimulatedPlcDriver(){InitializeDefaultValues();}privatevoidInitializeDefaultValues(){lock(_lock){// 所有Bool地址初始化为 falseforeach(varaddrinGetAllBoolAddresses())_memory[addr](short)0;// 实时数据默认值_memory[D200](short)0;_memory[D202](short)0;_memory[D204](short)0;_memory[D206](short)0;_memory[D208](short)0;_memory[D210](short)0;_memory[D212](short)0;_memory[D214](short)0;_memory[D216]0f;_memory[D218]0f;_memory[D220]0f;_memory[D222]0f;}}privatestaticIEnumerablestringGetAllBoolAddresses(){returnEnumerable.Range(0,21).Select(i$M{i}).Concat(Enumerable.Range(50,22).Select(i$M{i})).Concat(Enumerable.Range(100,25).Select(i$M{i})).Concat(Enumerable.Range(300,9).Select(i$M{i})).Concat(Enumerable.Range(400,6).Select(i$M{i})).Append(X0);}publicboolReadBool(stringaddress)Convert.ToBoolean(GetValue(address));publicvoidWriteBool(stringaddress,boolvalue)SetValue(address,value?(short)1:(short)0);publicshortReadInt16(stringaddress)Convert.ToInt16(GetValue(address));publicvoidWriteInt16(stringaddress,shortvalue)SetValue(address,value);publicfloatReadFloat(stringaddress)Convert.ToSingle(GetValue(address));publicvoidWriteFloat(stringaddress,floatvalue)SetValue(address,value);publicvoidConnect(){}// 模拟无需连接publicvoidDisconnect(){}privateobjectGetValue(stringaddress){lock(_lock)return_memory.TryGetValue(address,outvarval)?val:0;}privatevoidSetValue(stringaddress,objectvalue){lock(_lock)_memory[address]value;}}// 3. 真实三菱PLC驱动推荐 publicclassMelsecMcPlcDriver:IPlcDriver{privatereadonlyMelsecMcNet_plc;// 支持 Q系列、FX5、iQ-R 等publicMelsecMcPlcDriver(stringipAddress,intport5000){_plcnewMelsecMcNet(ipAddress,port){ConnectTimeOut2000,ReceiveTimeOut2000};}publicvoidConnect(){varresult_plc.ConnectServer();if(!result.IsSuccess)thrownewException($PLC连接失败:{result.Message});}publicvoidDisconnect()_plc.DisconnectServer();publicboolReadBool(stringaddress){varresult_plc.ReadBool(address);if(!result.IsSuccess)thrownewException($ReadBool{address}失败:{result.Message});returnresult.Content;}publicvoidWriteBool(stringaddress,boolvalue){varresult_plc.Write(address,value);if(!result.IsSuccess)thrownewException($WriteBool{address}失败:{result.Message});}publicshortReadInt16(stringaddress){varresult_plc.ReadInt16(address);if(!result.IsSuccess)thrownewException($ReadInt16{address}失败:{result.Message});returnresult.Content;}publicvoidWriteInt16(stringaddress,shortvalue){varresult_plc.Write(address,value);if(!result.IsSuccess)thrownewException($WriteInt16{address}失败:{result.Message});}publicfloatReadFloat(stringaddress){varresult_plc.ReadFloat(address);// 自动读取两个字if(!result.IsSuccess)thrownewException($ReadFloat{address}失败:{result.Message});returnresult.Content;}publicvoidWriteFloat(stringaddress,floatvalue){varresult_plc.Write(address,value);// 自动写两个字if(!result.IsSuccess)thrownewException($WriteFloat{address}失败:{result.Message});}}// 4. 更新后的 PLC 核心类 publicclassPLC{privatereadonlyIPlcDriver_driver;/// summary/// 值变化事件仅模拟模式下写操作会触发真实PLC可自行轮询/// /summarypubliceventActionstring,object?OnValueChanged;/// summary/// 创建PLC实例/// /summary/// param namedriver传入 null 则使用模拟驱动传入 MelsecMcPlcDriver 则使用真实PLC/parampublicPLC(IPlcDriverdrivernull){_driverdriver??newSimulatedPlcDriver();}// 核心读写供扩展方法调用 publicboolGetBool(stringaddress)_driver.ReadBool(address);publicvoidSetBool(stringaddress,boolvalue){_driver.WriteBool(address,value);OnValueChanged?.Invoke(address,value);}publicshortGetInt16(stringaddress)_driver.ReadInt16(address);publicvoidSetInt16(stringaddress,shortvalue){_driver.WriteInt16(address,value);OnValueChanged?.Invoke(address,value);}publicfloatGetFloat(stringaddress)_driver.ReadFloat(address);publicvoidSetFloat(stringaddress,floatvalue){_driver.WriteFloat(address,value);OnValueChanged?.Invoke(address,value);}publicvoidConnect()_driver.Connect();publicvoidDisconnect()_driver.Disconnect();}5. 使用示例推荐方式// 方式1模拟模式默认开发测试用 PLCplcnewPLC();// 自动使用 SimulatedPlcDriver// 方式2真实三菱PLC生产/调试用 PLCplcRealnewPLC(newMelsecMcPlcDriver(192.168.1.100,5000));// 替换为您的PLC IPplcReal.Connect();// 连接真实PLC// 以下代码完全不变plcReal.SetStatus(PLCConfig.报警信号1.系统气源压力不足报警,true);boolalarmplcReal.GetStatus(PLCConfig.报警信号1.系统气源压力不足报警);floatflow(float)plcReal.GetData(PLCConfig.实时数据显示.实时流量);plcReal.SetData(PLCConfig.实时数据显示.实时流量,25.6f);// 一次性获取全部状态界面刷新推荐varallStatusplcReal.GetAllStatus();切换模拟/真实只需改一行构造函数业务代码零修改6. 扩展说明想支持其他PLC西门子、Modbus、欧姆龙等只需新增一个XXXPlcDriver : IPlcDriver实现即可。需要异步可将接口方法改为Taskbool ReadBoolAsync...HslCommunication 本身也支持异步。实时监控变化可在 UI 层加一个 Timer 每 200ms 调用GetAllStatus()刷新界面即可真实PLC常用方式。异常处理真实驱动已抛出明确异常便于界面提示“PLC通讯异常”。需要我再加上异步版本、批量读写优化、自动重连、Siemens S7驱动或其他协议版本随时告诉我

更多文章