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

Python中Modbus discrete_inputs实时读取异常:外部修改后始终读0

问题分析与修复:Pymodbus读取Discrete Inputs始终为0的问题

核心问题原因

你的代码存在两个致命问题,导致无法读取外部修改的值:

  1. 线程内重复创建新数据块:check_discrete_inputs循环中每次都新建discrete_inputs = ModbusSequentialDataBlock(0, [0] * 100),这是局部变量,完全替换了全局的、与服务器绑定的数据块,每次循环都重置为全0,自然读不到外部修改内容。
  2. 操作对象不匹配:线程读写的是自己新建的空数据块,和Modbus服务器实际使用的数据块无关联,外部修改的数值根本传不到这里。

另外还有位运算优先级错误:beforeLast_value & 0b000000001 & lastValue != 1中!=优先级高于&,会导致判断逻辑失效,需给位运算部分加括号。

修复后的代码

# Import necessary modules
from pymodbus.datastore import ModbusSequentialDataBlock, ModbusSlaveContext, ModbusServerContext
from pymodbus.server.async_io import StartTcpServer
import time
import threading

# Define a ModbusSequentialDataBlock for discrete inputs
discrete_inputs = ModbusSequentialDataBlock(0, [0] * 100)

# Function to continuously check discrete inputs
def check_discrete_inputs():
    global discrete_inputs  # 绑定全局的服务器关联数据块
    while True:
        # 读取服务器实际使用的数据块值
        values = discrete_inputs.getValues(1, 10)
        beforeLast_value = values[-2]  # 倒数第二个位对应的寄存器值
        lastValue = values[-1]         # 最后一位对应的寄存器值

        # 检查倒数第二个位的最低位是否为1
        if beforeLast_value & 0b1:
            # 若最后一位不是1则设置为1
            if lastValue != 1:
                current_values = discrete_inputs.getValues(1, 10)
                current_values[9] = 1
                discrete_inputs.setValues(1, current_values)
                print("Set tenth bit to 1", discrete_inputs.getValues(1, 10))
        else:
            # 若最后一位不是0则重置为0
            if lastValue != 0:
                current_values = discrete_inputs.getValues(1, 10)
                current_values[9] = 0
                discrete_inputs.setValues(1, current_values)
                print("Reset tenth bit to 0", discrete_inputs.getValues(1, 10))

        time.sleep(3)

# Define the Modbus slave context
slave_context = ModbusSlaveContext(
    di=discrete_inputs
)

# Create a thread for the check_discrete_inputs function
thread = threading.Thread(target=check_discrete_inputs)
thread.daemon = True
thread.start()

# Define the Modbus server context
server_context = ModbusServerContext(slaves=slave_context, single=True)

# Start the Modbus TCP server
StartTcpServer(context=server_context, address=("127.0.0.1", 502))

关键修改说明

  • 删除线程内新建数据块的代码,用global声明绑定服务器关联的全局数据块,确保读写的是同一实例。
  • 修正位运算逻辑,简化重复读取的冗余代码,让判断更清晰。
  • 确保线程操作的是Modbus服务器实际使用的数据块,外部修改的数值能实时反映到读取结果中。

验证方式

启动修改后的代码,用外部Modbus工具(如Modbus Poll)修改Discrete Inputs对应位,控制台会输出状态变化,读取值与外部修改一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 19:44:52