Считывание информации с датчиков в Arduino по протоколу Modbus

Решил написать данную статью с связи с повышенным интересом посетителей нашего сайте к работе с протоколом Modbus в плате Arduino. Ранее на нашем сайте уже рассматривалась работа с протоколом Modbus в платах Arduino (в которых вы можете посмотреть описание данного протокола и работу с Modbus RTU по интерфейсу RS-485 в Arduino):

Но в комментариях к данным статья посетители нашего сайта просили также рассмотреть реализацию команд  0x03 (чтение значений из нескольких регистров хранения, Read Holding Registers) и 0x04 (чтение значений из нескольких регистров ввода, Read Input Registers)  - именно эти команды чаще всего и используются для считывания информации с различных датчиков, подключенных к плате Arduino по протоколу Modbus. Эти вопросы мы и постараемся рассмотреть в данной статье. Считывание информации с датчиков в Arduino по протоколу Modbus: общие принципы

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

Самый обширный материал по использованию протокола Modbus в англоязычном сегменте интернета я нашел на сайте instructables - могу перевести ряд статей с данного сайта если нужно. Но здесь необходимо чтобы вы подсказали мне какие статьи с данного сайта представляют наибольшую ценность для русскоязычных пользователей сети, потому что я сам пока не могу решить какие из них самые интересные/востребованные. Также, если вы найдете другие интересные статьи в интернете на английском языке, касающиеся использования протокола Modbus, то могу рассмотреть вопрос их перевода для нашего сайта (раз уж эта тематика вызвала такой интерес).

Общие принципы проекта

Итак, предположим у нас есть несколько датчиков (температуры, влажности, освещенности, движения и т. д.), которые работают про протоколу Modbus. Ими мы и хотим управлять (считывать с них информацию) с помощью нашей платы Arduino. Эти решения могут применяться для создания так называемого "умного дома", но не только - им можно найти и множество других применений. Достоинствами такого решения является дешевизна, универсальность (поскольку протокол Modbus сейчас весьма популярен) и, если мы используем протокол Modbus по интерфейсу RS-485 - то возможность связать в единую сеть достаточно удаленные друг от друга объекты (до 1200 метров).

Схематично изобразить данную ситуацию для случая управления (считывания информации) платой Arduino одним датчиком по протоколу Modbus RTU через интерфейс RS-485 можно с помощью следующего рисунка (картинка взята с сайта https://forum.arduino.ua/viewtopic.php?id=1081 - там вкратце вы можете прочитать суть описываемой проблемы):

Схема для считывания информации платой Arduino с датчика по протоколу Modbus RS-485

Для считывания информации с датчика в данном случае плата Arduino должна работать в качестве ведущей (Master) в протоколе Modbus RTU, а для считывания информации можно использовать команды 0x03 (чтение Holding Registers) и 0x04 (чтение Input Registers) данного протокола.

На основе анализа информации по данным вопросам в сети интернет для решения поставленной задачи (считывание информации с датчиков в Arduino по протоколу Modbus) лично мне больше всего понравились библиотеки ModbusRtu и ArduinoModbus. Их использование для данной задачи мы и рассмотрим в статье.

Использование библиотеки ModbusRtu для считывания информации с датчиков

Использование библиотеки Modbus RTU мы уже рассматривали на нашем сайте в этой статье, но в ней мы рассмотрели только использование команды 0х10 протокола Modbus, теперь же рассмотрим реализацию с ее помощью команды 0x03 (чтение Holding Registers/регистров хранения).

Пример использования библиотеки ModbusRtu для считывания информации с ведомого (slave) устройства расположен по данному адресу - с его помощью можно передать запрос на считывание массива данных  с ведомого устройства, работающего по протоколу Modbus (кому интересно, пример практического применения использования данного фрагмента кода можно посмотреть здесь - http://forum.amperka.ru/threads/modbus-master.18586/).  В примере рассмотрено использование протокола Modbus по интерфейсам USB или RS232 - для доработки примера под интерфейс RS-485 можно использовать решения из уже упоминавшейся статьи. Если вы хотите опробовать работу примера с помощью эмулятора на компьютере, то в качестве подобного эмулятора автор библиотеки рекомендует использовать программу Modbus slave, которую можно скачать по адресу - https://www.modbusdriver.com/diagslave.html.

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

На мой взгляд, в этом примере все достаточно логично: сначала мы передаем запрос ведомому с помощью функции master.query, а затем, когда значение переменной u8state станет равным 2, мы считываем данные от ведомого с помощью функции master.poll в наш массив au16data. Далее считанные данные из этого массива мы можем использовать по своему усмотрению - передавать их в окно монитора последовательной связи, выполнять какие-либо команды и т.д.

Также для библиотеки ModbusRtu доступен расширенный пример считывания информации с ведомого устройства, в котором кроме команды 0x03 (чтение Holding Registers/регистров хранения) рассмотрено также использование команды 0x06 (запись значения в один регистр хранения, Preset Single Register) - актуально для датчиков/программируемых контроллеров, которые поддерживают такую возможность. Далее приведен код этого примера с переведенными комментариями.

В данном примере мы с помощью команды master.query(telegram[u8query]) в зависмости от значения переменной u8query передаем ведомому устройству запрос либо на считывание информации, либо на запись одиночного регистра.

Использование библиотеки ArduinoModbus для считывания информации с датчиков

Библиотека ArduinoModbus рекомендована официальным сообществом Arduino для работы с протоколом Modbus. Информация с кратким описанием данной библиотеки (на английском языке) и доступных в ней функций находится на данной странице.

Для тех, кто хочет освоить работу с данной библиотекой, можно посмотреть пример ее использования для считывания информации с датчика температуры и влажности по протоколу Modbus RTU с помощью интерфейса RS-485. Тип используемого датчика приведен в комментариях вверху примера. Считывание данных температуры и влажности происходит каждые 5 секунд, после чего считанные данные передаются в окно монитора последовательной связи. Пример рассчитан на использование специального шилда для Arduino для работы по интерфейсу RS-485 (MKR 485 shield), для использования модуля MAX485 TTL to RS485 его необходимо немного переделать в соответствии с решениями из уже упоминавшейся статьи. Далее приведен текст этого примера с переведенными комментариями.

Как видите, текст примера достаточно простой и я думаю он не вызовет у вас затруднений при реализации.

Следующий пример библиотеки ArduinoModbus, который я счел нужным рассмотреть в данной статье (его код доступен на этой странице), демонстрирует почти все возможные операции в протоколе Modbus:

  • writeCoilValues() - запись регистров флагов;
  • readCoilValues() - считывание регистров флагов;
  • readDiscreteInputValues() - считывание дискретных входов;
  • writeHoldingRegisterValues() - запись регистров хранения;
  • readHoldingRegisterValues() - считывание регистров хранения;
  • readInputRegisterValues() - считывание регистров ввода.

Далее приведен код этого примера с переведенными комментариями.

Соотвественно, функция для выполнения команды 0x03 протокола Modbus (чтение значений из нескольких регистров хранения, Read Holding Registers) в представленном фрагменте кода приведена в строках с 128 по 148, а функция для выполнения команды 0x04 (чтение значений из нескольких регистров ввода, Read Input Registers) в представленном фрагменте кода приведена в строках с 150 по 170.

(Проголосуй первым!)
Загрузка...
145 просмотров


Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *