Pymodbus - считывает входной регистр счетчика энергии через rs485 на Uart Raspberry Pi3 - PullRequest
0 голосов
/ 08 мая 2019

У меня есть один счетчик энергии, и я пытаюсь получить напряжение, значения частоты от метра на Raspberry Pi UART через RS485

Мои соединения для Raspberry Pi и RS485 следующие Rs485 DI - Tx из Raspberry Pi Rs485R0 - Rx Raspberry Pi Rs485 DE / RE -Pin 7 Raspberry Pi

Мой код выглядит следующим образом:

импорт последовательного импорта RPi.GPIO в виде GPIO

из pymodbus.client.синхронизировать импорт ModbusSerialClient как ModbusClient
из pymodbus.register_read_message import ReadInputRegistersResponse

из pymodbus.register_read_message import ReadInputRegistersRequest

импортировать ведение журнала

logg.() log.setLevel (logging.DEBUG)

GPIO.setmode (GPIO.BOARD) GPIO.setup (7, GPIO.OUT, initial = GPIO.LOW)

клиент = ModbusClient (method = 'rtu', port = '/ dev / ttyS0', stopbits = 1, тайм-аут = 0.3, bytesize = 8, четность = 'N', скорость передачи данных = '9600')

connection = client.connect()

печать "Connection "подключение для печати

при 1:

volt=0     

freq=0   

if connection:  

    try:  

        voltage1= client.read_input_registers(0x000,4,unit=0x03)  
        print voltage1

    except:
        print "Error: No message Received"

client.close()

И я получаю вывод следующим образом

DEBUG:pymodbus.transaction:Current transaction state - TRANSACTION_COMPLETE
DEBUG:pymodbus.transaction:Running transaction 4
DEBUG:pymodbus.transaction:SEND: 0x3 0x4 0x0 0x0 0x0 0x4 0xf0 0x2b
DEBUG:pymodbus.framer.rtu_framer:Changing state to IDLE - Last Frame End - None, Current Time stamp - 1557304284.88
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: 0x7b 0x20 0x31 0x20 0x31 0x20 0x32 0x36 0x2e 0x33 0x35 0x20 0x31
DEBUG:pymodbus.transaction:Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
Modbus Error: [Input/Output] No Response received from the remote unit/Unable to decode response
DEBUG:pymodbus.transaction:Current transaction state - TRANSACTION_COMPLETE
DEBUG:pymodbus.transaction:Running transaction 5
DEBUG:pymodbus.transaction:Clearing current Frame : - 0x7b 0x20 0x31 0x20 0x31 0x20 0x32 0x36 0x2e 0x33 0x35 0x20 0x31
DEBUG:pymodbus.framer.rtu_framer:Resetting frame - Current Frame in buffer - 0x7b 0x20 0x31 0x20 0x31 0x20 0x32 0x36 0x2e 0x33 0x35 0x20 0x31
DEBUG:pymodbus.transaction:SEND: 0x3 0x4 0x0 0x0 0x0 0x4 0xf0 0x2b
DEBUG:pymodbus.framer.rtu_framer:Changing state to IDLE - Last Frame End - None, Current Time stamp - 1557304284.98
DEBUG:pymodbus.client.sync:New Transaction state 'SENDING'
WARNING:pymodbus.client.sync:Cleanup recv buffer before send: 0x37 0x2e 0x35 0x35 0x20 0x33
DEBUG:pymodbus.transaction:Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
DEBUG:pymodbus.transaction:Incomplete message received, Expected 13 bytes Recieved 7 bytes !!!!
DEBUG:pymodbus.transaction:Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
DEBUG:pymodbus.transaction:RECV: 0x2e 0x30 0x36 0x20 0x7d 0xd 0xa
DEBUG:pymodbus.transaction:Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
Modbus Error: [Input/Output] No Response received from the remote unit/Unable to decode response

Ответы [ 2 ]

1 голос
/ 13 мая 2019

Если я не ошибаюсь, вы правильно определяете свой вывод GPIO, но никогда не переключаете его высоко и низко.Чтобы получить сигнал DE / ~ RE на вашей микросхеме RS485, вы должны взять высокий уровень GPIO перед записью на шину и низкий уровень сразу после того, как сможете прочитать ответ с вашего счетчика.

К сожалению,Боюсь, что вы пытаетесь сделать это невозможно с pyModbus из коробки.Вы можете посмотреть по этой ссылке:

https://github.com/riptideio/pymodbus/issues/33

Возможно, вы сможете настроить pyModbus и использовать альтернативные функции RTS на вашем Pi (см. Здесь: https://github.com/mholling/rpirtscts),но я не думаю, что этот путь значительно повысит надежность.

Как я уже писал здесь: RS485: неподходящий ioctl для устройства , вам лучше выбрать аппаратное решение.Если вы не можете получить новое оборудование, вы всегда можете попробовать решение с таймером 555. По крайней мере, для временного исправления.

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

РЕДАКТИРОВАТЬ: Решение с использованием libmodbus вместо

Предложение использовать libmodbus было очень успешным. Выполните следующие шагиесли вы хотите попробовать его (протестировано с Raspberry Pi 3B):

1) Клонируйте вилку libmodbus с поддержкой GPIO для вашего Pi:

