用Python实现Modbus协议主站:快速对接工业PLC与传感器设备
在工业自动化现场,PLC、变频器、温控仪、智能电表等设备几乎都支持Modbus协议。过去对接这些设备通常使用C/C++或专用组态软件,开发周期长且调试不便。Python凭借pymodbus库,可以在几分钟内搭建一个功能完备的Modbus主站,实现对从站寄存器的读写。本文以Modbus TCP为例,演示从环境搭建到实际数据采集的全流程。
环境准备
安装pymodbus库,它同时支持TCP和RTU(串口)两种传输模式:
pip install pymodbus
基础示例:读取保持寄存器
大多数工业设备将运行参数存放在保持寄存器(Holding Register)中,每个寄存器16位。以下代码连接一个Modbus TCP从站(假设IP为192.168.1.100,端口502),读取地址0开始的10个寄存器:
from pymodbus.client import ModbusTcpClient
client = ModbusTcpClient('192.168.1.100', port=502)
client.connect()
# 读取保持寄存器,起始地址0,数量10
response = client.read_holding_registers(0, 10)
if response.isError():
print("读取失败:", response)
else:
values = response.registers
print("寄存器值:", values)
client.close()
response.registers是一个整数列表,每个元素对应一个寄存器的原始值。若需要转换为实际物理量(如温度=值/10),在取值后做换算即可。
写入数据:控制PLC输出
Modbus主站不仅可以读取,还能写入。例如控制PLC的第0号线圈(DO0)置位:
# 写单个线圈
client.write_coil(0, True) # 置位
client.write_coil(0, False) # 复位
# 写单个保持寄存器
client.write_register(10, 1234)
批量写入使用write_registers或write_coils,适合一次性设置多个参数。
进阶:批量轮询与异常处理
实际产线通常需要周期性采集多个从站的数据。以下代码使用循环和超时机制,实现稳定的批量轮询:
import time
from pymodbus.client import ModbusTcpClient
SLAVES = [
{'ip': '192.168.1.100', 'unit': 1},
{'ip': '192.168.1.101', 'unit': 1},
]
def poll_slave(slave):
client = ModbusTcpClient(slave['ip'], timeout=3)
if not client.connect():
print(f"{slave['ip']} 连接失败")
return None
try:
resp = client.read_holding_registers(0, 10, unit=slave['unit'])
if resp.isError():
print(f"{slave['ip']} 读取错误: {resp}")
return None
return resp.registers
finally:
client.close()
while True:
for slave in SLAVES:
data = poll_slave(slave)
if data:
print(f"{slave['ip']}: {data}")
time.sleep(5)
unit参数对应Modbus从站地址(1-247),用于区分同一串行总线上的不同设备。
Modbus RTU(串口)模式
如果设备通过RS485连接,使用Modbus RTU。只需将客户端替换为ModbusSerialClient:
from pymodbus.client import ModbusSerialClient
client = ModbusSerialClient(method='rtu', port='/dev/ttyUSB0',
baudrate=9600, timeout=1)
client.connect()
resp = client.read_holding_registers(0, 10, unit=1)
client.close()
注意串口参数(波特率、数据位、校验位)必须与从站一致。
实际应用场景
能源监控:读取智能电表的电压、电流、功率寄存器,每小时上报云端。
产线数据采集:轮询PLC中的产量计数器、设备状态,存入数据库。
远程控制:通过上位机Python脚本向变频器写入频率设定值,实现远程调速。
常见问题
连接超时:检查IP和端口,确保防火墙允许502端口。
地址偏移:有些设备寄存器地址从1开始,但Modbus协议中地址从0开始,需根据手册调整。
字节序:32位浮点数可能以大端或小端存储,使用struct模块解析。
写在最后
Python+Modbus的组合让工业数据采集的门槛大幅降低。无论你是想快速验证一个传感器,还是搭建完整的SCADA系统,pymodbus都能提供稳定可靠的通信基础。从简单的读取寄存器到复杂的批量轮询,几十行代码即可完成以往需要C++工程师数天的工作。掌握这套工具,你的嵌入式开发工具箱里又多了一把利器。





