使用pymodbus通过Elfin EW11读取Orno WE-517电表Modbus数据失败求助
解决Orno WE-517电表通过Modbus WiFi转换器的数据读取问题
Let's break down what's going wrong here and fix your code step by step.
核心问题分析
从日志和代码来看,你已经成功建立了连接并收到了电表的响应,但代码里的一个错误操作导致了后续的超时错误:
你在调用client.read_holding_registers(28,1)后,额外调用了client.execute(result)——这完全是多余且错误的。read_holding_registers方法本身就会自动发送请求并返回响应结果,把这个结果再传给execute,相当于发送了一次无效的重复请求(看日志里的事务2,发送的是把之前的响应数据当成请求发出去了),这就是最后出现超时错误的原因。
另外,你第一次请求(事务1)其实已经成功拿到了电表数据:日志里的RECV: 0x0 0x1 0x0 0x0 0x0 0x5 0x1 0x3 0x2 0x3e 0xf0中,0x3e 0xf0就是寄存器28返回的16位数据,转换成十进制是16048,你需要对照电表手册解析这个值。
修正后的代码
from pymodbus.client.sync import ModbusTcpClient import logging FORMAT = ('%(asctime)-15s %(threadName)-15s ' '%(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s') logging.basicConfig(format=FORMAT) log = logging.getLogger() log.setLevel(logging.DEBUG) # 连接到Modbus TCP转换器 client = ModbusTcpClient('192.168.0.18', 502) if not client.connect(): print('Error connecting') exit() print('Reading holding register 28...') # 关键修正:指定unit参数(Orno WE-517默认从站ID是1),无需调用execute result = client.read_holding_registers(address=28, count=1, unit=1) # 检查请求是否成功 if not result.isError(): # 获取原始寄存器值 raw_value = result.registers[0] print(f"Raw register value: {raw_value}") # 参考电表手册解析实际值,以电压为例(假设系数为0.1,需根据手册调整) actual_value = raw_value * 0.1 print(f"Actual line voltage (L1-N): {actual_value} V") else: print(f"Error reading register: {result}") client.close()
关键注意事项
- 显式指定unit参数:Modbus TCP必须指定从站单元ID(即电表的地址),Orno WE-517默认值为1,显式传入可以避免潜在的地址匹配问题。
- 不要调用execute:
read_holding_registers已经封装了请求发送和响应接收的逻辑,直接使用它的返回结果即可。 - 对照手册解析数据:不同寄存器的转换系数不同,比如Orno WE-517的寄存器28(0x1C)对应线电压L1-N,系数通常为0.1,你需要严格参考设备的Modbus映射表确认地址和系数。
- 地址偏移确认:注意pymodbus的
address参数是0-based的,如果手册里的寄存器是1-based编号,需要减1后传入。
内容的提问来源于stack exchange,提问作者Bwibwi13
相关产品推荐
相关产品推荐

