[英]Pymodbus read holding registers
I was assigned to perform the task without any documentation.我被指派在没有任何文件的情况下执行任务。 I have a problem with reading data from MODBUS.
我在从 MODBUS 读取数据时遇到问题。 This is the script that I was able to create:
这是我能够创建的脚本:
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.payload import BinaryPayloadBuilder
from pymodbus.client.sync import ModbusTcpClient
client = ModbusTcpClient('X.X.X.X')
connection = client.connect()
request = client.read_holding_registers(12606,2)
result = request.registers
decoder = BinaryPayloadDecoder.fromRegisters(result, Endian.Big, wordorder=Endian.Little)
print "Counter1: %0.2f" % decoder.decode_32bit_float()
request = client.read_holding_registers(12482,2)
result = request.registers
decoder = BinaryPayloadDecoder.fromRegisters(result, Endian.Big, wordorder=Endian.Little)
print "Counter2: %0.2f" % decoder.decode_32bit_float()
client.close()
Everything looks fine, But the data on the counter is different from those in the script for example:一切看起来都很好,但是计数器上的数据与脚本中的数据不同,例如:
Value on the counter : 39558853.30 (value is decimal)
Value from the script: 58853.30
(value is decimal)
Read input registers (HEX): E54D 4765
And this is how the address documentation looks like"这就是地址文档的样子”
P 12458 Q2 4\DW12458 = 1\ND20_Q2\P(F)
Q 12462 Q2 4\DW12462 = 1\ND20_Q2\Q(F)
S 12466 Q2 4\DW12466 = 1\ND20_Q2\S(F)
I 12470 Q2 4\DW12470 = 1\ND20_Q2\I(F)
U 12474 Q2 4\DW12474 = 1\ND20_Q2\U(F)
f 12478 Q2 4\DW12478 = 1\ND20_Q2\f(F)
EP_POB 12482 Q2 4\DW12482 = 1\ND20_Q2\EP_POB(F)
EP_ODD 12486 Q2 4\DW12486 = 1\ND20_Q2\EP_ODD(F)
EQ_IND 12490 Q2 4\DW12490 = 1\ND20_Q2\EQ_IND(F)
EQ_POJ 12494 Q2 4\DW12494 = 1\ND20_Q2\EQ_POJ(F)
THDVL1 12498 Q2 4\DW12498 = 1\ND20_Q2\THDVL1(F)
THDVL2 12502 Q2 4\DW12502 = 1\ND20_Q2\THDVL2(F)
THDVL3 12506 Q2 4\DW12506 = 1\ND20_Q2\THDVL3(F)
THDIL1 12510 Q2 4\DW12510 = 1\ND20_Q2\THDIL1(F)
THDIL2 12514 Q2 4\DW12514 = 1\ND20_Q2\THDIL2(F)
THDIL3 12518 Q2 4\DW12518 = 1\ND20_Q2\THDIL3(F)
UL1 12522 Q2 4\DW12522 = 1\ND20_Q2\UL1(F)
UL2 12526 Q2 4\DW12526 = 1\ND20_Q2\UL2(F)
UL3 12530 Q2 4\DW12530 = 1\ND20_Q2\UL3(F)
IL1 12534 Q2 4\DW12534 = 1\ND20_Q2\IL1(F)
IL2 12538 Q2 4\DW12538 = 1\ND20_Q2\IL2(F)
IL3 12542 Q2 4\DW12542 = 1\ND20_Q2\IL3(F)
PL1 12546 Q2 4\DW12546 = 1\ND20_Q2\PL1(F)
PL2 12550 Q2 4\DW12550 = 1\ND20_Q2\PL2(F)
PL3 12554 Q2 4\DW12554 = 1\ND20_Q2\PL3(F)
QL1 12558 Q2 4\DW12558 = 1\ND20_Q2\QL1(F)
QL2 12562 Q2 4\DW12562 = 1\ND20_Q2\QL2(F)
QL3 12566 Q2 4\DW12566 = 1\ND20_Q2\QL3(F)
S1 12570 Q2 4\DW12570 = 1\ND20_Q2\S1(F)
S2 12574 Q2 4\DW12574 = 1\ND20_Q2\S2(F)
S3 12578 Q2 4\DW12578 = 1\ND20_Q2\S3(F)
I improved your code as the following:我改进了你的代码如下:
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.client.sync import ModbusTcpClient
def validator(instance):
if not instance.isError():
'''.isError() implemented in pymodbus 1.4.0 and above.'''
decoder = BinaryPayloadDecoder.fromRegisters(
instance.registers,
byteorder=Endian.Big, wordorder=Endian.Little
)
return float('{0:.2f}'.format(decoder.decode_32bit_float()))
else:
# Error handling.
print("There isn't the registers, Try again.")
return None
client = ModbusTcpClient('X.X.X.X', port=502) # Specify the port.
connection = client.connect()
if connection:
request = client.read_holding_registers(12606, 2, unit=1) # Specify the unit.
data = validator(request)
print(data)
request = client.read_holding_registers(12482, 2, unit=1) # Specify the unit.
data = validator(request)
print(data)
client.close()
else:
print('Connection lost, Try again')
[ NOTE ]: [注意]:
Do you ensure about desired float32 decode?您是否确保所需的 float32 解码?
byteorder=Endian.Big, wordorder=Endian.Big
byteorder=Endian.Big, wordorder=Endian.Big
byteorder=Endian.Big, wordorder=Endian.Little
byteorder=Endian.Big, wordorder=Endian.Little
byteorder=Endian.Little, wordorder=Endian.Big
byteorder=Endian.Little, wordorder=Endian.Big
byteorder=Endian.Little, wordorder=Endian.Little
byteorder=Endian.Little, wordorder=Endian.Little
Set the unit_ID :设置unit_ID :
unit
is 1
as default ID.unit
是1
作为默认 ID。 [ UPDATE ]: [更新]:
Maybe you need to reading and decoding as the double/float64 value at the 12482
register address, because I think when the desired register in the doc is 12482
and the next register is 12846
, therefore we need to read 4regs ( float64/double ):也许您需要读取和解码为
12482
寄存器地址处的double/float64值,因为我认为当文档中所需的寄存器是12482
并且下一个寄存器是12846
,因此我们需要读取4regs ( float64/double ):
request = client.read_holding_registers(12482, 4, unit=1)
And和
return float('{0:.2f}'.format(decoder.decode_64bit_float()))
I'm pretty sure the value 39558853.30 is to large to store in a IEEE single precision float.我很确定 39558853.30 的值太大了,无法存储在 IEEE 单精度浮点数中。 There are 7.22 digits of precision, that number requires 9 digits.
有 7.22 位精度,该数字需要 9 位。 I did some experimentation with assigning the value to float and double values in C# confirms this.
我做了一些在 C# 中将值分配给 float 和 double 值的实验证实了这一点。
That leads me believe:这让我相信:
1) Like Benyamin Jafari suggested, you need to read four registers. 1) 像 Benyamin Jafari 建议的那样,您需要读取四个寄存器。 However, that number (as a double) in hex is 0x4182dcf62a666666 which doesn't seem to correspond any of the data that you are reading.
但是,十六进制中的该数字(作为双精度数)是 0x4182dcf62a666666,它似乎与您正在阅读的任何数据都不对应。
OR或者
2) It is also possible that it is returned as a UINT32 which must be scaled by (1/100) to give you what the counter is showing. 2) 它也可能作为 UINT32 返回,必须按 (1/100) 缩放才能为您提供计数器显示的内容。 0xE54D4765 = 3847047013 => scaled by 1/100.0 = 38470470.13 which is close to what you are seeing on the counter.
0xE54D4765 = 3847047013 => 按 1/100.0 = 38470470.13 缩放,这与您在柜台上看到的很接近。 In my experience, this is a common practice in Modbus.
根据我的经验,这是 Modbus 中的常见做法。
OR或者
3) They are using some other (non-standard) format to represent the data. 3)他们使用其他(非标准)格式来表示数据。
Can you give us the product name, model, etc?你能给我们产品名称,型号等吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.