Pymodbus调用write_coil为何同时写入Discrete Input寄存器?
解决Pymodbus的两个功能问题
问题1:写入线圈后离散输入寄存器同步变化
你把Discrete Input(di)和Coils(co)绑定到同一个ModbusSequentialDataBlock实例上,这相当于让两个完全独立的Modbus存储区域共享同一块内存——改一个自然会影响另一个。按照Modbus规范,离散输入是只读的输入型寄存器,线圈是可读写的输出型寄存器,必须用独立的数据块存储。
解决方法:分别为di和co创建独立的ModbusSequentialDataBlock实例,再配置到服务器上下文里:
from pymodbus.datastore import ModbusSequentialDataBlock, ModbusSlaveContext, ModbusServerContext # 分别初始化独立的数据块 di_block = ModbusSequentialDataBlock(0, [False]*20) # 离散输入:20个初始值 co_block = ModbusSequentialDataBlock(0, [False]*20) # 线圈:20个初始值 # 创建从站上下文,指定各区域对应的数据块 slave_context = ModbusSlaveContext( di=di_block, co=co_block, # 其他区域(hr、ir)按需配置 ) server_context = ModbusServerContext(slaves=slave_context, single=True)
这样修改线圈后,离散输入的数据就不会被影响了。
问题2:read_discrete_inputs仅返回16个布尔值
出现这个问题大概率是两个原因:要么读取时没指定足够的count参数,要么数据块初始化的长度不对。
排查&解决步骤:
- 确认数据块初始化长度:确保创建
ModbusSequentialDataBlock时,第二个参数的列表长度是20(比如[False]*20),这样数据块才会包含20个离散输入值。 - 读取时指定完整的count:调用
read_discrete_inputs时,必须明确传入count=20,否则会使用默认值(通常是16)。示例代码:
# 客户端读取示例 from pymodbus.client import ModbusTcpClient client = ModbusTcpClient('localhost', port=502) client.connect() # 读取起始地址0开始的20个离散输入 response = client.read_discrete_inputs(address=0, count=20) if not response.isError(): print(response.bits) # 这里会输出20个布尔值 client.close()
- 检查服务器上下文配置:确保服务器的从站上下文里,di区域的数据块确实是你初始化的那个20长度的实例,没有被其他代码覆盖。
内容的提问来源于stack exchange,提问作者Martin
相关产品推荐
相关产品推荐

