Arduino и MODBUS

ВНИМАНИЕ! Весь материал, представленный в данной статье размещен только в образовательных и ознакомительных целях, автор данной статьи, равно, как и ресурс её разместивший не несут никакой ответственности за последствия, возникшие в результате использования данного материала!

Идея данной статьи «висела в воздухе» довольно давно. В свое время, работая на довольно высокотехнологичном производстве я порой сталкивался с ситуациями, когда из строя выходили элементы системы, с одной стороны не представляющие собой ничего сложного, а с другой без их нормального функционирования вся система оказывалась неработоспособной, и так, как содержание склада всех необходимых компонентов требовало, одновременно специализированных площадей и омертвления довольно весомого бюджета, приходилось простаивать, неся убытки. Вроде, как, это «проблемы начальства», которое не выделило вовремя средства, но не надо забывать, что «мы все в одной лодке» и недовыполнение объемов производства даже по объективным причинам напрямую сказывается на прибыли, а соответственно и на зарплате, ибо «тумбочка» у этого самого «начальства» отнюдь не резиновая. Кроме пресловутого бюджета есть еще временной фактор – время простоя оборудования, съедающее и без того в этой ситуации ограниченные денежные средства, а заказ нового элемента иногда длится несколько недель, а порой и месяцев, это при начале сотрудничества с компанией-поставщиком всё представляется довольно радужно, обещается «в случае чего выслать самолётом из Европы в течении суток»… Реальность, на самом деле более прозаична и после размещения «сверхсрочного заказа» идет выслушивание отговорок, что «один заболел, второй уехал в командировку, деталь зависла на таможне, перепутали на заводе и мы делаем возврат, и.т.д. и.т.п.»… 

Поэтому при знакомстве с Arduino меня порадовало наличие достаточно большого разнообразия датчиков, аналоговые и цифровые входы, ШИМ... в общем все то, что при желании могло выручить не просто эмулируя отсутствующий элемент, но и более-менее успешно его заменяя. Хочу предупредить – я не сторонник замены промышленных элементов «игрушечными», однако иногда ситуация требует. Но вернемся к MODBUS-у. MODBUS - это то самое звено, которое связывает центральный компьютер, управляющий каким-либо оборудованием (либо целой системой, обеспечивающей технологический процесс), со всеми необходимыми датчиками и исполнительными элементами. Если кратко – то это открытый протокол обмена, позволяющий «железякам» общаться на одном языке, естественно, при этом понимая друг друга. Описывать сам протокол не буду, кому интересно – есть файлики в конце статьи, причем довольно толковые. Единственное о чем кратко упомяну – протокол работает по принципу «Ведущий – Ведомый» («Master – Slave»), где Ведущий (один единственный в системе) инициирует запросы и отдает команды, а Ведомые (может быть до 247 устройств в системе, но обычно намного меньше) ждут запрос, обрабатывают его и дают ответ. 

Для практического изучения материала данной статьи нам понадобится: Arduino UNO, купить её проще всего можно здесь:http://arduino-kit.com.ua/product_4079.html или здесь: http://arduino-kit.com.ua/product_463.html, 2 светодиода, 2 резистора на 100 Ом и 1 переменный резистор на 10 КОм. 3 куска провода я не считаю, равно, как и 8-пиновую колодку, потому, что провод найдется практически у любого «на хозяйстве», а при должной аккуратности можно обойтись и без колодки. Из программного обеспечения нам понадобится библиотека SimpleModbusSlave.h и программа, которая могла бы эмулировать Ведущее устройство (MODBUS master) на нашем компьютере. В качестве такой программы (предварительно перепробовав массу всего интересного и не очень) я использую ModbusTerminal 2.0.3.9. это, конечно не предел мечты, но работает стабильно, в общем, для моих целей полностью подходит. Да, и еще одно: 

Пожалуйста, не проводите нижеописанные эксперименты на компьютерах обеспечивающих управление оборудованием или технологическими процессами, это может привести не только к серьезным убыткам, в том числе и в связи с порчей оборудования, но также и к жертвам!!! 

Часть первая, легкая, предварительная.

Для начала соберем нехитрую схему. Схема настолько проста, что предлагаю собрать сразу на весь материал. Длинные ножки светодиодов (аноды) подключаем к 10 и 11 пинам Ардуино, а короткие (катоды) подключаем к контакту GND Ардуино через 100-Омные резисторы. Переменный резистор подключаем согласно схеме на Рисунке 1. 

Схема подключения переменного резистора 
Рисунок 1. Схема подключения переменного резистора.



То, что у меня в итоге получилось хорошо видно на фотографии (Рисунок 2) получилось за 15 минут не торопясь. 

Собранная схема
Рисунок 2. Собранная схема.



