You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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参数,要么数据块初始化的长度不对。

排查&解决步骤:

  1. 确认数据块初始化长度:确保创建ModbusSequentialDataBlock时,第二个参数的列表长度是20(比如[False]*20),这样数据块才会包含20个离散输入值。
  2. 读取时指定完整的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()
  1. 检查服务器上下文配置:确保服务器的从站上下文里,di区域的数据块确实是你初始化的那个20长度的实例,没有被其他代码覆盖。

内容的提问来源于stack exchange,提问作者Martin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 16:20:28