Использование: 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)
Это не сработало. Он запустился, но плата не обновилась. Предложения очень приветствуются.