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

Can someone help me understand how to use pyModbus to encode string data to a digital display board?

使用: python3, pyModbusTCP, Linux, Raspberry pi4、 Automation Direct 的 ViewMarq

我有一个可以接收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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,..... <all 100 zeros>]

有人可以帮助我了解我是否在朝着正确的方向前进,我接下来应该做什么?我尽量保持简单,感谢您的帮助。

提前致谢。

更新:

根据建议,我更深入地研究了文档。显示文档会在执行完成后立即将这些寄存器返回到 0。从文档 *

c) Word Swap and Byte Swap should be checked assuming the selections are Off (default) in the ViewMarq display. d) Slave Modbus Memory Starting Address is the location of the Command Block within the ViewMarq display (400000+11000 = 411000). e) The Function Code should be set to 16 – Write Multiple Registers.

不得不承认。我不知道如何编写有效负载。我重写了代码并尝试了一种有效载荷构造方法。

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>""[=13=]D") #[=13=]D 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='<' -> 小端 "<I"
    8260=0x2044 -> 0x20=' ' 0x44='D' -> 小端"D "
    12339=0x3033 -> 0x30='0' 0x33='3' -> 小端 "30"

这3个写入寄存器的值对应"<ID 30"

所以每个 Modbus 寄存器似乎对应于 little-endian 字节顺序的缓冲区的 2 个字节。
响应缓冲区很可能是相同的。

编辑 问题编辑后:

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