Общие сведения:
Блок климатических датчиков RS485 / Modbus - это устройство включающее в себя датчики HTL: влажности (Humidity), температуры (Temperature) и освещённости (Light).
Показания каждого датчика можно получать по протоколу Modbus шины RS485.
Блок HTL можно использовать для контроля климата гидропонной установки. Устройство легко подключается к блоку управления гидропонной установки, сетевым кабелем через разъемы RJ45.
Блок климатических датчиков HTL не обязательно использовать в гидропонных установках, это могут быть иные проекты где требуется контролировать климат используя для получения данных протокол Modbus широко применяемый в промышленности.
В соответствии с протоколом Modbus, к одной шине RS485 можно подключить до 247 блоков климатических датчиков. Адрес устройства (по умолчанию 0x03) назначается программно и хранится в его энергонезависимой памяти. Все устройства на шине должны иметь уникальный адрес.
Видео:
Редактируется...
Спецификация:
- Напряжение питания: от 12 до 24 В постоянного тока (разъем RJ45).
- Ток потребляемый модулем: до 10 мА.
- Интерфейс: RS485 / Modbus.
- Скорость шины: 4800 / 9600 / 19200 / 38400 / 57600 / 115200 бит/с.
- Адрес на шине: устанавливается программно (по умолчанию 0x03).
- Диапазон измерений температуры: от -40 до +125 °С (с шагом 0,1).
- Диапазон измерений влажности воздуха: от 0 до 100 % (с шагом 0,1).
- Диапазон измерений влажности воздуха: от 0 до 655,35 г/м3 (с шагом 0,01).
- Диапазон измерений освещённости: от 0 до 65'535 лк (с шагом 1).
- Рабочая температура: от -25 до +60 °С.
- Габариты: 65 x 45 x 29 мм.
- Вес: ? г.
Подключение:
Важно: Перед подключением устройства к шине RS485 нужно отключить питание.
Так называемое «горячее подключение» может повредить устройство!
Для подключения блока климатических датчиков к шине RS485 используется разъем RJ45.
Назначение выводов разъема RJ45:
- 1: «A» - Линия данных (неинвертирующая).
- 2: «B» - Линия данных (инвертирующая).
- 3: «NC» - Не используется.
- 4: «PWR» - Вывод питания от +12 до +24В.
- 5: «PWR» - Вывод питания от +12 до +24В.
- 6: «NC» - Не используется.
- 7: «GND» - Общий вывод питания.
- 8: «GND» - Общий вывод питания.
- HL-1: «BLINK» - Индикатор включения (мигает если подано питание).
- HL-2: «DATA» - Индикатор получения запроса и обнаружения устройства.
Назначение индикаторов разъёма RJ45:
- HL-1 «BLINK» Индикатор включения:
- Индикатор коротко мигает раз в две секунды -
значит устройство работает, но не получило ни 1 запроса с подачи питания. - Индикатор медленно мигает раз в секунду -
значит устройство работает, но последний запрос принят более 10 сек. назад. - Индикатор часто мигает пять раз в секунду -
значит устройство работает и последний запрос принят менее 10 сек. назад. - HL-2 «DATA» Индикатор получения запроса и обнаружения устройства:
- Индикатор включается при получении запросов, что позволяет визуально отследить их поступление.
- Устройству можно отправить команду на постоянное свечение индикатора, что позволит визуально найти устройство с известным адресом среди одинаковых устройств на шине.
Питание:
Входное напряжение питания модуля от 12 до 24В постоянного тока подаётся через разъем PJ45. Модуль HTL сохраняет работоспособность при снижении питания до 5В. Не подавайте питание выше 24В.
Подробнее о блоке HTL:
Блок климатический (температура, влажность, освещённость) RS485 / Modbus построен на базе микроконтроллера STM32G030F4 и конвертера SN65HVD3082EDR с цепями защиты шины RS485 и встроенным терминатором, который можно отключать переключателем на плате. В устройстве присутствуют: импульсный DC-DC преобразователь, линейные преобразователи и датчики: SHT20 и LTR553. На корпусе блока есть фиксатор позволяющий устанавливать его на DIN-рейку.
Блок позволяет:
- Менять свой адрес на шине.
- Менять тип протокола Modbus (RTU/ASCII).
- Менять скорость передачи данных.
- Сохранять одно двухбайтное слово в энергонезависимую память и читать его.
- Читать напряжение питания поступившее с разъема RJ45.
- Управлять светодиодом обнаружения устройства на разъеме RJ45.
- Читать показания датчиков:
- Температура воздуха в °С.
- Относительная влажность воздуха в %.
- Абсолютная влажность воздуха в г/м3.
- Освещённость в люксах.
- Задавать и узнавать период обновления показаний датчиков.
Для работы с блоком климатических датчиков RS485 / Modbus предлагаем воспользоваться разработанными нами библиотеками iarduino_Modbus и iarduino_MB_HTL. Первая позволяет работать по протоколу Modbus на шине RS485, а вторая предназначена для работы с блоком климатических датчиков.
Подробнее про установку библиотек читайте в нашей инструкции.
Примеры:
- Предложенные библиотеки содержат больше примеров, доступных из меню Arduino IDE:
- Файл / Примеры / iarduino Modbus (протокол) / ModbusClient / HardwareSerial.
- Файл / Примеры / iarduino Modbus (протокол) / ModbusClient / SoftwareSerial.
- Файл / Примеры / iarduino Modbus HTL (модуль климатических датчиков) / HardwareSerial.
- Файл / Примеры / iarduino Modbus HTL (модуль климатических датчиков) / SoftwareSerial.
Так как у большинства плат Arduino и ESP нет шины RS485, то библиотека iarduino_Modbus использует аппаратную или программную шину UART, сигналы которой преобразуются в сигналы шины RS485 при помощи конвертирующего модуля UART-RS485, например, на базе микросхемы MAX485. Конвертер подключается к выводам TX и RX шины UART, а так же назначается вывод разрешающий работу передатчика DE.
Для более удобного подключения, можно воспользоваться Trema конвертером UART-RS485, как показано на картинке ниже. У этого конвертера имеется порт RJ-45, который позволяет подключать датчик при помощи стандартного 8-жильного кабеля витой пары патч-корд.
Обратите внимание на то, что вывод TX конвертера подключается к выводу RX Arduino, вывод RX конвертера к выводу TX Arduino, вывод разрешения работы передатчика D (DE) подключается к любому выводу Arduino (назначается в скетче).
В примерах ниже, для создания шины RS485, будет использована аппаратная шина UART1 (класс Serial1). Если у вашей платы Arduino нет свободных аппаратных шин UART, используйте программную шину UART при помощи входящей в состав Arduino IDE библиотеки SoftwareSerial.
Смена адреса блока на шине:
Пример меняет текущий адрес блока (nowAddress) на новый (newAddress) и сохраняет его в энергонезависимую память блока, значит адрес сохранится и после отключения питания.
uint8_t nowAddress = 3; // Текущий адрес блока климатических датчиков ( 1 - 247 ). uint8_t newAddress = 10; // Новый адрес блока климатических датчиков ( 1 - 247 ). uint8_t pinDE = 2; // Вывод DE конвертера UART-RS485. // #include <iarduino_Modbus.h> // Подключаем библиотеку для работы по протоколу Modbus. #include <iarduino_MB_HTL.h> // Подключаем библиотеку для работы с блоком климатических датчиков. // ModbusClient modbus(Serial1, pinDE); // Создаём объект для работы по протоколу Modbus указав шину UART-RS485 и вывод DE. iarduino_MB_HTL sensor(modbus); // Создаём объект для работы с климатическими датчиками указав объект протокола Modbus. // void setup(){ // int f; // Serial.begin(9600); while(!Serial); // Инициируем передачу данных в монитор последовательного порта, указав его скорость. Serial1.begin(9600); while(!Serial1); // Инициируем работу с шиной UART подключённой к конвертеру UART-RS485. modbus.begin(); // Инициируем работу по протоколу Modbus. // modbus.setTimeout(10); // Указываем максимальное время ожидания ответа по протоколу Modbus. // modbus.setDelay(4); // Указываем минимальный интервал между отправляемыми сообщениями по протоколу Modbus. // modbus.setTypeMB( MODBUS_RTU ); // Указываем тип протокола Modbus: MODBUS_RTU (по умолчанию), или MODBUS_ASCII. Serial.print("Инициализация "); // f = sensor.begin(nowAddress); // Инициируем работу с блоком климатических датчиков, указав его текущий адрес nowAddress. if(f){ Serial.println("OK"); } // Если f=true значит инициализация пройдена успешно. else { Serial.println("ERR"); } // Если f=false значит инициализация не пройдена. Serial.print("Смена адреса "); // f = sensor.changeID(newAddress); // Меняем адрес блока климатических датчиков на новый newAddress. if(f){ Serial.println("OK"); } // Если f=true значит адрес изменён. else { Serial.println("ERR"); } // Если f=false значит адрес не изменён. Serial.print("Текущий адрес "); // Serial.println(sensor.getID()); // Выводим текущий адрес блока климатических датчиков. Serial.print("Версия прошивки "); // Serial.println(sensor.getVersion()); // Выводим версию прошивки блока климатических датчиков. } // // void loop(){ // Визуально показываем у какого устройства был изменён адрес. sensor.setIDLED(true ); delay(1000); // Включаем светодиодом обнаружения устройства (на разъёме RJ45). sensor.setIDLED(false); delay(1000); // Выключаем светодиодом обнаружения устройства (на разъёме RJ45). } //
Пример будет более коротким, если убрать вывод данных в монитор последовательного порта и обращаться к функциям sensor.begin()
, sensor.changeID()
без проверки f
. Если при обращении к функции sensor.begin()
не указывать текущий адрес блока nowAddress
, то он будет найден автоматически, но это займёт некоторое время.
Чтение показаний с датчиков блока:
Пример выводит показания всех датчиков с проверкой корректности чтения.
uint8_t pinDE = 2; // Вывод DE конвертера UART-RS485. // #include <iarduino_Modbus.h> // Подключаем библиотеку для работы по протоколу Modbus. #include <iarduino_MB_HTL.h> // Подключаем библиотеку для работы с блоком климатических датчиков. // ModbusClient modbus(Serial1, pinDE); // Создаём объект для работы по протоколу Modbus указав шину UART-RS485 и вывод DE. iarduino_MB_HTL sensor(modbus); // Создаём объект для работы с климатическими датчиками указав объект протокола Modbus. // void setup(){ // Serial.begin(9600); while(!Serial); // Инициируем передачу данных в монитор последовательного порта, указав его скорость. Serial1.begin(9600); while(!Serial1); // Инициируем работу с шиной UART подключённой к конвертеру UART-RS485. modbus.begin(); // Инициируем работу по протоколу Modbus. // modbus.setTimeout(10); // Указываем максимальное время ожидания ответа по протоколу Modbus. // modbus.setDelay(4); // Указываем минимальный интервал между отправляемыми сообщениями по протоколу Modbus. // modbus.setTypeMB( MODBUS_RTU ); // Указываем тип протокола Modbus: MODBUS_RTU (по умолчанию), или MODBUS_ASCII. int f = sensor.begin(3); // Инициируем работу с блоком климатических датчиков, указав его адрес. Если адрес не указан sensor.begin(), то он будет найден, но это займёт некоторое время. if( !f ){ // Если функция begin() вернула false, значит блок климатических датчиков с адресом 3 не найден. Serial.print("Блок не найден"); // while(1); // Запрещаем дальнейшее выполнение скетча. } // // sensor.setPeriod( SENSOR_SHT, 0.5f ); // Указываем модулю обновлять данные датчика влажности и температуры каждые 0.5 секунд. // sensor.setPeriod( SENSOR_LTR, 1.0f ); // Указываем модулю обновлять данные датчика освещённости каждую секунду. } // // void loop(){ // float i; // // Читаем температуру: // i=sensor.getTEM(); // Serial.print("TEM=" ); // Читаем данные. if( i< -40 ){ Serial.print("ERROR"); } // Сообщаем об ошибке чтения. else { Serial.print( i , 1 ); } // Выводим данные с одном знаком после запятой. Serial.print("°C, " ); // Выводим единицы измерения. // Читаем относительную влажность: // i=sensor.getHUM(); // Serial.print("HUM=" ); // Читаем данные. if( i< 0 ) { Serial.print("ERROR"); } // Сообщаем об ошибке чтения. else { Serial.print( i , 1 ); } // Выводим данные с одном знаком после запятой. Serial.print("%, " ); // Выводим единицы измерения. // Читаем абсолютную влажность: // i=sensor.getHUMA(); // Serial.print("HUM=" ); // Читаем данные. if( i< 0 ) { Serial.print("ERROR"); } // Сообщаем об ошибке чтения. else { Serial.print( i , 2 ); } // Выводим данные с двумя знаками после запятой. Serial.print("г/м3, "); // Выводим единицы измерения. // Читаем освещённость: // i=sensor.getLUX(); // Serial.print("LUX=" ); // Читаем данные. if( i< 0 ) { Serial.print("ERROR"); } // Сообщаем об ошибке чтения. else { Serial.print( i , 0 ); } // Выводим данные целочисленно. Serial.println("лк."); // Выводим единицы измерения. // Задержка (не обязательно): // delay(1000); // } //
Этот пример кажется большим, но если убрать все проверки и некоторые комментарии, то код будет более компактным.
Пример без проверок:
uint8_t pinDE = 2; // Вывод DE конвертера UART-RS485. // #include <iarduino_Modbus.h> // Подключаем библиотеку для работы по протоколу Modbus. #include <iarduino_MB_HTL.h> // Подключаем библиотеку для работы с блоком климатических датчиков. // ModbusClient modbus(Serial1, pinDE); // Создаём объект для работы по протоколу Modbus указав шину UART-RS485 и вывод DE. iarduino_MB_HTL sensor(modbus); // Создаём объект для работы с климатическими датчиками указав объект протокола Modbus. // void setup(){ // Serial.begin(9600); while(!Serial); // Инициируем передачу данных в монитор последовательного порта, указав его скорость. Serial1.begin(9600); while(!Serial1); // Инициируем работу с шиной UART подключённой к конвертеру UART-RS485. modbus.begin(); // Инициируем работу по протоколу Modbus. sensor.begin(3); // Инициируем работу с блоком климатических датчиков, указав его адрес. Если адрес не указан sensor.begin(), то он будет найден, но это займёт некоторое время. } // // void loop(){ // float i; // i=sensor.getTEM(); // Читаем температуру. Serial.print((String)"TEM="+i+"°C, " ); // i=sensor.getHUM(); // Читаем относительную влажность. Serial.print((String)"HUM="+i+"%, " ); // i=sensor.getHUMA(); // Читаем абсолютную влажность. Serial.print((String)"HUM="+i+"г/м3, ");// i=sensor.getLUX(); // Читаем освещённость. Serial.println((String)"LUX="+i+"лк."); // delay(1000); // } //
Несмотря на то, что код без проверок кажется более понятным, рекомендуется выполнять проверки, так как это помогает отслеживать ошибки в процессе работы устройства.
Описание функций библиотеки:
В данном разделе описаны функции библиотеки iarduino_MB_HTL для работы с блоком климатических датчиков RS485 / Modbus. Эта библиотека работает совместно с библиотекой iarduino_Modbus, описание функций которой доступно по ссылке Wiki - Работа с протоколом Modbus RTU/ASCI по шине RS485.
Подключение библиотек:
В примерах вход DE конвертера UART-RS485 подключён к выводу D2 Arduino. Вместо вывода D2 можно использовать любой выход Arduino, номер выхода указывается при создании объекта для работы по протоколу Modbus.
- Если используется аппаратная шина UART:
#include <iarduino_Modbus.h> // Подключаем библиотеку для работы по протоколу Modbus. #include <iarduino_MB_HTL.h> // Подключаем библиотеку для работы с блоком климатических датчиков. // ModbusClient modbus(Serial, 2); // Создаём объект для работы по протоколу Modbus указав класс Serial и номер вывода DE конвертера UART-RS485. iarduino_MB_HTL sensor(modbus); // Создаём объект для работы с блоком климатических датчиков, указав объект протокола Modbus. // void setup(){ // ... // Serial.begin(9600); // Указываем скорость шины RS485. Она равна скорости шины UART подключённой к конвертеру UART-RS485. while(!Serial); // sensor.begin(3); // Инициируем работу с блоком климатических датчиков, указав его адрес. ... // Если адрес блока не указан sensor.begin(), то он будет найден автоматически. } //
Если используется аппаратная шина UART-1, то вместо класса Serial указываем Serial1, для шины UART2 указываем Serial2 и т.д.
- Если используется программная реализация шины UART:
#include <SoftwareSerial.h> // Подключаем библиотеку для работы с программной шиной UART. #include <iarduino_Modbus.h> // Подключаем библиотеку для работы по протоколу Modbus. #include <iarduino_MB_HTL.h> // Подключаем библиотеку для работы с блоком климатических датчиков. // SoftwareSerial rs485(8, 9); // Создаём объект для работы с программной шиной UART указывая выводы RX, TX. ModbusClient modbus(rs485, 2); // Создаём объект для работы по протоколу Modbus указав объект программной шины UART и номер вывода DE конвертера UART-RS485. iarduino_MB_HTL sensor(modbus); // Создаём объект для работы с блоком климатических датчиков, указав объект протокола Modbus. // void setup(){ // ... // rs485.begin(9600); // Указываем скорость шины RS485. Она равна скорости программной шины UART подключённой к конвертеру UART-RS485. while(!rs485); // sensor.begin(3); // Инициируем работу с блоком климатических датчиков, указав его адрес. ... // Если адрес блока не указан sensor.begin(), то он будет найден автоматически. } //
Для программной реализации шины UART необходимо указать выводы которые будут использоваться как RX и TX, в примере указаны выводы 8, и 9 соответственно. При создании объекта modbus указывается не класс Serial, а объект для работы с программной шиной UART.
Скорость передачи данных по шине Modbus равна скорости шины UART.
Функция begin();
- Назначение: Инициализация работы с блоком климатических датчиков.
- Синтаксис: begin( [ АДРЕС_МОДУЛЯ ] );
- Параметр: АДРЕС_МОДУЛЯ uint8_t - значение от 1 до 247.
- Возвращаемое значение: bool - результат инициализации (true или false).
- Примечание:
- Если вызвать функцию без параметра, то адрес блока климатических датчиков будет найден автоматически. На это уйдёт некоторое время и на шине долен быть только один блок климатических датчиков.
- Функцию достаточно вызвать 1 раз в коде Setup(), до обращения к остальным функциям библиотеки.
- Блоки климатических датчиков поставляются с адресом 3 на шине, но этот адрес можно изменить.
- Пример:
sensor.begin(3); // Инициируем работу с блоком климатических датчиков, указав его адрес на шине.
Функция reset();
- Назначение: Программная перезагрузка блока климатических датчиков.
- Синтаксис: reset();
- Параметры: Нет.
- Возвращаемое значение: bool - результат перезагрузки (true или false).
- Пример:
sensor.reset(); // Выполняем программную перезагрузку.
Функция changeID();
- Назначение: Установка нового адреса на шине.
- Синтаксис: changeID( АДРЕС_МОДУЛЯ );
- Параметр: АДРЕС_МОДУЛЯ uint8_t - значение от 1 до 247.
- Возвращаемое значение: bool - результат изменения адреса (true или false).
- Примечание:
- Новый адрес сохраняется в энергонезависимую память, а значит остаётся после отключения питания.
- Выполнение функции занимает более 120 миллисекунд.
- Пример:
sensor.changeID(10); // Изменить адрес модуля на значение 10.
Функция setSpeedMB();
- Назначение: Установка новой скорости передачи данных.
- Синтаксис: setSpeedMB( СКОРОСТЬ );
- Параметр: СКОРОСТЬ uint32_t - может принимать одно из значений:
4800 / 9600 / 19200 / 38400 / 57600 / 115200. - Возвращаемое значение: bool - результат изменения скорости (true или false).
- Примечание:
- Новая скорость применяется на 2 секунды, в течении которых её нужно подтвердить.
- Если скорость не подтвердить в течении 2 секунд, модуль вернёт прежнюю скорость.
- Скорость подтверждается функцией ackSpeedMB() на новой скорости шины.
Функция ackSpeedMB();
- Назначение: Подтверждение смены скорости передачи данных.
- Синтаксис: ackSpeedMB();
- Параметры: Нет.
- Возвращаемое значение: bool - результат подтверждения скорости (true или false).
- Примечание:
- Подтверждение скорости выполняется после установки новой скорости модуля функцией setSpeedMB() и установки той же скорости для шины UART-RS485.
- Если скорость не подтвердить в течении 2 секунд, модуль вернёт прежнюю скорость.
- Подтверждённая скорость сохраняется в энергонезависимую память, а значит остаётся после отключения питания.
- Выполнение функции занимает более 50 миллисекунд.
- Пример:
sensor.setSpeedMB(9600); // Изменить скорость модуля на 9600 бит/сек. Serial.begin(9600); // Изменить скорость шины UART-RS485 на 9600 бит/сек. sensor.ackSpeedMB(); // Подтвердить скорость модуля.
Функция setTypeMB();
- Назначение: Установка нового типа протокола Modbus.
- Синтаксис: setTypeMB( ТИП );
- Параметр: ТИП uint8_t - может принимать значение MODBUS_RTU или MODBUS_ASCII.
- Возвращаемое значение: bool - результат изменения типа протокола (true или false).
- Примечание:
- Новый тип протокола применяется на 2 секунды, в течении которых его нужно подтвердить.
- Если тип протокола не подтвердить в течении 2 секунд, модуль вернёт прежний тип.
- Тип протокола подтверждается функцией ackTypeMB() по новому типу протокола на шине.
Функция ackTypeMB();
- Назначение: Подтверждение смены типа протокола Modbus.
- Синтаксис: ackTypeMB();
- Параметры: Нет.
- Возвращаемое значение: bool - результат подтверждения типа протокола (true или false).
- Примечание:
- Подтверждение типа протокола Modbus выполняется после установки нового типа протокола модуля функцией setTypeMB() и установки того-же типа протокола для передачи данных по шине UART-RS485.
- Если тип протокола не подтвердить в течении 2 секунд, модуль вернёт прежний тип.
- Подтверждённый тип протокола Modbus сохраняется в энергонезависимую память, а значит остаётся после отключения питания.
- Выполнение функции занимает более 50 миллисекунд.
- Пример:
sensor.setTypeMB(MODBUS_RTU); // Изменить тип протокола модуля на Modbus RTU. modbus.setTypeMB(MODBUS_RTU); // Изменить тип протокола шины UART-RS485 на Modbus RTU. sensor.ackTypeMB(); // Подтвердить тип протокола модуля.
Функция writeFlash();
- Назначение: Запись пользовательского значения в Flash память.
- Синтаксис: writeFlash( ЧИСЛО );
- Параметр: ЧИСЛО uint16_t - любое значение от 0 до 65535.
- Возвращаемое значение: bool - результат записи (true или false).
- Примечание:
- Записываемое число сохраняется в энергонезависимую память, а значит остаётся после отключения питания.
- Выполнение функции занимает более 50 миллисекунд.
- Для чтения числа из Flash памяти воспользуйтесь функцией readFlash().
- Число хранится в регистре "Holding Registers" [0x0120] «USER_DATA».
- Пример:
sensor.writeFlash(12345); // Записать число в энергонезависимую память.
Функция readFlash();
- Назначение: Чтение пользовательского значения из Flash памяти.
- Синтаксис: readFlash();
- Параметры: Нет.
- Возвращаемое значение: int32_t - число из памяти (0...65535) , или -1 при провале чтения.
- Примечание:
- Для записи числа в Flash память воспользуйтесь функцией writeFlash().
- Число хранится в регистре "Holding Registers" [0x0120] «USER_DATA».
- Пример:
i = sensor.readFlash(); // Читаем число из энергонезависимой памяти. if(i<0){ Serial.print("ERR"); } // Сообщаем о ошибке. else { Serial.print( i ); } // Выводим прочитанное значение.
Функция getID();
- Назначение: Чтение адреса устройства на шине.
- Синтаксис: getID();
- Параметры: Нет.
- Возвращаемое значение: uint8_t - адрес (1...247), или 0 если устройство не инициировано.
- Примечание:
- Данная функция может пригодиться если инициализация устройства выполнена функцией begin() без указания адреса (адрес найден автоматически).
- Пример:
i = sensor.getID(); // Читаем адрес устройства на шине. if(i==0){ Serial.print("ERR"); } // Сообщаем о ошибке. else { Serial.print( i ); } // Выводим адрес устройства на шине.
Функция getVersion();
- Назначение: Чтение версии прошивки устройства.
- Синтаксис: getVersion();
- Параметры: Нет.
- Возвращаемое значение: uint8_t - версия прошивки, или 0 если устройство не инициировано.
- Пример:
i = sensor.getVersion(); // Читаем версию прошивки устройства. if(i==0){ Serial.print("ERR"); } // Сообщаем о ошибке. else { Serial.print( i ); } // Выводим версию прошивки устройства.
Функция setIDLED();
- Назначение: Управление индикатором обнаружения устройства.
- Синтаксис: setIDLED( СОСТОЯНИЕ );
- Параметр: СОСТОЯНИЕ bool - флаг включения индикатора (true или false).
- Возвращаемое значение: bool - результат применения состояния индикатора (true или false).
- Примечание:
- Индикатор обнаружения устройства - это светодиод на разъеме RJ-45.
- Если индикатор включён, то светодиод постоянно светится. Так можно визуально определить устройство, если на шине имеются несколько одинаковых устройств.
- Если индикатор отключен, то светодиод информирует о получении запросов, адресованных этому устройству.
- Пример:
sensor.setIDLED(true ); // Включаем индикатор обнаружения устройства. sensor.setIDLED(false); // Отключаем индикатор обнаружения устройства.
Функция getPWR();
- Назначение: Чтение напряжения питания.
- Синтаксис: getPWR();
- Параметры: Нет.
- Возвращаемое значение: float - напряжение (5,000...24,000 В), или -1 при провале чтения.
- Примечание:
- Данная функция позволяет узнать напряжение питания поступившее на разъем RJ45.
- Функция позволяет возвращать значение за пределами указанного диапазона, но корректная работа устройства при таком питании не гарантируется.
- Пример:
i = sensor.getPWR(); // Читаем напряжение поступившее на разъем RJ45. if(i<0){ Serial.print("ERR"); } // Сообщаем о ошибке. else { Serial.print( i ); } // Выводим напряжение питания в вольтах.
Функция checkSensor();
- Назначение: Проверка климатических датчиков.
- Синтаксис: checkSensor( ДАТЧИК );
- Параметр: ДАТЧИК uint8_t - может принимать одно из следующих значений:
- SENSOR_SHT - Проверить только датчик влажности и температуры (SHT20).
- SENSOR_LTR - Проверить только датчик освещённости (LTR-553ALS).
- SENSOR_ALL - Проверить все датчики блока.
- Возвращаемое значение: int8_t - результат проверки датчиков может принимать любую комбинацию из следующих значений:
- ERROR_SHT_INIT - Ошибка инициализации датчика влажности и температуры.
- ERROR_SHT_DATA - Ошибка чтения данных датчика влажности и температуры.
- ERROR_LTR_INIT - Ошибка инициализации датчика освещённости.
- ERROR_LTR_DATA - Ошибка чтения данных датчика освещённости.
- 0 - Ошибки не выявлены.
- -1 - Нет ответа от модуля.
- Примечание:
- Функция позволяет проверить один указанный датчик, или все датчики сразу.
- Ошибки инициализации информируют о неисправности датчика. Инициализацию датчиков осуществляет блок сразу после подачи питания или после перезагрузки.
- Ошибки чтения информируют, что с момента инициализации была хотя бы одна ошибка.
- Пример:
uint8_t err = sensor.checkSensor(SENSOR_ALL); // Проверяем все датчики модуля. if( err < 0 ){ Serial.println("Модуль не отвечает"); } if( err == 0 ){ Serial.println("Ошибки не выявлены"); } if( err & ERROR_SHT_INIT ){ Serial.println("Неисправен датчик SHT"); } if( err & ERROR_SHT_DATA ){ Serial.println("Ошибка чтения SHT"); } if( err & ERROR_LTR_INIT ){ Serial.println("Неисправен датчик LTR"); } if( err & ERROR_LTR_DATA ){ Serial.println("Ошибка чтения LTR"); }
Функция getTEM();
- Назначение: Чтение температуры в °С.
- Синтаксис: getTEM();
- Параметры: Нет.
- Возвращаемое значение: float - температура от -40 до +125, или -100 при провале чтения.
- Примечание: Температура возвращается с одним знаком после запятой.
- Пример:
i = sensor.getTEM(); // Читаем температуру в °С. if(i<-40){ Serial.print("ERR"); } // Ошибка чтения. else { Serial.print( i,1 ); } // Выводим температуру с одним знаком после запятой.
Функция getHUM();
- Назначение: Чтение относительной влажности в %.
- Синтаксис: getHUM();
- Параметры: Нет.
- Возвращаемое значение: float - влажность от 0 до 100%, или -1 при провале чтения.
- Примечание: Влажность возвращается с одним знаком после запятой.
- Пример:
i = sensor.getHUMA(); // Читаем влажность в %. if(i<0){ Serial.print("ERR"); } // Ошибка чтения. else { Serial.print( i,1 ); } // Выводим влажность с одним знаком после запятой.
Функция getHUMA();
- Назначение: Чтение абсолютной влажности в г/м3.
- Синтаксис: getHUMA();
- Параметры: Нет.
- Возвращаемое значение: float - влажность от 0 до 655.35 г/м3, или -1 при провале чтения.
- Примечание: Влажность возвращается с двумя знаками после запятой.
- Пример:
i = sensor.getHUMA(); // Читаем влажность в г/м3. if(i<0){ Serial.print("ERR"); } // Ошибка чтения. else { Serial.print( i,2 ); } // Выводим влажность с двумя знаками после запятой.
Функция getLUX();
- Назначение: Чтение освещённости в лк.
- Синтаксис: getLUX();
- Параметры: Нет.
- Возвращаемое значение: float - освещённость от 0 до 65535 лк, или -1 при провале чтения.
- Примечание: Освещённость возвращается целочисленно.
- Пример:
i = sensor.getLUX(); // Читаем освещённость в лк. if(i<0){ Serial.print("ERR"); } // Ошибка чтения. else { Serial.print( i,0 ); } // Выводим освещённость без знаков после запятой.
Функция setPeriod();
- Назначение: Установка периода опроса датчика внутри блока.
- Синтаксис: setPeriod( ДАТЧИК, ВРЕМЯ );
- Параметры:
- uint8_t ДАТЧИК - может принимать одно из следующих значений:
- SENSOR_SHT - Установить период для датчика влажности и температуры (SHT20).
- SENSOR_LTR - Установить период для датчика освещённости (LTR-553ALS).
- SENSOR_ALL - Установить период для всех датчиков блока.
- float ВРЕМЯ - количество секунд с одним знаком после запятой (от 0,1 до 6'553,5 сек.).
- Возвращаемое значение: bool - результат применения нового периода (true или false).
- Примечание:
- Блок постоянно опрашивает все датчики через определённые промежутки времени, сохраняя результаты в регистрах. Это позволяет читать значения по шине без задержек.
- Данная функция позволяет задать временные промежутки опроса датчиков блоком.
- Например, если установить период опроса датчика равным 5 секундам. А запрашивать данные из блока по шине RS485 каждую секунду, то мы будем получать по 5 одинаковых значений подряд. Значит период опроса датчика блоком, должен быть меньше периода с которым мы получаем данные из блока по шине RS485.
- Функцию достаточно вызвать по одному разу для требуемых датчиков в коде setup().
- Если в качестве первого параметра указать SENSOR_ALL, то указанный период опроса применится ко всем датчикам блока.
- Узнать период опроса датчика можно функцией getPeriod().
- Пример:
sensor.setPeriod(SENSOR_SHT, 0.5); // Указываем период опроса датчика влажности и температуры. sensor.setPeriod(SENSOR_LTR, 1.0); // Указываем период опроса датчика освещённости. sensor.setPeriod(SENSOR_ALL, 1.2); // Указываем период опроса для всех датчиков блока.
Функция getPeriod();
- Назначение: Чтение установленного периода опроса датчика внутри блока.
- Синтаксис: getPeriod( ДАТЧИК );
- Параметр: ДАТЧИК uint8_t - может принимать одно из следующих значений:
- SENSOR_SHT - Получить период опроса датчика влажности и температуры (SHT20).
- SENSOR_LTR - Получить период опроса датчика освещённости (LTR-553ALS).
- Возвращаемое значение: float - время в секундах (0,1...6'553,5), или -1 при провале чтения.
- Примечание:
- Блок постоянно опрашивает все датчики через определённые промежутки времени, сохраняя результаты в регистрах. Это позволяет читать значения по шине без задержек.
- Функция возвращает время в секундах с одним знаком после запятой. Это время является периодом опроса датчика модулем.
- Пример:
i = sensor.getPeriod(SENSOR_SHT); // Читаем период опроса датчика влажности и температуры. if(i<0){ Serial.print("ERR"); } // Ошибка чтения. else { Serial.print( i,1 ); } // Выводим время в секундах с одним знаком после запятой.
Обработка ошибок:
Рассмотренные выше функции библиотеки iarduino_MB_HTL возвращают не только результат чтения, но и ошибки при записи или чтении. Причину ошибок можно выяснить функцией lastError() библиотеки iarduino_Modbus.
Функция lastError();
- Назначение: Получение кода причины последней ошибки.
- Синтаксис: lastError(); // Функция библиотеки iarduino_Modbus.
- Параметры: Нет.
- Возвращаемое значение: uint8_t - код причины последней ошибки.
- ERROR_ILLEGAL_FUNCTION - Команда запроса не поддерживается модулем.
- ERROR_ILLEGAL_ADDRESS - У модуля отсутствует регистр с указанным адресом.
- ERROR_ILLEGAL_VALUE - Недопустимое значение в поле данных запроса.
- ERROR_DEVICE_FAILURE - Любая невосстановимая ошибка кроме первых трёх.
- ERROR_ACKNOWLEDGE - Модуль принял запрос, но на обработку требуется время.
- ERROR_DEVICE_BUSY - Ведомый занят, запрос проигнорирован.
- ERROR_MEMORY_PARITY - Ошибка чтения/записи файла.
- ERROR_GATEWAY_UNAVAILABLE - Шина перегружена данными или не настроена.
- ERROR_GATEWAY_NO_DEVICE - Ведомого устройства нет или от него нет ответа.
- ERROR_SYNTAX - Ошибка синтаксиса.
- ERROR_ADR_IARDUINO - Ошибка назначения или сортировки адресов устройств iarduino.
- ERROR_ADR_RESPONSE - Несовпадение адреса регистра в ответе.
- ERROR_VAL_RESPONSE - Несовпадение данных в ответе.
- ERROR_CRC_RESPONSE - Несовпадение CRC в принятом ответе.
- ERROR_LEN_REQUEST - Размер отправляемого запроса превышает размер буфера.
- ERROR_LEN_RESPONSE - Размер полученного ответа превышает размер буфера.
- Пример:
float i = sensor.getLUX(); // Читаем освещённость в лк. if(i>=0){ // Если чтение выполнено без ошибок... Serial.print( i,0 ); // Выводим значение освещённости без знаков после запятой. }else{ // Если чтение не выполнено... switch( modbus.lastError() ){ // Получаем код последней ошибки. case ERROR_ILLEGAL_FUNCTION: Serial.println( F("Модуль не поддерживает команду или функцию запроса") ); break; case ERROR_ILLEGAL_ADDRESS: Serial.println( F("Запрос содержит недопустимый адрес регистра") ); break; case ERROR_ILLEGAL_VALUE: Serial.println( F("Запрос содержит недопустимое значение в поле данных") ); break; case ERROR_DEVICE_FAILURE: Serial.println( F("Ошибка запроса не связана с командой, адресом или данными") ); break; case ERROR_ACKNOWLEDGE: Serial.println( F("Модуль сообщает что занят и обработает запрос позже") ); break; case ERROR_DEVICE_BUSY: Serial.println( F("Модуль сообщает что занят и не будет обрабатывать запрос") ); break; case ERROR_MEMORY_PARITY: Serial.println( F("Модуль сообщает что произошла ошибка чтения/записи файла") ); break; case ERROR_GATEWAY_UNAVAILABLE: Serial.println( F("Шлюз неправильно настроен или перегружен запросами") ); break; case ERROR_GATEWAY_NO_DEVICE: Serial.println( F("Модуль которому адресован запрос не отвечает") ); break; case ERROR_SYNTAX: Serial.println( F("Ошибка синтаксиса") ); break; case ERROR_ADR_IARDUINO: Serial.println( F("Ошибка назначения или сортировки адресов устройств iarduino") ); break; case ERROR_ADR_RESPONSE: Serial.println( F("Ответ от модуля содержит недопустимый адрес регистра") ); break; case ERROR_VAL_RESPONSE: Serial.println( F("Ответ от модуля содержит недопустимое значение в поле данных") ); break; case ERROR_CRC_RESPONSE: Serial.println( F("Несовпадение CRC в ответе модуля") ); break; case ERROR_LEN_REQUEST: Serial.println( F("Размер запроса к модулю превышает буфер обмена или ADU") ); break; case ERROR_LEN_RESPONSE: Serial.println( F("Размер ответа от модуля превышает буфер обмена") ); break; default: Serial.println( F("Неизвестная ошибка") ); break; } }
- Зная причину ошибки, можно принять меры к её устранению:
- ERROR_GATEWAY_NO_DEVICE - нет ответа от модуля, означает что устройство отсутствует на шине. Причиной данной ошибки может быть, как физическое отключение устройства, так и плохой контакт, или недостаточное питание.
- ERROR_SYNTAX - ошибка синтаксиса, означает наличие ошибки в коде, например функция вызвавшая данную ошибку была вызвана с некорректными параметрами, или вызвана до инициализации модуля.
Ссылки:
- Блок климатический (температура, влажность, освещенность) RS485 / Modbus.
- Trema конвертер UART-RS485.
- Wiki - Блоки климатические (eCO2,TVOC, t°C, RH%, lux) RS485 / Modbus - Datasheet.
- Wiki - Работа с протоколом Modbus RTU/ASCI по шине RS485.
- Библиотека iarduino_Modbus.
- Библиотека iarduino_MB_HTL.
- Wiki - Установка библиотек в Arduino IDE.
Обсуждение