pymodbus与XG5000 PLC的Modbus RTU串口通信NUL值问题排查
Modbus RTU串口通信异常排查方案(Python pymodbus + XG5000 PLC)
问题现象
- 向PLC D100寄存器发送
[97,98,99,49,50,51]时,Python报错:Fail to write data Modbus Error: [Input/Output] Modbus Error: [Invalid Message] No response received, expected at least 4 bytes (0 received) - XG5000作为Slave收到的数据含大量NUL等控制字符,但D100~D108寄存器已正确存储ASCII码数据
- 读取D100~D104数据时,Python仍报无响应错误,PLC侧的请求、响应帧均含异常控制字符
排查与解决步骤
1. 硬件链路校验
- 串口接线检查:Modbus RTU需A/B线交叉连接(PLC的A端接Python串口的B端,PLC的B端接Python串口的A端),必须共GND,否则易出现信号干扰导致帧异常
- 链路连通性测试:用串口助手(如SSCOM)发送标准Modbus RTU读写帧,验证PLC是否能正常响应,排除Python代码之外的硬件问题
- 终端电阻添加:若串口线路长度超过10米,在总线两端添加120Ω终端电阻,抑制信号反射
2. 通信参数一致性验证
确保Python端与PLC端的波特率、校验位、数据位、停止位完全一致,XG5000默认参数通常为9600,N,8,1,需核对PLC侧设置:
- Python端代码参数示例:
client = ModbusSerialClient( method='rtu', port='COM3', # Linux下为'/dev/ttyUSB0' baudrate=9600, parity='N', stopbits=1, bytesize=8, timeout=5, # 延长超时时间,避免因响应慢报错 strict=False # 关闭严格CRC校验适配部分PLC的非标准实现 )
3. pymodbus代码细节修正
- 寄存器地址映射确认:XG5000的D寄存器对应Modbus保持寄存器,需查手册确认地址偏移(部分型号D100对应Modbus地址40101,而非直接100)
- 写寄存器方法正确调用:使用
write_registers写入保持寄存器,确保数据长度与寄存器数量匹配:# 假设D100对应Modbus保持寄存器地址100(需根据手册调整) write_result = client.write_registers(address=100, values=[97,98,99,49,50,51], unit=1) if write_result.isError(): print(f"写入错误: {write_result}") - 读寄存器示例:
read_result = client.read_holding_registers(address=100, count=5, unit=1) if not read_result.isError(): print(f"读取数据: {read_result.registers}") else: print(f"读取错误: {read_result}")
4. PLC端Modbus配置检查
- 确认XG5000的Modbus Slave地址(Unit ID)与Python代码中
unit参数一致 - 关闭PLC串口的流控设置(如RTS/CTS),Modbus RTU通常无需硬件流控
- 检查PLC的Modbus功能码权限:确保允许使用06(单寄存器写)、16(多寄存器写)、03(读保持寄存器)功能码
5. 帧完整性排查
用串口抓包工具(如Wireshark+USBPcap)捕获通信帧,对比标准Modbus RTU帧格式:
- 标准帧结构:Slave ID + 功能码 + 数据 + CRC校验(2字节)
- 检查是否存在帧截断、CRC错误、额外控制字符插入,若有则大概率是信号干扰或接线问题
内容的提问来源于stack exchange,提问作者Violet
相关产品推荐
相关产品推荐

