Доброго здравия, уважаемые друзья и читатели!
Сегодня на мини-обзоре небольшая платка, которая называется R4IOI16
– это расширитель GPIO на 16 входов или выходов, предназначенная для работы с шиной RS485 и протоколом Modbus RTU. Плата имеет 16 цифровых GPIO, которые можно использовать либо как входы, либо как выходы. Производится она китайской компанией Eletechsup, которая, к слову сказать, в последнее время выбросила на рынок довольно большой ассортимент подобных RS485 – адаптеров, на всякий вкус и цвет.
Обычно я пишу обзоры на то, что мне самому интересно или необходимо для каких-либо целей. Для чего мне понадобилась эта плата? Лично я хочу засунуть её вместе с твердотельными реле в коммутационную коробку освещения, дабы можно управлять освещением с центрального контроллера, и при этом не тянуть к нему силовые провода. На мой взгляд она идеально подходит для этого.
Общие сведения
Обозреваемое устройство представляет собой небольшую печатную плату размером 50 х 25 мм с маской зеленого цвета:
На плате расположены: микроконтроллер неизвестного роду-племени с маркировкой 2G8T71B, RS485-трансивер BL3085, линейный стабилизатор напряжения +5В 1А 78M05, и некоторые другие элементы обвязки. Плата имеет два ряда контактов с шагом 2,54 мм, при этом стандартной “гребенки”, так любимой китайскими производителями, в комплекте не было.
На стороне входов / выходов через каждые четыре сигнальных вывода GPIO расположена контактная площадка GND. Все входы-выходы подключены к микроконтроллеру через резисторы 470 Ом, что позволяет подключать к плате светодиоды или оптроны напрямую, без использования дополнительных внешних резисторов.
Допустимый ток через выводы не указан, но в описании другой подобной платы я встречал значение максимального тока до 50 мА на вывод – стоит ли этому доверять в данном случае – не знаю. С использованием резисторов 470 Ом при напряжении 5В максимум, что удастся от нее получить – это примерно 10 мА. Разумеется, для управления мощной нагрузкой потребуется дополнительное реле или электронный ключ.
Вход питания VIN (6 ~ 25 В) защищен от ошибочного подключения диодом Шоттки, при этом можно “снять” выходные 5В со встроенного стабилизатора. Либо можно подать 5В с внешнего источника, если таковой имеется, но защиты от переполюсовки уже нет. Допускается только один вариант источника питания одновременно (то есть не нужно подавать питание одновременно и на VIN и на контакт 5V).
RS485-трансивер BL3085 частично защищен супрессорами, но положенных в этом случае полупроводниковых самовосстанавливающихся предохранителей нет. Поэтому в случае случайной длительной подачи повышенного напряжения на линии А или В, супрессоры, скорее всего, выгорят.
Светодиод PWR подключен к одному из выводов микроконтроллера и отображает его работу, а также в моменты общения с хостом немного “подмигивает”. Программно отключить светодиод нельзя, или я не знаю как.
Для сброса на заводские настройки включите плату и замкните контакты RES на время около 5 секунд. Или отправьте команду в соответствующий регистр, о чем ниже.
Технические характеристики
- Напряжение питания (допускается только один вариант из перечисленных ниже):
- DC 6-25 В (с защитой от переполюсовки на диоде D1)
- DC 4-5 В (без защиты)
- Потребляемый ток: 6 мА (я так понимаю без учета тока выходов)
- Режим входа: поддерживаются уровни TTL 3,3 В/5 В, два активных уровня: низкий уровень (по умолчанию) или высокий уровень
- Режим выхода: уровни TTL 5 В, два активных уровня: низкий уровень (по умолчанию) или высокий уровень
- Скорость передачи: 1200, 2400, 4800, 9600(default), 19200, 38400, 57600, 115200 baud; None/Odd/Even Parity
Режимы работы GPIO
Режим работы выводов микроконтроллера (на вход или выход) конфигурируется не программно, а с помощью перемычек – М1 ~ M4.
А вот активные уровни – уже программно, с помощью регистров Modbus, о чем будет рассказано ниже.
- 16 DI – все 16 выводов используются как входы
- 16 DO – все 16 выводов используются как выходы
- 8 DI + 8 DO – первая половина (1 ~ 8 контакты) используются как входы, вторая половина (9~16 контакты) – как выходы
- 4 DI + 12 DO – четыре входа и двенадцать выходов
- 12 DI + 4 DO – двенадцать входов и четыре выхода
Изображение ниже иллюстрирует эти варианты:
Можно самому переключать эти режимы, а можно купить готовую платку с перемычкой в нужном месте. На обратной стороне можно найти мини-инструкцию, как переключать режимы входов-выходов данной платы и пояснительные надписи к контактам:
Все входы-выходы подключены к микроконтроллеру через резисторы 470 Ом, что позволяет подключать к плате светодиоды или оптроны напрямую, без использования дополнительных внешних резисторов.
По умолчанию на всех входах и выходах настроен активный низкий уровень, то есть подключенный светодиод будет светиться при 0 на выходе, а для считывания 1 на входе необходимо замкнуть выбранный вывод платы на землю (G).
Взаимосвязь входов и выходов
Плата имеет довольно интересную особенность, если настроена на режим 8DI-8DO (может быть и на 4DI-12DO и 12DI-4DO – я не проверял) – входы можно заставить управлять выходами непосредственно “на месте действия”, причем сделать это можно разными способами. Все входы и выходы объединяются в пары: DI 1 управляет выходом DO 9, DI 2 -> DO 10, …, DI 8 -> DO 16.
- По умолчанию взаимосвязь входов и выходов отключена – все работает независимо, то есть командами modbus вы переключаете выходы и читаете их состояние и состояние входов.
- Самоблокировка – первый активный сигнал на входе, например DI 1, включает соответствующий ему выход DO 9. Повторный сигнал – выключает. То есть действует как кнопка с самоблокировкой. Очень удобно использовать для управления освещением как с кнопки, так и по команде “умного дома”.
- Защелка – любой активный сигнал на входе, например DI 1, включает соответствующий ему выход DO 9. Триггер. Отключить выход можно только по команде modbus. Можно использовать для обнаружения каких-либо событий. Но можно настроить регистр 244 так, чтобы выходы автоматически отключались через заданное время.
- Кратковременный – при появлении на входе, например DI 1, активного уровня, на соответствующем ему выходе, например DO 9, на примерно полсекунды появится соответствующий активный уровень, а потом выход будет вновь отключен.
- Переключатель – здесь входы и выходы связаны уже парами. Например DI 1 включает DO 9, но выключает DO 10; а DI 2 включает DO 10, но при этом выключает DO 9.
- Повторитель (выход = вход) – как вы, наверное, уже догадались, активный уровень на входе повторяет то же самое на соответствующем выходе. Просто как кнопка без фиксации.
Разумеется, вся эта автоматика не отменяет управление через команды modbus.
Регистры modbus
Плата имеет на редкость хорошую документацию (на английском). Поэтому получить необходимую информацию о регистрах не составило особого труда. Итак…
Параметры связи по умолчанию: 9600 Baud, 8 Data bits, None Parity, 1 Stop Bit
Модуль поддерживает несколько разных команд (в зависимости от варианта использования M1 ~ M4 этот список может отличаться):
01
(hex0x01
) :: Read coils – чтение состояний выходов DO02
(hex0x02
) :: Read discrete inputs – чтение состояний входов DI03
(hex0x03
) :: Read holding registers – чтение функциональных регистров (параметров устройства) и регистров состояний DI и DO в виде битовой маски05
(hex0x05
) :: Write single coil – одиночное изменение состояний выходов DO06
(hex0x06
) :: Write single registers – изменение функциональных регистров (параметров устройства) по одному15
(hex0x0F
) :: Write multiple coils – множественное изменение состояний выходов DO16
(hex0x10
) :: Write multiple registers – изменение сразу нескольких функциональных регистров (параметров устройства)
Сводная таблица регистров приведена ниже. Обратите внимание, что в зависимости от выбранного режима (перемычками M1 ~ M4), диапазоны адресов могут быть изменены или вовсе отсутствовать.
Команда | Адрес или диапазон | Допустимые значения | Описание |
---|---|---|---|
Цифровые выходы DO (если есть) | |||
01 (0x01) | 1-16 (0x0001 – 0x000F) |
0 или 1 | Чтение состояния одного цифрового выхода DO |
05 (0x05) | Изменение состояния одного цифрового выхода DO | ||
15 (0x0F) | Изменение состояния нескольких цифровых выходов DO | ||
03 (0x03) | 128 (0x0080) | 0 ~ 65535 | Чтение состояния всех выходов DO в виде битовой маски 0-15 бит |
06 (0x06) | Изменение состояния всех выходов DO в виде битовой маски 0-15 бит | ||
Цифровые входы DI (если есть) | |||
02 (0x02) | 1-16 (0x0001 – 0x000F) |
0 или 1 | Чтение состояния цифрового входа DI |
03 (0x03) | 144 (0x0090) | 0 ~ 65535 | Чтение состояния всех входов DI в виде битовой маски 0-15 бит |
Настройки устройства (03 – чтение регистра, 06 / 16 – запись регистра) | |||
03 (0x03) 06 (0x06) 16 (0x10) |
243 (0x00F3) |
0 ~ 65535 | Плата будет включена автоматически после подачи питания, если в течение заданного времени не будет получена какая-либо команда. 0: Не включать автоматически (по умолчанию) 1: Включить через 1 секунду без какой-либо команды 2: Включить через 2 секунды без какой-либо команды 100: Включить через 100 секунд без какой-либо команды Максимальная задержка включения – 65535 секунд |
03 (0x03) 06 (0x06) 16 (0x10) |
244 (0x00F4) |
0 ~ 65535 | Автоматическое отключение всех выходных портов (установка состояния в OFF), если в течение заданного периода времени не будет получена какая-либо команда. 0: Не закрывать автоматически выходные порты (по умолчанию) 1: Закрывает выходы, если в течение 1 секунды не поступает команда 2: Закрывает выходы, если в течение 2 секунд не поступает команда 100: Закрывает выходы, если в течение 100 секунд не поступает команда Максимальная задержка выключения – 65535 секунд |
03 (0x03) 06 (0x06) 16 (0x10) |
245 (0x00F5) |
0x0000 0x0001 |
Активный уровень входных портов 0x0000 (NPN) Активный уровень низкий (по умолчанию) 0x0001 (PNP) Активный уровень высокий |
03 (0x03) 06 (0x06) 16 (0x10) |
246 (0x00F6) |
0x0000 0x0001 |
Активный уровень выходных портов 0x0000 (NPN) Активный уровень (ON) низкий (по умолчанию) 0x0001 (PNP) Активный уровень (ON) высокий |
03 (0x03) 06 (0x06) 16 (0x10) |
248 (0x00F8) |
0x0000-0x0255 | Автоматическое отправка данных о состоянии цифровых входов (DI) 0: Только по запросу хоста (по умолчанию) 1-255: Автоматическая отправка по таймеру, единица измерения — секунда 1: Отчет каждую секунду 2: Отчет каждые 2 секунды 10: Отчет каждые 10 секунд Максимальный интервал 255 секунд |
03 (0x03) 06 (0x06) 16 (0x10) |
250 (0x00FA) |
0x0000-0x0005 | Связь входов и выходов 0x0000 Входы и выходы изолированы друг от друга (по умолчанию) 0x0001 Самоблокировка 0x0002 Защелка 0x0003 Кратковременный 0x0004 Переключатель (используется 2 входа) 0x0005 Повторитель (выход = вход) Другие значения интерпретируются так же, как 0 |
06 (0x06) | 251 (0x00FB) |
0x0000 | Сброс на заводские настройки Например, если вы не знаете адрес устройства, можно отправить команду с широковещательным адресом 0xFF: FF 06 00 FB 00 00 ED E5 |
03 (0x03) 06 (0x06) |
252 (0x00FC) |
0x0000-0x1000 | Время ответа на команды Временной интервал для ответа на команды управления (единица: миллисекунды) Значение настройки: 0-1000 |
03 (0x03) 06 (0x06) |
253 (0x00FD) |
0x0001-0x0254 | Адрес RS485 (идентификатор подчиненного устройства) Если адрес не известен (утерян), можно отправить команду на широковещательный адрес 0xFF |
03 (0x03) 06 (0x06) |
254 (0x00FE) |
0x0000-0x0255 | Скорость передачи данных 0 = 1200, 1 = 2400, 2 = 4800, 3 = 9600 (default), 4 = 19200, 5 = 38400, 6 =57600, 7 = 115200 Любое другое значение: сброс на заводские настройки |
03 (0x03) 06 (0x06) |
255 (0x00FF) |
0x0000-0x0002 | Контроль четности 0 = None Parity, 1 = Odd Parity, 2 = Even Parity |
Эту таблицу можно проиллюстрировать “картами” из программы Modbus Poll:
Здесь стоит поподробнее остановится на некоторых регистрах – опциях.
243 (0x00F3)
Автовключение. Вот честно говоря, не очень понял, для чего эта опция предназначена. Если в данном регистре 0, то при подаче питания ничего не происходит. Если больше 0 – через заданное время начинает мигать светодиод – плата как бы пытается сама достучаться до хоста? Состояние входов и выходов никак не меняется. И что это дает?
244 (0x00F4)
Автоматическое отключение всех выходных портов. Более интересная опция. Если во время работы неожиданно была разорвана связь с хостом (мыши провод сгрызли), то спустя заданное время все выходы будут переведены в режим OFF. Если попытаться включить выходы с помощью входов – то они почти немедленно будут выключены. Можно использовать для того, чтобы при потере связи с контроллером управления вся нагрузка отключалась автоматически.
245 (0x00F5)
Активный уровень входных портов. Если в регистре записан 0, то при низком уровне на входе (замыкании его на “землю”) программа будет считать, что на входе логическая единица. Если в регистре записана 1, то для активации входа необходимо подать 5В на соответствующий контакт платы.
246 (0x00F6)
Активный уровень выходных портов. Если в регистре записан 0, то при отправке в соответствующий выход команды на включение, на нем будет установлен низкий уровень и наоборот. Если в регистре записана 1, то запись в соответствующий выход логической единицы приведет к появлению на контакте напряжения 5В.
Про взаимосвязь входов и выходов я уже написал выше.
Работа с платой на ESP32
В качестве примера я написал небольшую программку, для которой использовал ESP-IDF API, которое так и называется – ESP_MODBUS. Про нее я уже писал тут: Работа с шиной RS485 и протоколом Modbus RTU на ESP32. Поэтому подробно весь процесс я описывать не буду, а приведу лишь код демонстрирующий чтение состояния входов из регистра 144 (0x0090):
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <inttypes.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "mbcontroller.h" #include "sdkconfig.h" #include "esp_log.h" #include "esp_err.h" // Хэендл мастер-контроллера static void *master_handle = NULL; void app_main(void) { // Настраиваем modbus контроллер mb_communication_info_t modbus_config = {0}; modbus_config.ser_opts.port = UART_NUM_1; modbus_config.ser_opts.mode = MB_RTU; modbus_config.ser_opts.baudrate = 9600; modbus_config.ser_opts.parity = MB_PARITY_NONE; modbus_config.ser_opts.response_tout_ms = 1000; modbus_config.ser_opts.data_bits = UART_DATA_8_BITS; modbus_config.ser_opts.stop_bits = UART_STOP_BITS_1; // Создаем master-контроллер на COM-порту esp_err_t err = mbc_master_create_serial( &modbus_config, // Указантель на config &master_handle // Указатель на переменную, в которую будет записан хендл контроллера ); if ((err != ESP_OK) || (master_handle == NULL)) { ESP_LOGE("MODBUS", "MB controller initialization failure: %d %s", (int)err, esp_err_to_name(err)); return; }; // Настраиваем выводы COM-порта err = uart_set_pin( UART_NUM_1, // Номер COM-порта 17, // Номер вывода TXD 16, // Номер вывода RXD -1, // Номер вывода RTS -1 // Номер вывода CTS ); if (err != ESP_OK) { ESP_LOGE("MODBUS", "UART1 set pins failure: %d %s", (int)err, esp_err_to_name(err)); return; }; // Устанавливаем режим Half Duplex для COM-порта err = uart_set_mode( UART_NUM_1, // Номер COM-порта UART_MODE_RS485_HALF_DUPLEX // Режим Half Duplex RS485 ); if (err != ESP_OK) { ESP_LOGE("MODBUS", "UART1 set mode failure: %d %s", (int)err, esp_err_to_name(err)); return; }; // Запускаем modbus контроллер err = mbc_master_start( master_handle // Указатель на хендл контроллера ); if (err != ESP_OK) { ESP_LOGE("MODBUS", "MB controller start failure: %d %s", (int)err, esp_err_to_name(err)); return; }; ESP_LOGI("MODBUS", "Modbus started"); // Основной цикл while (1) { // Буфер под получаемые данные uint16_t buffer[1]; // Настраиваем параметры запроса mb_param_request_t request = { .slave_addr = 0x01, // Адрес slave устройства .command = 0x03, // Код команды .reg_start = 0x0090, // Начальный адрес регистра .reg_size = 1 // Количество регистров подряд }; // Отправляем запрос err = mbc_master_send_request( master_handle, // Указатель на хендл контроллера &request, // Параметры запроса &buffer[0] // Указатель на начало буфера ); if (err == ESP_OK) { // Выводим состояние входов в лог ESP_LOGI("MODBUS", "Read register: 0x%04X", (int)buffer[0]); } else { ESP_LOGE("MODBUS", "Read slave failure: %d %s", (int)err, esp_err_to_name(err)); }; // Ожидание vTaskDelay(pdMS_TO_TICKS(1000)); } ESP_LOGI("MAIN", "Program stopped"); }
Результаты её работы:
I (312) main_task: Calling app_main() I (312) uart: queue free spaces: 20 I (312) mb_port.serial: mbm_rtu@0x3ffb5be0, suspend port from task. I (312) MODBUS: Modbus started I (332) MODBUS: Read register: 0x0020 I (1352) MODBUS: Read register: 0x0020 I (5432) MODBUS: Read register: 0x0020 I (6442) MODBUS: Read register: 0x0000 I (7462) MODBUS: Read register: 0x0008 I (8482) MODBUS: Read register: 0x0008 I (9492) MODBUS: Read register: 0x0008 I (10512) MODBUS: Read register: 0x0008 I (11532) MODBUS: Read register: 0x0008
Вначале был замкнут вывод 7, потом я переставил перемычку на вывод 4.
На этом разрешите откланяться, с вами был Александр aka kotyara12. Благодарю за внимание.
Пожалуйста, оцените статью:
-= Каталог статей (по разделам) =- -= Архив статей (подряд) =-