200smart modbus rtu 轮询 实际项目案例 和2台西门子v20变频器+7个阀的轮询,变频器写入频率,读取频率,启停控制,运行及故障信号反馈 球阀开关控制,开关型号反馈

先明确硬件&协议配置

200SMART用PORT0做Modbus主站,波特率9600、偶校验、停止位1;

  • V20站号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;

代码里的「坑」分析(实际踩过的)

  1. 地址偏移搞反
    一开始把协议40001直接写进Address,结果读不到数据——200SMART的MBUS_MSG偏移地址(协议40001=偏移1,40000=偏移0),手册里藏在「Modbus协议映射」小节,没仔细看真的坑!
  1. 频率没转整数
    V20的频率寄存器是16位整数(0.01Hz分辨率),直接写REAL(比如50.0)会乱码——必须乘100转INT(5000),读回来再除100转REAL,现场调试时变频器半天没反应,以为硬件坏了...
  1. 没做反馈校验
    球阀控制输出ON,但反馈OFF,当时没报警,导致现场漏液——后来加了Valve_Fault比较,客户才说「终于知道之前为啥偶尔出问题了」...

实际项目效果

  • 轮询周期≈200ms(2台V20+7个阀,速度够);
  • 变频器启停响应<500ms,频率调节无波动;
  • 球阀开关反馈实时校验,故障立即报警;

最后碎碎念:做工业通信别想当然,手册里的「小细节」(比如地址偏移、数据类型)才是坑王!踩过一次,下次看到Modbus地址就会先确认「是偏移还是绝对」——这就是经验吧~

200smart modbus rtu 轮询 实际项目案例 和2台西门子v20变频器+7个阀的轮询,变频器写入频率,读取频率,启停控制,运行及故障信号反馈 球阀开关控制,开关型号反馈

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