首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >pymodbus:问题读取字符串& Modbus设备中的多种类型数据

pymodbus:问题读取字符串& Modbus设备中的多种类型数据
EN

Stack Overflow用户
提问于 2019-02-15 12:41:11
回答 1查看 2.4K关注 0票数 1

我正在尝试从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服务器:

代码语言:javascript
复制
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客户端:

代码语言:javascript
复制
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:

代码语言:javascript
复制
Result :  ReadRegisterResponse (5)
name     cdefghijab

Modbus客户端应该将字符串解码为abcdefghij,但它正在将其解码为cdefghijab

输出Usecase-2:

代码语言:javascript
复制
Result :  ReadRegisterResponse (5)
temp     0.0
rpm  2949376
status   [True, False, False, False, False, False, True, False]

查看以上读取多个寄存器的输出,输出值与BinaryPayloadBuilder输入中的输出值不匹配。

我尝试过byteorderwordorder的所有组合,但是,它并不适用于任何情况。

请帮助我理解为什么数据是这样解码的?在编码或解码这些数据时,我是否遗漏了要添加的内容?

FYI:这个解决方案在Pymodbus 1.5.1版本中运行得很好。最近,我升级了版本&它没有像预期的那样工作。

任何帮助都将不胜感激。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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

代码语言:javascript
复制
    hrBlock = ModbusSequentialDataBlock(1, hrBuilder.to_registers() * 100)
    # Or
    store = ModbusSlaveContext(hr=hrBlock, ir=hrBlock, di=hrBlock, co=hrBlock, zero_mode=True)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54709624

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档