git clone https://github.com/dhruvvyas90/libmodbus

2) Настройте, скомпилируйте и установите библиотеку libmodbus (те же команды, что и для основного репо):

./autogen.sh && ./configure --prefix=/usr && make && sudo make install

3) Перейдите в папку rpi-test и скомпилируйте пример:

gcc -o test -I/usr/include/modbus test.c -lmodbus

4) Запустите проверку, вам нужно изменить разрешения или выполнить sudo: sudo ./test

То, что вы получаете, на самом деле намного лучше, чем я ожидал, и, вероятно, достаточно хорошо для большинства аппаратных средств Modbus:

Scope capture, blue is TX line (pin number 8 on Pi), yellow is GPIO17 (pin number 11)

Синим цветом вы видитеTX от UART Pi (контакт № 8 на разъеме) и желтым цветом вы получите свой DE / ~ RE (контакт № 11, GPIO17), который следует подключить к вашему чипу RS485.Как вы можете видеть, задержка составляет 0,6 мс от конца кадра данных Modbus до тех пор, пока шина не освободится для ответа ведомого устройства.На скорости, которую я использовал (9600 бит / с), минимальная задержка, необходимая для соответствия спецификации Modbus, составляет около 3 мс (3,5 символа), поэтому она должна подойти для большинства ситуаций.

Единственное, что ожидает, будетдобавить все эти функции GPIO в оболочку pylibmodbus, но это должно быть довольно просто.Я планирую использовать эту библиотеку из Python очень скоро в полевых условиях с моим компьютером Pocket Chip для работы в качестве портативного тестера Modbus, поэтому, если вам или кому-либо еще удастся найти время, я буду более чем рад его протестировать.

Как только у меня будет больше времени, я попробую libmodbus вместе с моим последовательным портом FTDI и сделаю несколько захватов области для сравнения аппаратной и программной сигнализации.

Я забыл упомянуть, чтоединственными изменениями, которые я внес в test.c, были:

Строка 13: #define UART_PORT "/dev/serial0"

Строка 14: #define BAUD_RATE 9600

Первое, только имявстроенный последовательный порт на моем Пи, а второй - скорость, которую я всегда использую для тестирования.

РЕДАКТИРОВАТЬ: Сигнализация между программным и аппаратным обеспечением

Как и было обещано, я протестировал предложенное решение с libmodbus , но вместо встроенного UART на Raspberry Pi я заставил его работать вместе с моим USB-адаптером FTDI, чтобы сравнить время, необходимое для освобождения шины.

*libmodbus* delay 500-600 microseconds*

FTDI TXEN hardware signal, delay 250 microseconds

Вы можете видеть, как TXEN (пурпурная трасса) достигает низкого уровня примерно через 250 микросекунд после стоп-битав то время как GPIO на Pi (синим цветом) занимает более или менее то же самое время, что и при захвате выше (500-600 микросекунд).

Итак, в ожидании более подробного тестирования, мой вывод libmodbus делает большую работу для UART, где у вас нет сигнала включения TX.Я думаю, что для большинства сценариев должна быть надежная связь Modbus.

0 голосов
/ 16 мая 2019

Решение с pylibmodbus

Я написал недостающие функции для библиотеки pylibmodbus .

См. Здесь: https://github.com/marcosgatcomputer/pylibmodbus

Как только вы все установили (ветка libmodbus с поддержкой GPIO и pylibmodbus по ссылке выше), вы можете попробовать тестовый файл:

from pylibmodbus import ModbusRtu


#Define Modbus RTU client (Python 2.x)
client=ModbusRtu(device="/dev/serial0", baud=19200, parity="N", data_bit=8, stop_bit=1)
# For Python 3.x you have to explicitly indicate ASCII enconding
#client=ModbusRtu(device="/dev/serial0".encode("ascii"), baud=19200, parity="N".encode("ascii"), data_bit=8, stop_bit=1)

#Read and set timeout
timeout_sec = client.get_response_timeout()
client.set_response_timeout(timeout_sec+1)

#Connect
client.connect()

SERVER_ID=0
BCM_PIN_DE=17
BCM_PIN_RE=9

#Set Slave ID number
client.set_slave(SERVER_ID)

#Enable RPi GPIO Functions
client.enable_rpi(1)

#Define pin numbers to be used as Read Enable (RE) and Drive Enable (DE)
client.configure_rpi_bcm_pins(BCM_PIN_DE,BCM_PIN_RE)

#Export pin direction (set as outputs)
client.rpi_pin_export_direction()

#Write Modbus registers, 10 starting from 0
client.write_registers(0, [0]*10)

#Read 10 input registers starting from number 0
result=(client.read_registers(0, 10))

#Show register values
print result

#Release pins and close connection
client.rpi_pin_unexport_direction()
client.close()

Этот код работает с Rpi 3B.Для Pocket Chip мне пришлось изменить libmodbus для учета номеров выводов GPIO (исходный код не смог записать файл / sys / class / gpio / export для создания устройства gpio1015).Эта проблема может возникнуть для оборудования с 4-значными числами (если вы видите папки, такие как gpiochipxxxx, в вашем / sys / class / gpio /)

...