我试图从 PM5300 仪表获取电压或电流,但总是只有 32768。 代码:
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
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)
UNIT = 0x01
def run_sync_client():
client = ModbusClient(method='rtu', port='COM15', timeout=1, baudrate=19200, parity='E', stopbits=1, bytesize=8)
client.connect()
request = client.read_holding_registers(address=43010, count=2, unit=UNIT)
result = request.registers
print(result)
decoder = BinaryPayloadDecoder.fromRegisters(result, Endian.Little, wordorder=Endian.Big)
#dc2 = (decoder.decode_32bit_float() + 32768 /1000)
#print(dc2)
print(decoder.decode_32bit_float())
client.close()
if __name__ == "__main__":
run_sync_client()
寄存器列表中的地址3010与current匹配(4为保持寄存器)
Endian.Little 的日志和打印:
2020-06-16 20:11:24,349 MainThread DEBUG transaction :115 Current transaction state - IDLE
2020-06-16 20:11:24,349 MainThread DEBUG transaction :120 Running transaction 1
2020-06-16 20:11:24,350 MainThread DEBUG transaction :219 SEND: 0x1 0x3 0xa8 0x2 0x0 0x2 0x45 0xab
2020-06-16 20:11:24,350 MainThread DEBUG sync :75 New Transaction state 'SENDING'
2020-06-16 20:11:24,350 MainThread DEBUG transaction :228 Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
2020-06-16 20:11:24,364 MainThread DEBUG transaction :304 Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
2020-06-16 20:11:24,365 MainThread DEBUG transaction :233 RECV: 0x1 0x3 0x4 0x80 0x0 0x80 0x0 0xb2 0x33
2020-06-16 20:11:24,365 MainThread DEBUG rtu_framer :180 Getting Frame - 0x3 0x4 0x80 0x0 0x80 0x0
2020-06-16 20:11:24,365 MainThread DEBUG factory :266 Factory Response[ReadHoldingRegistersResponse: 3]
2020-06-16 20:11:24,365 MainThread DEBUG rtu_framer :115 Frame advanced, resetting header!!
2020-06-16 20:11:24,366 MainThread DEBUG transaction :383 Adding transaction 1
2020-06-16 20:11:24,366 MainThread DEBUG transaction :394 Getting transaction 1
2020-06-16 20:11:24,366 MainThread DEBUG transaction :193 Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
[32768, 32768]
**2020-06-16 20:11:24,366 MainThread DEBUG payload :312 [32768, 32768]**
2020-06-16 20:11:24,367 MainThread DEBUG payload :368 [b'\x00\x80', b'\x00\x80']
1.1755122874426309e-38
Endian.Big 结果:-4.591774807899561e-41
非常感谢!
您的问题出在您尝试读取的寄存器编号中。在 pymodbus 上,您必须将寄存器指示为绝对地址编号;您不必像以前那样将 40000 添加到 Modbus 映射。
只需更改此行:
request = client.read_holding_registers(address=43010, count=2, unit=UNIT)
至:
request = client.read_holding_registers(address=3010, count=2, unit=UNIT)
根据你的仪表的map,这应该给你当前的平均值。
我现在无法访问仪表,但如果我的笔记是正确的,字节顺序应该是
byteorder=Endian.Big, wordorder=Endian.Little
所以你可能也想在你的代码中摆弄它。
阅读这个问题可能值得你花时间,它有一些代码我认为是针对同一系列的施耐德电气设备。
我认为,如果您得到的不是明显正确的读数,而是错误的地址错误,那会更好,这就是您在这种情况下应该得到的结果。我想他们想保持打开选项以向地图添加更多寄存器并且他们保持它不受限制。
编辑: 正如下面的评论中所讨论的,当前平均值的正确寄存器读取是 3009,因此请求应该是:
request = client.read_holding_registers(address=3009, count=2, unit=UNIT)
有些设备给你的保持寄存器编号从 40001 开始。对于 modbus 和其他的第一个保持寄存器是数字 0,所以如果设备的 Modbus 映射你应该读取寄存器编号 45125,例如,你需要减去 40001 到为
pymodbus获取
address
:
address=45125-40001=5124
你在这里处理的情况更烦人:映射从寄存器 1 开始,所以你需要减去 1.
如您在以下屏幕截图中所见:
ModbusPoll 遵循相同的逻辑:默认情况下,您必须为寄存器 40001 输入 0(或为寄存器 40011 输入 10。如果单击复选框 PLC 地址,则必须输入 1 才能从地址 40001 读取。
是的,我知道,令人困惑!
请注意,上面链接中的问题确实not提到-1偏移量。有些设备(比如你的!)不会让你从“错误”的寄存器中读取。这样,如果您想读取当前平均值(这是一个 FLOAT32,因此占用两个寄存器),您需要从寄存器 3009 开始读取并读取两个寄存器(是的,地图显示 3010,但请记住 -1 偏移量)。相反,如果您从寄存器 3010 开始,您实际上是在尝试读取当前平均值的上半部分和下一个变量(当前不平衡)的下半部分。由于您将无法获得任何有用的数据,因为您正在读取两个混淆的变量,因此您会收到错误消息。同样,这不是最好的错误;它至少应该给你一些提示,让你知道你做错了什么,但是唉!
我有这种格式的解决方案,PM5500 系列使用 ieee 格式来浮动数据。
我想做同样的事情来读取 SE 功率计。但从上面的代码看来,python 3.11.00 的 pymodbus 有一些更新。
如果您不介意,请与更新的 pymodbus 库共享代码?
问候, 维科