Загружаем скетч из файла Modbus_1_diod:
#include <SimpleModbusSlave.h> // Подключаем библиотеку
enum {D10,HOLDING_REGS_SIZE}; // Описываем регистры
unsigned int holdingRegs[HOLDING_REGS_SIZE]; // Определяем массив регистров
void setup(){
modbus_configure(&Serial, 9600, SERIAL_8N2, 1, 2, HOLDING_REGS_SIZE, holdingRegs); // Конфигурируем MODBUS
modbus_update_comms(9600, SERIAL_8N2, 1); // Описываем параметры обмена
pinMode(10, OUTPUT);} // Указываем работу 10-го пина на выход
void loop(){
modbus_update(); // Обновляем данные MODBUS
analogWrite(10, holdingRegs[D10]>>2);} // Записываем полученное значение в 10-й пин.

А теперь устанавливаем программу ModbusTerminal и делаем совершенно не сложные настройки: Указываем скорость обмена, порт, адрес устройства и адрес бита управляющего светодиодом. Думаю более понятно описание настроек можно представить визуально. 




И если все в порядке, то при изменении значения регистра «0» (в пределах от 0 до 255) соответственно будет меняться яркость светодиода. В моем случае к 10-у пину Ардуино подключен светодиод зеленого цвета. 

Часть вторая. Немножко усложним.

А теперь чуть-чуть усложним скетч, при этом вдвое расширим функционал – т.е. будем регулировать свечение сразу двух диодов.
Скетч вырастет совсем немножко – на 2 строчки. Загружаем в Ардуинку скетч из файла Modbus_2_diod:
#include <SimpleModbusSlave.h> // Подключаем библиотеку
enum {D10,D11,HOLDING_REGS_SIZE}; // Описываем регистры
unsigned int holdingRegs[HOLDING_REGS_SIZE];// Определяем массив регистров
void setup(){
modbus_configure(&Serial, 9600, SERIAL_8N2, 1, 13, HOLDING_REGS_SIZE, holdingRegs);// Конфигурируем MODBUS
modbus_update_comms(9600, SERIAL_8N2, 1); // Описываем параметры обмена
pinMode(10, OUTPUT);// Указываем работу 10-го пина на выход
pinMode(11, OUTPUT);}// Указываем работу 11-го пина на выход
void loop(){
modbus_update();// Обновляем данные MODBUS
analogWrite(10, holdingRegs[D10]>>2);// Записываем полученное значение в 10-й пин.
analogWrite(11, holdingRegs[D11]>>2);}// Записываем полученное значение в 11-й пин.
Видно, что скетч «потяжелел» всего на 2 строчки. Настройки программы ModbusTerminal видно на Рисунке 4. 

Запись в 2 регистра – нулевой и первый
Рисунок 4. Запись в 2 регистра – нулевой и первый.



Значение регистра «1» в моем случае отвечает за яркость свечения светодиода красного цвета.

Часть третья, заключительная, но не исчерпывающая.

Протокол MODBUS включает в себя очень много интересного и просто описание всех его функций достойно гораздо большего объема, чем эта статья, не говоря уже о прикладных примерах, я же в своей третьей части ограничусь чтением одного единственного регистра при помощи этого протокола. Напоминаю, что ползунок переменного резистора подключен к контакту А0 нашей Ардуинки. Допишем в скетч еще пару строчек и получится код, который можно загрузить из файлаModbus_2_diod_plus_rezistor:
#include <SimpleModbusSlave.h> // Подключаем библиотеку
enum {D10,D11,RS0,HOLDING_REGS_SIZE};// Описываем регистры
unsigned int holdingRegs[HOLDING_REGS_SIZE];// Определяем массив регистров
void setup(){
modbus_configure(&Serial, 9600, SERIAL_8N2, 1, 13, HOLDING_REGS_SIZE, holdingRegs);// Конфигурируем MODBUS
modbus_update_comms(9600, SERIAL_8N2, 1); // Описываем параметры обмена
pinMode(10, OUTPUT);// Указываем работу 10-го пина на выход
pinMode(11, OUTPUT);}// Указываем работу 11-го пина на выход
void loop(){
modbus_update();// Обновляем данные MODBUS
analogWrite(10, holdingRegs[D10]>>2);// Записываем полученное значение в 10-й пин.
analogWrite(11, holdingRegs[D11]>>2);// Записываем полученное значение в 11-й пин.
holdingRegs[RS0] = analogRead(A0)/4;// Читаем значение АЦП и записываем его в регистр
delay(1);}// Пауза для подавления возможного "дребезга"
Скетч снова «потяжелел» на 2 строчки. Наверное, без последней строчки (паузы в 1 миллисекунду) можно было бы обойтись, но я умышленное её поставил, чтобы погасить возможный «дребезг» переменного резистора. Что получилось видно на Рисунке 5. 

Чтение значения регистра 2
Рисунок 5. Чтение значения регистра 2.



На этом я заканчиваю данную статью, однако в будущем есть планы применить эти скромные наработки для чего-либо более интересного.



Все полезные файлы: 11-all-files.zip 

Обзор подготовил Павел Сергеев