Arduino & Modbus
В предыдущей статье мы соединили открытую платформу домашней автоматизации OpenHAB с контроллером Arduino использовав очень простой, текстовый протокол. Но это решение поставит нас в тупик, если мы захотим подключить наш контроллер к другой системе, что же делать? Modbus — самый известный и распространенный стандарт в промышленной автоматизации, его поддерживают миллионы устройств по всему миру, эти устройства легко интегрируется в единую сеть и стыкуются с огромным количеством готового программного обеспечения. Попробуем использовать его в нашем проекте?
Что нам необходимо знать об этом стандарте? Протокол Modbus использует последовательные линии связи (например, RS232, RS485), а протокол Modbus TCP рассчитан на передачу данных по сетям TCP/IP.Протокол Modbus имеет два режима передачи RTU и ASCII, в режиме ASCII каждый байт передается как два ASCII символа его шестнадцатеричного представления.В сети Modbus есть только один ведущий, который с заданным интервалом опрашивает несколько ведомых устройств, каждое из которых имеет свой уникальный адрес от 1 до 254, адрес 0 широковещательный и на него отвечают все устройства, так как ведущий в сети один у него нет своего адреса.В спецификации Modbus определено два типа данных, один бит и 16 битное слово. Данные организованны в четыре таблицы с 16 битной адресацией ячеек, адресация в таблицах начинается с 0. Для доступа к данным из разных таблиц предназначены отдельные команды.
Discrete Inputs 1 бит только чтение Coils 1 бит чтение и запись Input Registers 16 бит только чтение Holding Registers 16 бит чтение и запись Как нам подключить Modbus устройство к OpenHAB? За это отвечает модуль Modbus Tcp Binding, этот модуль работает в режиме ведущего и обеспечивает подключение нескольких ведомых устройств через последовательный порт или TCP/IP сеть.Для того чтобы связать с ним Arduino нам необходимо реализовать в контроллере ведомое Modbus устройство, воспользуемся для этого библиотекой Modbus-Master-Slave-for-Arduino.Скачаем библиотеку и создадим скетч, скопировав следующий код в редактор программ. При желании можно просто скачать проект с необходимыми файлами из репозитория.
Рассмотрим на примере нашего скетча основные шаги необходимые для работы с этой библиотекой.
Все функции библиотеки реализованы в одном файле ModbusRtu.h.Для взаимодействия с ней, в программе нужно создать объект, задав в его конструкторе Modbus адрес, номер последовательного порта, номер выхода, управляющего передачей (для RS485)
Modbus slave (ID, 0, 0); Затем определить массив регистров Modbus uint16_t au16data[11]; После этого, при старте программы настроить последовательный порт ведомого slave.begin (19200); В основном цикле программы необходимо вызывать функцию обработки Modbus сообщений state = slave.poll (au16data, 11); И после этого можно обработать полученные данные и сохранить необходимые переменные в регистрах Modbus. #include «ModbusRtu.h»
#define ID 1 // адрес ведомого #define btnPin 2 // номер входа, подключенный к кнопке #define stlPin 13 // номер выхода индикатора работы // расположен на плате Arduino #define ledPin 12 // номер выхода светодиода
//Задаём ведомому адрес, последовательный порт, выход управления TX Modbus slave (ID, 0, 0); boolean led; int8_t state = 0; unsigned long tempus;
// массив данных modbus uint16_t au16data[11];
void setup () { // настраиваем входы и выходы io_setup (); // настраиваем последовательный порт ведомого slave.begin (19200); // зажигаем светодиод на 100 мс tempus = millis () + 100; digitalWrite (stlPin, HIGH); }
void io_setup () { digitalWrite (stlPin, HIGH); digitalWrite (ledPin, LOW); pinMode (stlPin, OUTPUT); pinMode (ledPin, OUTPUT); pinMode (btnPin, INPUT); }
void loop () { // обработка сообщений state = slave.poll (au16data, 11); // если получили пакет без ошибок — зажигаем светодиод на 50 мс if (state > 4) { tempus = millis () + 50; digitalWrite (stlPin, HIGH); } if (millis () > tempus) digitalWrite (stlPin, LOW); //обновляем данные в регистрах Modbus и в пользовательской программе io_poll (); }
void io_poll () { //Копируем Coil[1] в Discrete[0] au16data[0] = au16data[1]; //Выводим значение регистра 1.3 на светодиод digitalWrite (ledPin, bitRead (au16data[1], 3)); //Сохраняем состояние кнопки в регистр 0.3 bitWrite (au16data[0], 3, digitalRead (btnPin)); //Копируем Holding[5,6,7] в Input[2,3,4] au16data[2] = au16data[5]; au16data[3] = au16data[6]; au16data[4] = au16data[7]; //Сохраняем в регистры отладочную информацию au16data[8] = slave.getInCnt (); au16data[9] = slave.getOutCnt (); au16data[10] = slave.getErrCnt (); } Стандарт предусматривает отдельную таблицу для каждого типа данных, но особенностью применённой библиотеки является то, что все регистры хранятся в одном массиве, поэтому структура регистров контроллера будет выглядеть следующим образом: Регистр Тип Название Доступ au16data[0] discrete 0: DT0; 1: DI1; 2: DT2; 3: BTN только чтение au16data[1] coil 0: CL0; 1: CL1; 2: CL2; 3: LED чтение и запись au16data[2] input IN0 только чтение au16data[3] input IN1 только чтение au16data[4] input IN2 только чтение au16data[5] holding HLD0 чтение и запись au16data[6] holding HLD1 чтение и запись au16data[7] holding HLD2 чтение и запись Для демонстрации работы с разными регистрами, в процессе работы программы данные из регистра с типом coil будут скопированы в регистр с типом discrete, а из регистров с типом holding в регистры с типом input. Кроме этого состояние кнопки будет сохранено в третий бит регистра au16data[0] (discrete), а значение третьего бита регистра au16data[1] (coil) выведено на светодиод.Доработаем макет контроллера, который был собран для предыдущих экспериментов, переключим светодиод с 13 на 12 вывод. Обычно на плате самого Arduino уже есть светодиод, подключенный к 13 выводу, в нашей программе он станет индикатором статуса работы. Теперь подключим USB кабель к компьютеру, скомпилируем и загрузим программу в контроллер.
Пора приступать к испытаниям. Значительно облегчает работу на этом этапе эмулятор Modbus мастер-устройства, в сети есть несколько хороших, при этом бесплатных программ, вот некоторые из них: www.focus-sw.com/fieldtalk/modpoll.htmlqmodbus.sourceforge.net/www.mikont.com/products/EAT-Console.html
Среди них можно отметить утилиту EAT-Console которая позволяет не только управлять и опрашивать Modbus устройства, но и отображает данные в графическом виде, что очень удобно при отладке работы с различными датчиками, например датчиками влажности, давления и температуры. Перед началом работы с программой и её конфигуратором рекомендую ознакомиться с документацией.
Для установки эмулятора нужно скачать архив и распаковать его в папку C:\arduino\EATConsole, затем открыть страницу загрузки Eclipse, скачать Eclipse IDE for Java Developers и распаковать его в папку C:\arduino\eclipse, после этого скопировать файлы из папки C:\arduino\EATConsole\eclipse\plugins в папку C:\arduino\eclipse\plugins.
Для создания конфигурации необходимо запустить C:\arduino\eclipse\eclipse.exe, создать пустой проект, скопировать в него пустой файл C:\arduino\EATConsole\menu.ptmenu и добавить в редакторе пункты в соответствии со следующей таблицей. Если же вы скачали проект из репозитория, то в нём, в папке EATConsole уже есть подготовленный файл menu.ptmenu.
Type Address Bit Name Point Slave Display Boolean 0 0 DT0 1 Display Boolean 0 1 DT1 1 Display Boolean 0 2 DT2 1 Display Boolean 0 3 BTN 1 Input Boolean 1 0 CL0 1 Input Boolean 1 1 CL1 1 Input Boolean 1 2 CL2 1 Input Boolean 1 3 LED 1 Display Integer 2 IN0 0 1 Display Integer 3 IN1 0 1 Display Integer 4 IN2 0 1 Display Integer 5 HLD0 0 1 Display Integer 6 HLD1 0 1 Display Integer 7 HLD2 0 1 Type — тип элемента меню EATConsole.Address — адрес регистра данных.Bit — номер бита в регистре.Name — название элемента меню.Point — количество десятичных знаков после точки.Slave — Modbus адрес контроллера.
Теперь сохраним и скопируем файл menu.ptmenu в каталог C:\arduino\EATConsole, для этого можно щёлкнуть правой кнопкой мыши на файле прямо в Eclipse, выбрать в контекстном меню пункт «Copy», а затем вставить в проводнике в папку C:\arduino\EATConsole.
После этого запустим C:\arduino\EATConsole\EATConsole.exe, настроим последовательное соединение, выбрав пункт меню Файл\Настройки, в диалоговом окне укажем номер порта, скорость 19200, 8 бит данных, 1 стоповый бит.
*Программа работает с портами с 1 по 8 и если USB переходник Arduino встал на порт с большим номером, придётся открыть диспетчер устройств Windows и изменить номер порта для него.
Когда все настройки будут введены, нажмите кнопку «Установить», сразу после этого программа начнёт опрос устройства и если что-то пошло не так появится сообщение — НЕТ СВЯЗИ. Если же всё было сделано правильно и связь есть в чём можно убедиться по миганию индикатора статуса (светодиод на выводе 13), то пора приступить к испытаниям нашего контроллера.
Попробуем поменять значение в регистрах HLD0…HLD2 и СL0…СL2, при этом должно поменяться значение в соответствующем регистре IN0…IN2 и DT0…DT2, затем нажмём на кнопку макета, при этом должно поменяться значение в поле BTN, щёлкнем по полю LED, при этом должен загореться или потухнуть светодиод.
Что мы получили в результате нашей работы:
1 познакомились с азами протокола Modbus;2 создали скетч, который превращает Arduino в Modbus slave устройство и позволяет читать и записывать несколько Modbus регистров с разными типами данных;3 протестировали обмен с контроллером при помощи эмулятора функций Modbus master устройства, для которого создали конфигурацию соответствующую структуре регистров контроллера.
ВыводыБиблиотека Modbus-Master-Slave-for-Arduino проста в использовании, позволяет создать ведомое Modbus устройство, которое корректно работает с программным эмулятором. Скомпилированный пример занимает немногим более 5 кб памяти программ, так что в контроллере остаётся достаточно места для добавления необходимого функционала.
Стандарт Modbus открыт и популярен, но в нём есть ряд недостатков — в стандарте определено только два типа данных, протокол требует постоянного обмена между ведущим и ведомыми устройствами, конфигурировать систему приходится вручную.
Имея некоторые недостатки, протокол вполне пригоден для использования в контроллере систем домашней автоматизации, особенно если необходима стыковка с различным программным обеспечением.
В следующий раз займёмся подключением контроллера к платформе OpenHAB.