我被指派在没有任何文档的情况下执行任务。我在从MODBUS读取数据时遇到问题。这是我能够创建的脚本:
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()
一切看起来都很好,但计数器上的数据与脚本中的数据不同,例如:
Value on the counter : 39558853.30 (value is decimal)
Value from the script: 58853.30
(value is decimal)
Read input registers (HEX): E54D 4765
这就是地址文档看起来像">
P 12458 Q2 4DW12458 = 1ND20_Q2P(F)
Q 12462 Q2 4DW12462 = 1ND20_Q2Q(F)
S 12466 Q2 4DW12466 = 1ND20_Q2S(F)
I 12470 Q2 4DW12470 = 1ND20_Q2I(F)
U 12474 Q2 4DW12474 = 1ND20_Q2U(F)
f 12478 Q2 4DW12478 = 1ND20_Q2f(F)
EP_POB 12482 Q2 4DW12482 = 1ND20_Q2EP_POB(F)
EP_ODD 12486 Q2 4DW12486 = 1ND20_Q2EP_ODD(F)
EQ_IND 12490 Q2 4DW12490 = 1ND20_Q2EQ_IND(F)
EQ_POJ 12494 Q2 4DW12494 = 1ND20_Q2EQ_POJ(F)
THDVL1 12498 Q2 4DW12498 = 1ND20_Q2THDVL1(F)
THDVL2 12502 Q2 4DW12502 = 1ND20_Q2THDVL2(F)
THDVL3 12506 Q2 4DW12506 = 1ND20_Q2THDVL3(F)
THDIL1 12510 Q2 4DW12510 = 1ND20_Q2THDIL1(F)
THDIL2 12514 Q2 4DW12514 = 1ND20_Q2THDIL2(F)
THDIL3 12518 Q2 4DW12518 = 1ND20_Q2THDIL3(F)
UL1 12522 Q2 4DW12522 = 1ND20_Q2UL1(F)
UL2 12526 Q2 4DW12526 = 1ND20_Q2UL2(F)
UL3 12530 Q2 4DW12530 = 1ND20_Q2UL3(F)
IL1 12534 Q2 4DW12534 = 1ND20_Q2IL1(F)
IL2 12538 Q2 4DW12538 = 1ND20_Q2IL2(F)
IL3 12542 Q2 4DW12542 = 1ND20_Q2IL3(F)
PL1 12546 Q2 4DW12546 = 1ND20_Q2PL1(F)
PL2 12550 Q2 4DW12550 = 1ND20_Q2PL2(F)
PL3 12554 Q2 4DW12554 = 1ND20_Q2PL3(F)
QL1 12558 Q2 4DW12558 = 1ND20_Q2QL1(F)
QL2 12562 Q2 4DW12562 = 1ND20_Q2QL2(F)
QL3 12566 Q2 4DW12566 = 1ND20_Q2QL3(F)
S1 12570 Q2 4DW12570 = 1ND20_Q2S1(F)
S2 12574 Q2 4DW12574 = 1ND20_Q2S2(F)
S3 12578 Q2 4DW12578 = 1ND20_Q2S3(F)
我改进了您的代码如下:
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("The register does not exist, 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')
[注意]:
你确定想要的float32解码吗?
- 浮动AB CD==
byteorder=Endian.Big, wordorder=Endian.Big
- 浮动CD AB==
byteorder=Endian.Big, wordorder=Endian.Little
- 浮动BA DC==
byteorder=Endian.Little, wordorder=Endian.Big
- 浮动直流BA==
byteorder=Endian.Little, wordorder=Endian.Little
设置unit_id:
- 在许多情况下,
unit
默认为1
[更新]:
也许您需要将结果读取并解码为12482
寄存器地址的double/foat64值,因为我认为当文档中的相应寄存器为12482
,下一个寄存器为12846
时,您需要读取4regs--float64/foat64-double:
request = client.read_holding_registers(12482, 4, unit=1)
和
return float('{0:.2f}'.format(decoder.decode_64bit_float()))
我很确定39558853.30的值太大了,无法存储在IEEE单精度浮点中。精度为7.22位,这个数字需要9位。我做了一些实验,将值分配给float,C#中的双值证实了这一点。
这让我相信:
1( 就像Benyamin Jafari建议的那样,你需要读取四个寄存器。然而,十六进制中的数字(作为双精度(是0x4182dcf62a66666,这似乎与您正在读取的任何数据都不对应。
或
2( 它也可能作为UINT32返回,必须按(1/100(缩放才能显示计数器显示的内容。0xE54D4765=3847047013=>按1/100.00=38470470.13缩放,这与您在计数器上看到的内容接近。根据我的经验,这是Modbus中的常见做法。
或
3( 他们正在使用一些其他(非标准(格式来表示数据。
你能告诉我们产品名称、型号等吗?