有人可以帮助我了解如何使用pyModbus将字符串数据编码到数字显示板上吗?

问题描述

使用: python3, pyModbusTCP, Linux 树莓派4, ViewMarq by Automation Direct

我有一个数字显示板,可以接收ModBusTCP ascii数据包。以下信息与我要作为测试邮件发送的信息类似。

测试

我是python Modbus的新手,正在尝试使用pyModbus客户端通过端口502将数据发送到其411000的保持寄存器,我相信通过删除4可以将其发送给11000。我已经建立了一个简单的客户端脚本,与董事会沟通,但我必须对消息进行编码才能将其发送到寄存器。在PLC领域,这要简单得多,但这不是一个选择。

使用Windows应用程序填充开发板,如下检测到我的Wireshark modbus数据:

Ethernet II,Src: Dell_63:da:e2 (34:48:ed:63:da:e2),Dst: FACTSEng_06:6c:fc (60:52:d0:06:6c:fc)
Internet Protocol Version 4,Src: 169.254.108.210,Dst: 169.254.108.223
Transmission Control Protocol,Src Port: 55053,Dst Port: 502,Seq: 1,Ack: 1,Len: 85
Modbus/TCP
    Transaction Identifier: 256
    Protocol Identifier: 0
    Length: 79
    Unit Identifier: 1
Modbus
    .001 0000 = Function Code: Write Multiple Registers (16)<nl>
    Reference Number: 10999
    Word Count: 36
    Byte Count: 72
    Register 10999 (UINT16): 18748
    Register 11000 (UINT16): 8260
    Register 11001 (UINT16): 12339
    Register 11002 (UINT16): 15422
    Register 11003 (UINT16): 19523
    Register 11004 (UINT16): 15954
    Register 11005 (UINT16): 22332
    Register 11006 (UINT16): 20041
    Register 11007 (UINT16): 12320
    Register 11008 (UINT16): 12320
    Register 11009 (UINT16): 12832
    Register 11010 (UINT16): 14136
    Register 11011 (UINT16): 13088
    Register 11012 (UINT16): 15921
    Register 11013 (UINT16): 20540
    Register 11014 (UINT16): 21327
    Register 11015 (UINT16): 12320
    Register 11016 (UINT16): 12320
    Register 11017 (UINT16): 15422
    Register 11018 (UINT16): 19020
    Register 11019 (UINT16): 15422
    Register 11020 (UINT16): 19522
    Register 11021 (UINT16): 20000
    Register 11022 (UINT16): 15422
    Register 11023 (UINT16): 21315
    Register 11024 (UINT16): 12320
    Register 11025 (UINT16): 15422
    Register 11026 (UINT16): 21063
    Register 11027 (UINT16): 15950
    Register 11028 (UINT16): 21564
    Register 11029 (UINT16): 21566
    Register 11030 (UINT16): 29541
    Register 11031 (UINT16): 15476
    Register 11032 (UINT16): 21551
    Register 11033 (UINT16): 3390
    Register 11034 (UINT16): 52237

从这里开始,我对下一步该怎么办感到困惑。我试图读取那些寄存器地址,但在那里什么也没看到。

from pyModbusTCP.client import ModbusClient

client = ModbusClient('169.254.108.223',port=502)
client.open()
print(client.read_holding_registers(10999,100))

并收到...

[0,..... <all 100 zeros>]

有人可以帮助我了解我是否朝着正确的方向前进,下一步该怎么做?我正在尝试使其尽可能简单,感谢您的帮助。

谢谢。

更新:

提出建议后,我对文档进行了更深入的研究。显示器的文档中,执行完成后,这些寄存器会立即返回0。来自文档 *

c)假设以下情况,应检查字交换和字节交换: ViewMarq显示中的选择为关闭认)。 d)从站Modbus存储器的起始地址是命令块的位置 在ViewMarq显示中(400000 + 11000 = 411000)。 e)功能码应设置为16 –写多个寄存器。

我必须承认。我不知道如何编写有效载荷。我重写了代码,并尝试了有效负载构建方法

from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.payload import BinaryPayloadBuilder
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
from pymodbus.compat import iteritems
from collections import OrderedDict

client =  ModbusClient('169.254.108.223',port=502)
client.connect()
builder = BinaryPayloadBuilder(byteorder=Endian.Little,wordorder=Endian.Little)
builder.add_string("<ID 30><CLR>""$0D") #$0D is the termination code in the docs
payload = builder.build()

client.write_registers(10999,payload,skip_encode=True,unit=1)

这没有用。它运行了,但是董事会没有更新。建议非常受欢迎。

解决方法

这不是您问题的完整解决方案,仅是下一步的建议。

  • 阅读显示器的文档。

    • 也许命令缓冲区寄存器是只写的?
    • 或者当显示器处理完命令后,您可能会读取全0?
  • 尝试读取响应缓冲区寄存器。

  • 将Wireshark日志中的数据转换为十六进制:
    18748 = 0x493c-> 0x49 = 'I' 0x3c = '<'-> little endian "<I"
    8260 = 0x2044-> 0x20 = ' ' 0x44 = 'D'-> little endian "D "
    12339 = 0x3033-> 0x30 = '0' 0x33 = '3'->小端"30"

这三个写入寄存器的值对应于"<ID 30"等。

因此,每个Modbus寄存器似乎都以小尾数字节顺序对应于缓冲区的2个字节。
响应缓冲区很可能是相同的。

问题编辑完毕后,

编辑

如果您的程序无法运行,请将您的程序发送的数据与Windows应用程序发送的数据进行比较,例如使用Wireshark。