Raspberry Pi RS485 / Uart Modbus - PullRequest
0 голосов
/ 16 мая 2018

Я пытаюсь подключить адаптер RS485 в UART для связи через Modbus на Raspberry Pi. Моя конечная цель - заставить все это работать с приложением Node, но до сих пор мой разработчик работал с Python.

Мое аппаратное соединение выглядит так:

[Modbus-Device] <===> [RS485 chip <==> Raspberry PI GPIO] контакты. RS485 имеет три провода (Transmit, Receive, Direction), к которым они подключены следующим образом

RaspiPi <=> Адаптер

GPIO 14 (8) - Tx <=> Data +

GPIO 15 (10) - Rx <=> - Данные-

GPIO 18 (12) - Направление

RS485 не является типичным 9-контактным адаптером. У меня три провода от чипа. Витая пара, которая служит дифференциальным набором и проводом заземления.

Мне удалось отправить последовательный обмен данными между этим adpater и адаптером USB-RS485, вручную перевернув GPIO18 для отправки / получения. (Код ниже) [1]. Этот код предназначен исключительно для проверки работоспособности адаптера

Я застрял при работе с Modbus на адаптере GPIO. Я пробовал использовать минимальную шину, которая хорошо работает с адаптером USB-RS485, но не работает с адаптером GPIO. Я подозреваю, что это потому, что направляющий штифт не устанавливается.

Идеальным решением было бы найти драйвер RS485 для GPIO на пи, но если не считать этого, я вижу три варианта

1 - Создайте свой собственный драйвер (что-то, с чем я совершенно не знаком) 2 - Каким-то образом получить библиотеку Modbus, чтобы перевернуть вывод GPIO в пространстве ядра 3 - Вручную отправьте сообщения Modbus через последовательный порт и отрегулируйте вывод GPIO в пространстве пользователя. Это кажется самым простым, но и худшим с точки зрения скорости и надежности. Моя попытка кода ниже [2]

Любой совет на эту тему был бы очень признателен. Если кто-то делал что-то подобное раньше и мог бы взвесить мои варианты, это было бы полезно. Я никогда не работал над программным обеспечением на этом уровне, поэтому я не нахожу удивительным, если бы был какой-то очевидный ответ, который я полностью игнорирую.

[1] Этот код связывается с другим адаптером RS485 на Raspberry Pi, подключенном через USB. Это было написано, чтобы доказать, что адаптер GPIO работает, и что я могу контролировать направление с помощью Pin 12 на Raspberry pi

import time
import serial
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT);

ser = serial.Serial(
       port= '/dev/ttyS0',
       baudrate= 57600,
       parity= serial.PARITY_NONE,
       stopbits= serial.STOPBITS_ONE,
       bytesize= serial.EIGHTBITS,
       timeout=1
)



def write_add():
 counter = 0;
 message = 0
 while (True):
    print "writing",
    GPIO.output(12,1) #set high/transmit
    ser.write('%d \n'%(message))
    time.sleep(0.005) #baud for 57600
    #time.sleep(0.5) #baud for 9600
    GPIO.output(12, 0) #pin set to low/receive


    loop_count = 0
    res =""
    while (res == ""):
       res =ser.readline();
       if(res != ""):
         print ""
         print "Read Cycles: "+str(loop_count)+" Total: "+str(counter)
         print res
         message = int(res) + 1
         counter = counter + 1
       elif(loop_count > 10):
         res = "start over"
       else:
         print ".",
         loop_count = loop_count + 1

write_add()

[2] Этот код пытается установить связь с другим устройством Modbus. Мое сообщение отправляется, но ответ - garabge. Я предполагаю, что указатель направления GPIO переворачивается либо слишком рано и отключает сообщение, либо слишком поздно и пропускает часть ответа.

import serial 
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)

ser = serial.Serial(
    port='/dev/ttyS0',
    baudrate = 57600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS,
    timeout=1
)


GPIO.output(12,1) #set high/transmit
ByteStringToSend = "\x00\x03\x01\xb8\x00\x01\x04\x02"
ser.write(ByteStringToSend)
time.sleep(0.005) #baud for 57600
GPIO.output(12, 0) #pin set to low/receive
ReceivedData = ""
while (ReceivedData == ""):
   RecievedData = ser.readline();
   print RecievedData

[3] Рабочий код USB-RS-485. USB-адаптер на Pi, подключенный к устройству Modbus. Этот код читает регистр 440 каждую секунду.

#1/usr/bin/env python
import minimalmodbus
import time

print minimalmodbus._getDiagnosticString()

minimalmodbus.BAUDRATE=57600
minimalmodbus.PARITY='N'
minimalmodbus.BYTESIZE=8
minimalmodbus.STOPBITS=1
minimalmodbus.TIMEOUT=0.1

instrument = minimalmodbus.Instrument('/dev/ttyUSB0', 0)  #port and slave
#instrument.debug = True
while True:
    batterVolt = instrument.read_register(440, 2) #register number, number decimals
    print batterVolt
    time.sleep(1)

Редактировать: Уточненная схема. Edit2: дополнительно уточнена схема и добавлен / отредактирован код

1 Ответ

0 голосов
/ 17 мая 2018

Код в примере 2 действительно работает правильно. Мне просто нужно было отформатировать ответ.

print RecievedData.encode('hex')

Это даст шестнадцатеричную строку в формате ответа Modbus. Как отметил Андрей Дебенжак, time.sleep (x) будет зависеть от скорости передачи и размера сообщения.

Примечание: я нашел эту страницу полезной для расшифровки передачи Modbus.

http://www.modbustools.com/modbus.html

Редактировать: Отправляемая мной строка байтов не должна работать при правильной настройке Modbus. Первый байт x00 является широковещательным байтом и не должен запрашивать ответ. Похоже, что с аппаратным обеспечением, с которым я работаю, что-то происходит. В типичной настройке Modbus вам необходимо указать, с каким устройством вы пытаетесь установить связь. Спасибо Маркер за то, что указал на это.

...