如何在Python中通过pymodbus同时读取多段Modbus RTU寄存器?
解决Modbus多组不连续寄存器同步读取的问题
首先得明确:pymodbus的read_holding_registers方法本身不支持直接传入地址列表和对应字长列表,因为Modbus协议的读保持寄存器功能码(0x03)本身是针对连续地址区间设计的。不过我们有两种靠谱的方案来实现你要的“同步读取”,让各组寄存器的时间戳尽可能一致甚至完全一致:
方案1:批量发送多个读请求(时间戳几乎一致)
利用pymodbus在同一个TCP连接里连续发送多个读请求,因为请求发送间隔极短,加上网关的处理速度,各组寄存器的读取时间差可以忽略不计,几乎等同于同一时间戳。
直接上代码示例:
from pymodbus.client import ModbusTcpClient # 连接你的Modbus-TCP网关 client = ModbusTcpClient("网关IP地址", port=502) client.connect() unit = 1 # 替换成你的Modbus-RTU设备站号 # 准备三个读请求(对应你需要的三组寄存器) req1 = client.read_holding_registers(address=0, count=2, unit=unit) req2 = client.read_holding_registers(address=2, count=2, unit=unit) req3 = client.read_holding_registers(address=206, count=4, unit=unit) # 批量执行请求并收集结果 responses = [req.execute() for req in [req1, req2, req3]] # 解析响应,整理成你想要的格式 results = [] for resp in responses: if not resp.isError(): results.append(resp.registers) else: # 这里可以根据需求添加错误处理逻辑 results.append(f"读取失败: {resp}") # 关闭连接 client.close() print(results) # 输出会是你想要的格式:[[0,26],[0,27],[0,0,0,3008]]
这个方案的优势是不需要读取冗余寄存器,带宽占用小;唯一需要注意的是确认你的网关支持批量处理Modbus请求——市面上主流的RTU/TCP网关都支持这个操作。
方案2:读取超大连续区间后截取(时间戳完全一致)
如果你追求绝对完全一致的时间戳,可以直接读取从起始最小地址(0)到最大地址末端(206+4-1=209)的所有寄存器,然后从返回的寄存器列表里截取你需要的部分。
代码示例:
from pymodbus.client import ModbusTcpClient client = ModbusTcpClient("网关IP地址", port=502) client.connect() unit = 1 # 读取从地址0到209的所有寄存器(共210个) full_resp = client.read_holding_registers(address=0, count=210, unit=unit) results = [] if not full_resp.isError(): # 截取对应区间的寄存器 reg1 = full_resp.registers[0:2] # 地址0,字长2 reg2 = full_resp.registers[2:4] # 地址2,字长2 reg3 = full_resp.registers[206:210] # 地址206,字长4 results = [reg1, reg2, reg3] else: results.append(f"读取失败: {full_resp}") client.close() print(results)
这个方案的优势是真正的单次读取,时间戳完全一致;缺点是会读取大量你不需要的中间寄存器,带宽占用稍高——如果你的设备和网关之间的通信带宽足够,这个方案完全没问题。
两种方案都能解决你当前的时间戳不一致问题,你可以根据实际场景选择。
内容的提问来源于stack exchange,提问作者JCB
相关产品推荐
相关产品推荐

