Arduino & Modbus

в 6:57, , рубрики: arduino, openhab, opensource, scada, smart home, Разработка для интернета вещей, умный дом

В предыдущей статье мы соединили открытую платформу домашней автоматизации 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 кабель к компьютеру, скомпилируем и загрузим программу в контроллер.

Arduino & Modbus - 1

Пора приступать к испытаниям. Значительно облегчает работу на этом этапе эмулятор Modbus мастер-устройства, в сети есть несколько хороших, при этом бесплатных программ, вот некоторые из них:
www.focus-sw.com/fieldtalk/modpoll.html
qmodbus.sourceforge.net/
www.mikont.com/products/EAT-Console.html

Среди них можно отметить утилиту EAT-Console которая позволяет не только управлять и опрашивать Modbus устройства, но и отображает данные в графическом виде, что очень удобно при отладке работы с различными датчиками, например датчиками влажности, давления и температуры. Перед началом работы с программой и её конфигуратором рекомендую ознакомиться с документацией.

Arduino & Modbus - 2

Для установки эмулятора нужно скачать архив и распаковать его в папку C:arduinoEATConsole, затем открыть страницу загрузки Eclipse, скачать Eclipse IDE for Java Developers и распаковать его в папку C:arduinoeclipse, после этого скопировать файлы из папки C:arduinoEATConsoleeclipseplugins в папку C:arduinoeclipseplugins.

Для создания конфигурации необходимо запустить C:arduinoeclipseeclipse.exe, создать пустой проект, скопировать в него пустой файл C:arduinoEATConsolemenu.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 адрес контроллера.

Arduino & Modbus - 3

Теперь сохраним и скопируем файл menu.ptmenu в каталог C:arduinoEATConsole, для этого можно щёлкнуть правой кнопкой мыши на файле прямо в Eclipse, выбрать в контекстном меню пункт “Copy”, а затем вставить в проводнике в папку C:arduinoEATConsole.

После этого запустим C:arduinoEATConsoleEATConsole.exe, настроим последовательное соединение, выбрав пункт меню ФайлНастройки, в диалоговом окне укажем номер порта, скорость 19200, 8 бит данных, 1 стоповый бит.

Arduino & Modbus - 4

*Программа работает с портами с 1 по 8 и если USB переходник Arduino встал на порт с большим номером, придётся открыть диспетчер устройств Windows и изменить номер порта для него.

Когда все настройки будут введены, нажмите кнопку “Установить”, сразу после этого программа начнёт опрос устройства и если что-то пошло не так появится сообщение – НЕТ СВЯЗИ. Если же всё было сделано правильно и связь есть в чём можно убедиться по миганию индикатора статуса (светодиод на выводе 13), то пора приступить к испытаниям нашего контроллера.

Попробуем поменять значение в регистрах HLD0…HLD2 и СL0…СL2, при этом должно поменяться значение в соответствующем регистре IN0..IN2 и DT0..DT2, затем нажмём на кнопку макета, при этом должно поменяться значение в поле BTN, щёлкнем по полю LED, при этом должен загореться или потухнуть светодиод.

Arduino & Modbus - 5

Что мы получили в результате нашей работы:

1 познакомились с азами протокола Modbus;
2 создали скетч, который превращает Arduino в Modbus slave устройство и позволяет читать и записывать несколько Modbus регистров с разными типами данных;
3 протестировали обмен с контроллером при помощи эмулятора функций Modbus master устройства, для которого создали конфигурацию соответствующую структуре регистров контроллера.

Выводы
Библиотека Modbus-Master-Slave-for-Arduino проста в использовании, позволяет создать ведомое Modbus устройство, которое корректно работает с программным эмулятором. Скомпилированный пример занимает немногим более 5кб памяти программ, так что в контроллере остаётся достаточно места для добавления необходимого функционала.

Стандарт Modbus открыт и популярен, но в нём есть ряд недостатков — в стандарте определено только два типа данных,
протокол требует постоянного обмена между ведущим и ведомыми устройствами, конфигурировать систему приходится вручную.

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

В следующий раз займёмся подключением контроллера к платформе OpenHAB.

Автор: Borich

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js