Может ли кто-нибудь помочь мне понять, как использовать pyModbus для кодирования строковых данных на цифровой дисплей?

Использование: python3, pyModbusTCP, Linux, Raspberry pi 4, ViewMarq от Automation Direct

У меня есть цифровой дисплей, который может принимать ascii-пакеты ModBusTCP. Приведенная ниже информация аналогична тому, что я пытаюсь отправить в качестве тестового сообщения.

‹ID 30›‹CLR›‹WIN 0 0 287 31›‹POS 0 0›‹LJ›‹BL N›‹CS 0›‹GRN›‹T›Test‹/T›

Я новичок в python Modbus и пытаюсь использовать клиент pyModbus для отправки данных в его регистр хранения 411000 через порт 502, который, как я полагаю, составляет всего 11000, отбрасывая 4. Я настроил простой клиентский скрипт, который может общаться с board, но я должен закодировать сообщение, чтобы отправить его в реестр. В мире ПЛК это намного проще, но здесь это не вариант.

Используя приложение Windows для заполнения платы, мои данные Modbus Wireshark были обнаружены следующим образом:

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) Перестановка слов и замена байтов должны быть отмечены при условии, что выбранные значения отключены (по умолчанию) на дисплее ViewMarq. d) Начальный адрес подчиненной памяти Modbus — это расположение командного блока на дисплее ViewMarq (400000+11000 = 411000). д) Функциональный код должен быть установлен на 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)

Это не сработало. Он запустился, но плата не обновилась. Предложения очень приветствуются.


person Jason E    schedule 30.09.2020    source источник
comment
Изменение вопроса после того, как ответ был написан, не является хорошей идеей, потому что ответ больше не соответствует вопросу. Лучше напишите новый вопрос. Я добавил примечание к своему ответу.   -  person Bodo    schedule 08.10.2020
comment
Спасибо за информацию Бобо. Я поставил как обновление и привел причину. Я думал, что это нормально. Я надеюсь, что любой, у кого есть похожая проблема, увидит весь масштаб проблемы, как я, автор, удовлетворенный результатом. Кроме того, я думал, что новые повторяющиеся вопросы не одобрялись.   -  person Jason E    schedule 09.10.2020


Ответы (1)


Это не полное решение вашей проблемы, а лишь предложение, что делать дальше.

  • Прочтите документацию дисплея.

    • Maybe the command buffer registers are write only?
    • Или, может быть, вы прочитаете все 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 соответствует 2 байтам буфера в порядке байтов с прямым порядком байтов.
Скорее всего, то же самое и для ответного буфера.

Изменить после редактирования вопроса:

Если ваша программа не работает, сравните данные, отправленные из вашей программы, с данными, отправленными из приложения Windows, например. с помощью Wireshark.

person Bodo    schedule 30.09.2020
comment
Бобо, это было очень полезно. Я отредактировал приведенное выше, чтобы показать мое изменение направления. Это не дало ожидаемого результата, поэтому я создам сервер и посмотрю, как выглядят регистры. - person Jason E; 30.09.2020
comment
Бобо, полезные нагрузки, созданные с помощью pyModbus, не работают должным образом. Кажется, это ошибка. Посмотрев на полезную нагрузку в wireshark, я смог написать свою собственную функцию Little Endian и отправить ее на устройство. Это работало нормально. - person Jason E; 09.10.2020