Raspberry Modbus RS485

Рассмотрим подключение Raspberry Pi 3 Model B к устройству с Modbus RTU. Целью является подружить Raspberry Pi и любое устройство с Modbus.
Купить Raspberry Pi 3 Model B будет получать осуществлять сбор данных, в нашем случае от Modbus реле. Будет использоваться физический канал связи RS-485.
Необходимые этапы разработки:
1. Организация физической связи.
2. Организация программной связи.

1. Проектирование принципиальной схемы:
Реле Modbus RTU выбрано с магазина электроники mkchip.ru. Выбрано было следующего вида реле:

Оно использует питание DC 12В, 4 канала управления, 6 возможных команд:

  • открыть
  • закрыть
  • мгновенно
  • самоблокировка
  • блокировка
  • задержка

Есть возможность использовать как AT команды, так и обычный Modbus RTU. Мы не будем использовать AT команды.
Как известно, Raspberry Pi не поддерживает интерфейс RS-485, однако есть UART. Следует, нам необходимо проектировать схемы, чтобы сделать преобразователь интерфейсов UART <-> RS-485.
В идеальном случае, лучше использовать опторазвязку. Пример простой схемы на рисунке ниже.

Доработанная схема с учетом ньюансов.

Однако, если нет желания тратить время на проектирование схемы, установку и закупку компонентов, имеется и другой способ:
закупить уже готовый преобразователь uart-rs485. Его цена при количестве менее 10 штук получится даже меньше, чем проектирование и макетирование своей платы. преобразователь uart-rs485

Данная плата может использовать питание как от 3.3V, так и от 5V.
Подключение производить пинами:
Raspberry <-> Преобразователь
1 <-> VCC
2 <-> VCC
6 <-> gnd
8 <-> TxD
10 <-> RxD

2. Программная часть
Для того что бы работа с RS-485 линией была возможна, необходимо привести последовательный порт в работоспособное состояние. Для начала необходимо проверить активен ли UART и не настроен ли он как дополнительный терминал. Запустим терминал или подключимся к ОС установленной на RPi по SSH.
Далее, необходимо запустить конфигуратор системы следующей командой:
pi@raspberrypi:~ $ sudo raspi-config
После запуска raspi-config выбрать пункт «Advanced options», а затем ‘Serial’. Вы увидите сообщение такого вида:

По умолчанию утилита предлагает вариант «Yes», меняем его на «No» используя стрелки на клавиатуре и жмем «Enter».
Следующее сообщение говорит о том что порт отключен. Но это нормально.

Жмем «Ok» и после возврата в основное меню конфигуратора при помощи клавиши «Tab» выбираем «Finish» и жмем «Enter». На следующем экране утилита предложит перезагрузить систему. От этого предложения пока нужно отказаться.
В системе имеется два отдельных uart: /dev/ttyAMA0 основанный на PL011 (полноценный контроллер последовательного порта) и /dev/ttyS0 (16550-совместимый miniUART). Начиная с версии Raspberry Pi 3 была сломана совместимость с прошлыми платами. Дело в том, что в Raspberry Pi 3 появился Bluetooth и для него был задействован полноценный аппаратный UART (ttyAMA0), а на контакты разъема расширений был скоммутирован miniUART (ttyS0). Проблема такого решения заключается в нестабильной работе miniUART при высокой загрузке CPU, что меня категорически не устраивает. Решением этой проблемы будет «пересадка» Bluetooth модуля на miniUART, а полноценный контроллер последовательного порта мы сможем использовать для подключения RS-485 адаптера, т.к. от точности и стабильности работы последовательного порта зависит количество потенциальных ошибок при передаче данных по линии связи.

Для этого необходимо внести некоторые изменения в конфигурацию системы добавив в конец файла /boot/config.txt директивы, решающие проблему с UART:
Вы можете использовать редактор vim или nano:
pi@raspberrypi:~# sudo vim /boot/config.txt
pi@raspberrypi:~# sudo nano /boot/config.txt
Вносим изменения:
dtoverlay=pi3-miniuart-bt
enable_uart=1

Для того что бы внесенные изменения вступили в силу необходимо перезагрузиться.
pi@raspberrypi:~# sudo reboot
Обратим внимание на права. Устройство /dev/ttyAMA0 принадлежит пользователю root и группе diaout. Ввиду того что маска прав доступа crw-rw—- более никто не может его использовать. Соответственно, системный пользователь, от имени которого будут выполняться приложения использующие последовательный порт должны быть участниками группы dialout. В моем случае для пользователя «pi».
pi@raspberrypi:~ $ id pi | grep 'dialout'
Результат:
uid=1001(wolf) gid=1001(pi) groups=1001(pi),0(root),4(adm),20(dialout),24(cdrom),27(sudo),29(audio),44(video),46(plugdev),60(games),100(users),101(input),108(netdev),999(spi),998(i2c),997(gpio)
Как видим пользователь «pi» является участником группы 20(dialout). Теперь мы можем использовать аппаратный UART.

Чтобы отправить команду по аппаратному UART мы будем использовать язык python3.
Есть огромный выбор библиотек, которые упрощают разработку управления для данного модуля. Однако, мы будем использовать только библиотеку serial для работы с uart. С функциями modbus вы сможете ознакомиться сайте. В этой статье мы будем использовать только функцию 06 — запись в RTU. Эта функция нам пригодится для изменения значения реле с состояния выключено в состояние включено.

Таким образом, нам необходимо сформировать такую команду для управления. Для открытия реле №1:
01 06 00 01 01 00 D9 9A
Формируем пакет в hex формате:
import serial
data = '\x01\x06\x00\x01\x01\x00\xD9\x9A'
with serial.Serial(name, baudrate, timeout=1) as sr:
sr.write(packet)
packet = sr.read(100)
if packet:
print(packet)

Другие примеры освещены на нашем сайте