我正在尝试从Modbus设备读取String (Usecase-1)和multiple type of data in one request (Usecase-2)数据,但是它无法正确地解码它。
系统配置:
Python 3.6.5 Pymodbus: 2.1.0 平台: Windows 10 64位
Modbus TCP服务器:
import logging
from pymodbus.constants import Endian
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.payload import BinaryPayloadBuilder
from pymodbus.server.sync import StartTcpServer
class ModbusTCPServer(object):
# initialize your data store:
hrBuilder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Big)
# Usecase-1
hrBuilder.add_string("abcdefghij")
#Uncomment below three lines for usecase-2
# hrBuilder.add_32bit_float(20.5)
# hrBuilder.add_32bit_int(45)
# hrBuilder.add_bits([1, 0, 0, 0, 0, 0, 0, 0])
hrBlock = ModbusSequentialDataBlock(0, hrBuilder.to_registers() * 100)
store = ModbusSlaveContext(hr=hrBlock, ir=hrBlock, di=hrBlock, co=hrBlock)
slaves = {
1: store,
}
context = ModbusServerContext(slaves=slaves, single=False)
# initialize the server information
identity = ModbusDeviceIdentification()
modbusDeviceAddress = "127.0.0.1"
modbusDevicePort = 501
# run the TCP server
# TCP:
print("Modbus TCP Server started.")
StartTcpServer(context, identity=identity, address=(modbusDeviceAddress, modbusDevicePort))
if __name__ == "__main__":
print("Reading application configurations...")
ModbusTCPServer();Modbus TCP客户端:
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.constants import Endian
from pymodbus.compat import iteritems
if __name__ == '__main__':
client = ModbusClient('127.0.0.1', port=501)
client.connect()
result = client.read_holding_registers(0, 5, unit=1)
print("Result : ",result)
decoder = BinaryPayloadDecoder.fromRegisters(result.registers, byteorder=Endian.Big, wordorder=Endian.Big)
# Usecase-1
decoded = {
'name': decoder.decode_string(10).decode(),
}
# Usecase-2
# decoded = {
# 'temp': decoder.decode_32bit_float(),
# 'rpm': decoder.decode_32bit_int(),
# 'status': decoder.decode_bits()
#}
for name, value in iteritems(decoded):
print ("%s\t" % name, value)
client.close()输出Usecase-1:
Result : ReadRegisterResponse (5)
name cdefghijabModbus客户端应该将字符串解码为abcdefghij,但它正在将其解码为cdefghijab。
输出Usecase-2:
Result : ReadRegisterResponse (5)
temp 0.0
rpm 2949376
status [True, False, False, False, False, False, True, False]查看以上读取多个寄存器的输出,输出值与BinaryPayloadBuilder输入中的输出值不匹配。
我尝试过byteorder和wordorder的所有组合,但是,它并不适用于任何情况。
请帮助我理解为什么数据是这样解码的?在编码或解码这些数据时,我是否遗漏了要添加的内容?
FYI:这个解决方案在Pymodbus 1.5.1版本中运行得很好。最近,我升级了版本&它没有像预期的那样工作。
任何帮助都将不胜感激。
发布于 2019-02-16 06:57:37
Tl博士在zero_mode=True中使用ModbusSlaveContext。
如果要映射寄存器,客户端中的[0..n]将读入服务器中的[0..n]。默认情况下,pymodbus服务器将地址[0..n]的寄存器读取映射到其内部存储中的[1..n]。这是为了遵守modbus规范。引用了pymodbus源代码。
#从上下文也可以在zero_mode中初始化,这意味着地址(0-7)的#请求将映射到地址(0-7)。缺省值为# False,它基于规范的4.4节,因此address(0-7) #将映射到(1-8):
因此,在您的情况下,您可以将ModbusSequentialDataBlock的起始地址设置为1,也可以使用zero_mode=True初始化ModbusSlaveContext。
hrBlock = ModbusSequentialDataBlock(1, hrBuilder.to_registers() * 100)
# Or
store = ModbusSlaveContext(hr=hrBlock, ir=hrBlock, di=hrBlock, co=hrBlock, zero_mode=True)https://stackoverflow.com/questions/54709624
复制相似问题