1. 项目背景与需求分析
去年接手了一个自动化称重项目,需要用到三菱FX3U PLC同时对接8台数字称重仪表。这种多设备通信的场景在食品包装、化工配料等行业很常见,但实际开发时发现市面上完整案例很少。经过两周的调试,最终用ST语言+梯形图混合编程实现了稳定通信,这里把关键技术和踩坑经验记录下来。
称重仪表采用的是RS485接口的Modbus RTU协议,波特率19200。FX3U本体自带一个编程口(RS422),需要通过FX3U-485BD扩展板实现RS485通信。核心需求包括:
- 轮询读取8台仪表的实时重量数据
- 数据异常时触发声光报警
- 重量累计值超过阈值时控制输送带启停
- 通过触摸屏显示各通道状态
关键点:FX3U的通信指令处理周期较长,当设备数超过5台时容易出现响应超时,需要特别优化通信时序。
2. 硬件配置与通信原理
2.1 硬件连接示意图
plaintext复制[FX3U本体] ←→ [FX3U-485BD] ←→ [RS485总线] ←→ [称重仪表1-8]
(终端电阻120Ω) (手拉手连接)
2.2 通信参数设置
| 参数项 | 配置值 | 备注 |
|---|---|---|
| 协议 | Modbus RTU | 仪表固定模式 |
| 波特率 | 19200bps | 与仪表严格一致 |
| 数据位 | 8bit | |
| 停止位 | 1bit | |
| 校验方式 | 偶校验 | 部分仪表要求无校验 |
| 站号分配 | 1-8 | 避免地址冲突 |
实际调试中发现,不同品牌的称重仪表对Modbus的支持程度差异很大:
- 梅特勒仪表:严格遵循标准Modbus协议
- 寺冈仪表:需要启用"连续读取"模式
- 某国产仪表:要求先发送唤醒帧(0xAA)
3. 程序架构设计
3.1 主程序流程图
st复制// 初始化
IF M8002 THEN
RS485_INIT(); // 通信口初始化
TIMER_SET(); // 轮询定时器设置
END_IF;
// 主循环
WHILE TRUE DO
CASE state OF
0: // 空闲状态
IF T0 THEN state := 1; END_IF;
1: // 发送请求帧
SEND_MODBUS(当前站号);
state := 2;
T1 := 50ms; // 超时定时器
2: // 等待响应
IF 收到完整帧 THEN
PARSE_DATA();
state := 0;
站号 := (站号 MOD 8) + 1;
ELSIF T1 THEN
错误计数[站号] += 1;
state := 0;
END_IF;
END_CASE;
END_WHILE;
3.2 关键数据结构
在D寄存器区划分了以下数据区:
- D100-D107:8台仪表的实时重量值(32bit浮点)
- D200-D207:8台仪表的通信状态(0正常 1超时 2校验错误)
- D300-D307:累计重量值(32bit浮点)
- D400:当前轮询站号(1-8)
4. 通信程序实现细节
4.1 Modbus帧构造
采用ST语言编写发送程序,核心代码如下:
st复制FUNCTION SEND_MODBUS : BOOL
VAR_INPUT
slave_id : INT;
END_VAR
VAR
crc : WORD;
END_VAR
// 构造03功能码请求帧
tx_buf[0] := slave_id; // 从站地址
tx_buf[1] := 16#03; // 功能码
tx_buf[2] := 16#00; // 起始地址高字节
tx_buf[3] := 16#64; // 起始地址低字节(重量数据地址)
tx_buf[4] := 16#00; // 寄存器数量高字节
tx_buf[5] := 16#02; // 寄存器数量低字节(2个寄存器=32bit)
crc := CRC16(tx_buf, 6); // CRC校验计算
tx_buf[6] := LOBYTE(crc);
tx_buf[7] := HIBYTE(crc);
// 通过RS指令发送
RS_TX(tx_buf, 8);
4.2 响应处理
在梯形图中用RS指令接收数据,配合中断处理:
ladder复制|-[RS D200 K8 D210 K20]-| // 接收缓冲区设置
|-[DTOH D210 D220 K8]-| // 数据转换
|-[CMP D220 K1]-[MOVP K1 D200]-| // 站号校验
|-[DCMP D222 K0]-[MOVP K0 D201]-| // 错误状态检测
经验:FX3U的RS指令接收超时最小为10ms,对于19200波特率建议设置20ms超时。
5. 性能优化技巧
5.1 通信时序优化
通过实测发现,8台设备轮询周期优化方案:
| 方案 | 周期时间 | 稳定性 |
|---|---|---|
| 顺序轮询 | 1.2s | 偶发超时 |
| 交错轮询 | 0.8s | 稳定 |
| 分组批量读取 | 0.5s | 易丢包 |
最终采用"交错轮询+动态超时"策略:
- 将8台设备分为两组(1,3,5,7)和(2,4,6,8)
- 每组内设备间隔50ms请求
- 根据网络质量动态调整超时时间(30-100ms)
5.2 错误处理机制
在D900-D907设置错误计数器,实现:
- 连续3次通信失败自动跳过该设备
- 错误计数每小时自动清零
- 通过触摸屏可手动重置任意通道
st复制// 在每次通信失败时执行
错误计数[站号] := 错误计数[站号] + 1;
IF 错误计数[站号] >= 3 THEN
报警标志[站号] := TRUE;
跳过站号 := 站号; // 临时跳过该站
END_IF;
6. 典型问题排查记录
6.1 数据跳变问题
现象:个别通道数据偶尔出现±10%跳变
排查过程:
- 用串口监听工具抓取原始数据 → 发现仪表输出稳定
- 检查PLC程序 → 发现浮点转换指令DFLT使用错误
- 修正后增加数据平滑滤波算法
最终解决方案:
st复制// 增加移动平均滤波
滤波缓冲区[站号][滤波指针] := 原始值;
滤波指针 := (滤波指针 + 1) MOD 5;
实时值 := (滤波缓冲区[站号][0] + ... + 滤波缓冲区[站号][4]) / 5;
6.2 通信干扰问题
现象:下午3点后频繁出现CRC错误
最终发现:
- 车间大功率设备启动导致电压波动
- RS485线路与变频器电缆平行走线
改进措施:
- 给PLC和仪表加装隔离电源
- 通信线更换为双绞屏蔽线
- 在总线两端增加120Ω终端电阻
7. 扩展功能实现
7.1 重量累计功能
采用32bit浮点累加,防止溢出:
st复制IF 新数据有效 THEN
累计值[站号] := 累计值[站号] + 实时值[站号];
IF 累计值[站号] >= 预设阈值 THEN
Y10 := ON; // 触发输送带停止
END_IF;
END_IF;
7.2 触摸屏界面设计
在GT Designer3中制作:
- 8个仪表盘分别显示各通道重量
- 通道状态用颜色区分(绿-正常/红-故障)
- 历史趋势图显示最近30分钟数据
- 手动校准按钮(需密码权限)
8. 程序维护建议
- 通信参数保存到D1000开始的寄存器,上电自动读取
- 重要参数设置写保护(用MOVP指令)
- 定期备份程序到SD卡:
ladder复制|-[M8002]-[DMOVP K4 D1000 SDWR]-|
这个项目给我的深刻体会是:工业现场通信必须考虑容错机制。后来我在所有通信程序中都加入了三级错误处理(重试→跳过→报警),系统稳定性显著提升。对于多设备通信,建议先用Modbus Poll工具单独测试每个仪表,确认协议细节后再集成开发。
