我已经开始使用pymodbus读取modbus的值,以便存储在离站点的数据库中。我一直在努力解决一个问题,即响应中收到的值与我在Jace上看到的值不一样。
我也尝试过modbus-tk,并且得到了同样不正确的响应,所以一定是我的Python代码中的什么东西导致了这个问题。从遗留系统(VB.Net)中检索到的数据与我在Jace上看到的输出相同。
这是从modbus检索数据的简单函数。我们在40160和40162有两个寄存器,第一个是读取366,它是正确的,第二个是读取367 (这是我有问题的一个)。我还在其他寄存器中看到了相同的问题,即使我可以在Jace上看到这个值增加了,读取也不会更新。
# -*- coding: utf-8 -*-
from __future__ import division, print_function, unicode_literals
from pymodbus.client.sync import ModbusTcpClient
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
def get_modbus_register_data(ip_address, register, device, count=2):
"""
Retrieve modbus data.
"""
client = ModbusTcpClient(ip_address, timeout=10)
client.connect()
# Read registers
response = client.read_holding_registers(
address=register, # 40162
count=count, # 2
unit=device) # 4
decoder = BinaryPayloadDecoder.fromRegisters(
registers=response.registers,
byteorder=Endian.Big,
wordorder=Endian.Little)
value = decoder.decode_32bit_float()
client.close()
return value # 366 and it should be 367Pymodbus调试日志
DEBUG:pymodbus.transaction:Current transaction state - IDLE
DEBUG:pymodbus.transaction:Running transaction 1
DEBUG:pymodbus.transaction:SEND: 0x0 0x1 0x0 0x0 0x0 0x6 0x4 0x3 0x0 0xa0 0x0 0x2
DEBUG:pymodbus.client.sync:New Transaction state 'SENDING'
DEBUG:pymodbus.transaction:Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
DEBUG:pymodbus.transaction:Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
DEBUG:pymodbus.transaction:RECV: 0x0 0x1 0x0 0x0 0x0 0x7 0x4 0x3 0x4 0x0 0x0 0x43 0xb7
DEBUG:pymodbus.framer.socket_framer:Processing: 0x0 0x1 0x0 0x0 0x0 0x7 0x4 0x3 0x4 0x0 0x0 0x43 0xb7
DEBUG:pymodbus.factory:Factory Response[ReadHoldingRegistersResponse: 3]
DEBUG:pymodbus.transaction:Adding transaction 1
DEBUG:pymodbus.transaction:Getting transaction 1
DEBUG:pymodbus.transaction:Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'


更新
在三居的帮助下,有人向我指出,我使用的偏移量可能是不正确的。确实是这样,通过将偏移量更改1 (40162 - 40001 = 161),我能够从寄存器中检索正确的值,wordorder需要更改为Endian.Big。
更新代码
def get_modbus_register_data(ip_address, register, device, count=2):
"""
Retrieve modbus data.
"""
client = ModbusTcpClient(ip_address, timeout=10)
client.connect()
# Read registers
response = client.read_holding_registers(
address=register, # 40161
count=count, # 2
unit=device) # 4
decoder = BinaryPayloadDecoder.fromRegisters(
registers=response.registers,
byteorder=Endian.Big,
wordorder=Endian.Big)
value = decoder.decode_32bit_float()
client.close()
return value # 367发布于 2018-08-23 04:00:26
使用pymodbus时,您必须注意pymodbus是如何处理偏移量的,偏移量0映射要注册40001,因此40162的偏移量是40162-40001,也就是0xa1,对于40160,偏移量也是0x9f。有关更多信息,请参阅message.ReadHoldingRegistersRequest
还请注意,BinaryPayloadDecoder假定的默认BinaryPayloadDecoder是用于byteorder的Endian.Little和用于wordorder的Endian.Big。如果这些orders不正确,您将得到错误的解码值。
https://stackoverflow.com/questions/51900315
复制相似问题