Python中Modbus discrete_inputs实时读取异常:外部修改后始终读0
问题分析与修复:Pymodbus读取Discrete Inputs始终为0的问题
核心问题原因
你的代码存在两个致命问题,导致无法读取外部修改的值:
- 线程内重复创建新数据块:
check_discrete_inputs循环中每次都新建discrete_inputs = ModbusSequentialDataBlock(0, [0] * 100),这是局部变量,完全替换了全局的、与服务器绑定的数据块,每次循环都重置为全0,自然读不到外部修改内容。 - 操作对象不匹配:线程读写的是自己新建的空数据块,和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
相关产品推荐
相关产品推荐

