Ошибка декодирования pymodbus: [Вход / Выход] От удаленного устройства не получен ответ / Невозможно декодировать ответ

У меня были ошибки декодирования на моем Raspberry Pi 3B с использованием pymodbus. Разработана плата, использующая MAX14854G в качестве приемопередатчика RS-485, который подключается к контактам UART RPI3 (8 и 10). В настоящее время тестируется с использованием кабеля RS-485 и симулятора Modbus (Modbus Simulator -> кабель RS485 -> плата RS-485 HAT UART -> Raspberry Pi 3B).

Блок-схема:

введите описание изображения здесь

Дополнительная информация: я использую полную функциональность UART (ttyAMA0), меняя местами ttyS0 и ttyAMA0 и отключая последовательные консоли и Bluetooth:

$ sudo systemctl disable [email protected]
$ sudo systemctl disable [email protected]
$ sudo systemctl disable [email protected]
$ sudo systemctl disable [email protected]

Вот мой код + ошибки + журнал:

In [1]: import pymodbus
   ...: import serial
   ...: import serial.rs485
   ...: from pymodbus.pdu import ModbusRequest
   ...: from pymodbus.client.sync import ModbusSerialClient as ModbusClient
   ...: from pymodbus.transaction import ModbusRtuFramer
   ...: from pymodbus.register_read_message import ReadInputRegistersResponse
   ...: 
   ...: import logging
   ...: logging.basicConfig()
   ...: log = logging.getLogger()
   ...: log.setLevel(logging.DEBUG)

In [2]: msys = ModbusClient(method='rtu',port='/dev/ttyAMA0',stopbits=1,bytesize=8,parity='O',baudrate=9600,timeout=2)

In [3]: msys.inter_char_timeout = 0.05

In [4]: HR2 = msys.read_holding_registers(0,1,unit=1)
DEBUG:pymodbus.transaction:Current transaction state - IDLE
DEBUG:pymodbus.transaction:Running transaction 1
DEBUG:pymodbus.transaction:SEND: 0x1 0x3 0x0 0x0 0x0 0x1 0x84 0xa
DEBUG:pymodbus.client.sync:New Transaction state 'SENDING'
DEBUG:pymodbus.transaction:Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
DEBUG:pymodbus.transaction:Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
DEBUG:pymodbus.transaction:RECV: 0x1 0x3 0x0 0x0 0x0 0x1 0x84
DEBUG:pymodbus.transaction:Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'

In [5]: HR2
Out[5]: 
pymodbus.exceptions.ModbusIOException('No Response received from the remote unit/Unable to decode response',
                                  3)

In [6]: print(HR2)
Modbus Error: [Input/Output] No Response received from the remote unit/Unable to decode response

In [7]: print(HR2.registers)
---------------------------------------------------------------------------
 AttributeError                            Traceback (most recent call last)
<ipython-input-7-02134bc1ab17> in <module>()
----> 1 print(HR2.registers)

AttributeError: 'ModbusIOException' object has no attribute 'registers'

Это проблема декодирования или UART Raspberry Pi 3B настроен неправильно? До отключения последовательных консолей я даже не мог подключиться к устройству. На основе симулятора Modbus есть трафик данных.

введите описание изображения здесь


person cknz    schedule 14.12.2018    source источник


Ответы (2)


Ответ неверный. Для функции 3 (то есть read out words) ответ должен выглядеть как [SlaveNb] [FnNb] [NbBytes] [Data] [CRC16]. Ваш запрос верен, вы запрашиваете 1 word, начиная с адреса 0.

Ответ должен быть 01 03 02 XX XX YY YY, где 02 - количество байтов данных, XX XX - данные, YY YY - CRC16. Вы должны заметить, что ваше поле NbBytes в ответе равно 0, но количество слов должно быть удвоено.

Кстати, ваш ответ похож на эхо запроса. Не ошиблись ли вы с подключением? Вы, наверное, зациклили rx & tx?

person grapes    schedule 17.12.2018
comment
Добавил изображение, это трафик данных из симулятора Modbus. Это похоже на журнал ошибок? - person cknz; 18.12.2018
comment
Ваш скриншот выглядит красиво. Я вижу 002 для длины данных, это означает, что ответ правильный (я не проверял crc, кстати) - person grapes; 18.12.2018
comment
Добавлена ​​блок-схема. Протестировал часть схемы RS-485, и я вижу правильный ответ. Правильные данные не проходят через Raspberry Pi. - person cknz; 20.12.2018

Я не уверен, что понимаю вашу настройку, но мне кажется, что вы пытаетесь читать с шины RS485, когда сигнал включения привода со стороны Pi всегда высокий.

Вам необходимо установить низкий уровень включения привода сразу после завершения отправки запроса Modbus, чтобы вы могли прочитать ответ от шины.

Вам необходимо реализовать аппаратный или программный способ переключения. Взгляните здесь: фон RS485

РЕДАКТИРОВАТЬ: см. эти вопросы и ответы, если вы хотите вместо этого использовать libmodbus, включая переключение строки GPIO, которую вам не хватает в вашем коде (это не Python, но вы можете обернуть это из библиотеки C довольно легко):

Решение с libmodbus

person Marcos G.    schedule 13.05.2019