最近搞了个小项目,200SMART带2台V20变频器+7个球阀,Modbus RTU轮询搞了半天,踩了点坑,分享下实际怎么弄的——
200smart modbus rtu 轮询 实际项目案例 和2台西门子v20变频器7个阀的轮询变频器写入频率读取频率启停控制运行及故障信号反馈 球阀开关控制开关型号反馈先明确硬件协议配置200SMART用PORT0做Modbus主站波特率9600、偶校验、停止位1V20站号1/2控制字启停、频率读写、状态运行/故障球阀站号3线圈控制开关、离散输入反馈关键先查手册V20的Modbus地址是协议绝对地址但200SMART的MBUS_MSG指令用的是偏移地址——比如协议里的40001实际频率指令里要写「1」偏移从1开始这个坑我踩过3次核心代码状态机轮询逻辑Modbus是串行通信同一时间只能发1个请求所以用状态机轮询避免多请求冲突直接上SCL比梯形图清晰VAR // Modbus主站实例 MBUS_Master: MBUS_MASTER; // V201参数站号1 V201_Station: USINT : 1; V201_SetFreq: REAL : 50.0; // 设定频率Hz V201_ReadFreq: REAL; // 实际频率Hz V201_CtrlWord: UINT : 1151; // 启动正转V20控制字0x047F V201_StatusWord: UINT; // 状态字运行/故障 V201_Running: BOOL; // 运行反馈 V201_Fault: BOOL; // 故障反馈 // V202参数站号2 V202_Station: USINT : 2; V202_SetFreq: REAL : 40.0; V202_ReadFreq: REAL; V202_CtrlWord: UINT : 1150; // 停止0x047E V202_StatusWord: UINT; V202_Running: BOOL; V202_Fault: BOOL; // 球阀参数站号3 Valve_Station: USINT : 3; Valve_Coil: ARRAY[0..6] OF BOOL; // 7个阀的控制输出 Valve_Feedback: ARRAY[0..6] OF BOOL; // 7个阀的反馈 Valve_Fault: ARRAY[0..6] OF BOOL; // 反馈校验故障 // 轮询状态机 Poll_State: USINT : 1; END_VAR // 主站初始化上电一次就行 IF NOT MBUS_Master.Initialized THEN MBUS_Master.Port : 0; MBUS_Master.BaudRate : 9600; MBUS_Master.Parity : 1; // 偶校验 MBUS_Master.StopBits : 1; MBUS_Master.Timeout : 1000; // 超时1s MBUS_Master.Initialized : TRUE; END_IF; // 状态机轮询 CASE Poll_State OF // 1. 读V201实际频率功能码03偏移地址1→协议40001 1: IF NOT MBUS_Master.Active THEN // 上一个请求完成 MBUS_Master.Station : V201_Station; MBUS_Master.Function : 3; MBUS_Master.Address : 1; // 协议40001偏移1 MBUS_Master.Length : 1; MBUS_Master.DataPtr : ADR(V201_ReadFreq); MBUS_Master.Enable : TRUE; Poll_State : 2; END_IF; // 2. 写V201设定频率功能码06偏移地址1 2: IF MBUS_Master.Done THEN // 读成功 // 注意V20频率分辨率0.01Hz要转成整数50Hz→5000 VAR_TEMP Write_Freq_INT: INT : INT(V201_SetFreq * 100); MBUS_Master.Station : V201_Station; MBUS_Master.Function : 6; MBUS_Master.Address : 1; MBUS_Master.DataPtr : ADR(Write_Freq_INT); MBUS_Master.Enable : TRUE; Poll_State : 3; ELSIF MBUS_Master.Error THEN // 读失败重试 Poll_State : 1; END_IF; // 3. 读V201状态字功能码03偏移地址0→协议40000 3: IF MBUS_Master.Done THEN MBUS_Master.Station : V201_Station; MBUS_Master.Function : 3; MBUS_Master.Address : 0; // 协议40000偏移0 MBUS_Master.Length : 1; MBUS_Master.DataPtr : ADR(V201_StatusWord); MBUS_Master.Enable : TRUE; Poll_State : 4; END_IF; // 4. 处理V202和V201逻辑一致省略重复代码 4: IF MBUS_Master.Done THEN // 读V202频率→写设定→读状态... Poll_State : 5; END_IF; // 5. 写7个球阀控制功能码15偏移地址0→协议00001 5: IF MBUS_Master.Done THEN MBUS_Master.Station : Valve_Station; MBUS_Master.Function : 15; // 写多个线圈 MBUS_Master.Address : 0; MBUS_Master.Length : 7; MBUS_Master.DataPtr : ADR(Valve_Coil); MBUS_Master.Enable : TRUE; Poll_State : 6; END_IF; // 6. 读7个球阀反馈功能码02偏移地址0→协议10001 6: IF MBUS_Master.Done THEN MBUS_Master.Station : Valve_Station; MBUS_Master.Function : 2; // 读多个离散输入 MBUS_Master.Address : 0; MBUS_Master.Length : 7; MBUS_Master.DataPtr : ADR(Valve_Feedback); MBUS_Master.Enable : TRUE; Poll_State : 1; // 循环轮询 ELSIF MBUS_Master.Error THEN Poll_State : 5; // 写失败重试 END_IF; END_CASE; // 状态字解析V20状态字位0运行位2故障 V201_Running : (V201_StatusWord AND 1) 1; V201_Fault : (V201_StatusWord AND 4) 4; // 球阀反馈校验控制≠反馈→故障 FOR i : 0 TO 6 DO Valve_Fault[i] : (Valve_Coil[i] Valve_Feedback[i]); END_FOR;代码里的「坑」分析实际踩过的地址偏移搞反一开始把协议40001直接写进Address结果读不到数据——200SMART的MBUS_MSG是偏移地址协议40001偏移140000偏移0手册里藏在「Modbus协议映射」小节没仔细看真的坑频率没转整数V20的频率寄存器是16位整数0.01Hz分辨率直接写REAL比如50.0会乱码——必须乘100转INT5000读回来再除100转REAL现场调试时变频器半天没反应以为硬件坏了...没做反馈校验球阀控制输出ON但反馈OFF当时没报警导致现场漏液——后来加了Valve_Fault比较客户才说「终于知道之前为啥偶尔出问题了」...实际项目效果轮询周期≈200ms2台V207个阀速度够变频器启停响应500ms频率调节无波动球阀开关反馈实时校验故障立即报警最后碎碎念做工业通信别想当然手册里的「小细节」比如地址偏移、数据类型才是坑王踩过一次下次看到Modbus地址就会先确认「是偏移还是绝对」——这就是经验吧~200smart modbus rtu 轮询 实际项目案例 和2台西门子v20变频器7个阀的轮询变频器写入频率读取频率启停控制运行及故障信号反馈 球阀开关控制开关型号反馈