Урок 39. Реле времени: управление устройствами по таймеру
В этом уроке мы создадим четырёхканальное реле времени. К данному устройству можно подключить до 4 приборов (лампочки, светодиодные ленты, моторы, обогреватели, вентиляторы и т.д.), каждое из которых будет включаться на заданные для него промежутки времени суток и в заданные дни недели.
Каждый из четырёх каналов нашего реле времени может выдавать не только логические уровни (1/0 — вкл/выкл), но и сигналы ШИМ (включать приборы на определённую мощность).
В реле времени имеется 20 таймеров (их количество можно уменьшить или увеличить до 128, указав нужное число в строке 16 скетча). Один таймер включает только одно устройство (канал) на заданный промежуток времени, не влияя на работу остальных устройств (каналов). Каждому устройству (каналу) можно назначить несколько таймеров, следовательно, включать и выключать каждое из устройств можно несколько раз в сутки и на разную мощность. При отключении питания, таймеры реле не сбиваются, так как их настройки хранятся в энергонезависимой памяти Arduino. Текущее время также не сбивается, так как оно берётся из модуля часов реального времени, который снабжен батарейкой.
Реле времени можно использовать для включения освещения по времени в доме, квартире, на даче, на производстве и т.д. Можно использовать для включения по времени вентиляции, котлов, обогревателей, полива газонов, систем очистки дачных бассейнов и т.д. Еще одним преимуществом реле времени является создание эффекта присутствия, например, Вас нет дома, но свет утром и вечером включается, а днём и ночью выключается, утром включается радио или телевизор, а ночью включается ночник. Это может заставить задуматься нежелательных «гостей», что дом обитаем и делать там нечего.
Нам понадобится:
- Arduino Uno х 1шт.
- Дисплей LCD1602 I2C зелёный или синий x 1шт.
- Trema I2C HUB прямоугольный или квадратный x 1шт.
- Trema модуль — RTC (часы реального времени) x 1шт.
- Trema модуль — энкодер x 1шт.
- Trema Shield x 1шт.
Для реализации проекта нам необходимо установить библиотеки:
- LiquidCrystal_I2C для работы с символьными ЖК дисплеями.
- iarduino_Encoder_tmr для работы с энкодерами через аппаратный таймер.
- iarduino_RTC для работы с модулями реального времени.
- Библиотеки EEPROM, Wire и pgmspace используемые в скетче, входят в стандартный набор Arduino IDE.
О том как устанавливать библиотеки, Вы можете ознакомиться на странице Wiki — Установка библиотек в Arduino IDE .
Видео:
Схема подключения:
Trema модуль RTC и дисплей LCD1602 I2C подключаются к аппаратной шине I2C через Trema I2C HUB, а Trema энкодер можно подключать к любым (цифровым или аналоговым) выводам Arduino, их номера указываются в скетче (в примере использованы выводы D4, D7 и D8). Для удобства подключения используется Trema Shield.
Приборы подключаются к каналам 1-4:
- Маломощные приборы с питанием 5 В постоянного тока до 20 мА можно подключать напрямую к одному из каналов.
- Приборы с питанием до 30 В постоянного тока подключаются через силовой ключ.
- Приборы с питанием от сети 220 В переменного тока подключаются через твердотельное или электромеханическое реле.
Алгоритм работы:
Режим просмотра времени: При включении питания на индикаторе отображается текущее время, дата и день недели. Номера включённых каналов отображаются в правом верхнем углу дисплея.
Меню: Для входа в меню нужно нажать на энкодер. Далее поворачивая экодер вправо или влево можно выбрать разделы «ТАЙМЕРЫ», «ЧАСЫ», «ВЫХОД», для входа в требуемый раздел нужно опять нажать на энкодер.
Меню>часы: В данном разделе меню, поворачивая энкодер вправо или влево, можно выбрать разделы «ВРЕМЯ», «ДАТА», «ВЫХОД», для входа в требуемый раздел нужно нажать на энкодер.
Меню>часы>время: Этот раздел меню предназначен для установки текущего времени. Устанавливаемый в данный момент параметр времени (часы, минуты, секунды) должен мигать. Выбор значения осуществляется поворотом энкодера, а переход к следующему значению, нажатием на энкодер.
Меню>часы>дата: Этот раздел меню предназначен для установки текущей даты и дня недели. Устанавливаемый в данный момент параметр даты (день, месяц, год, день недели) должен мигать. Выбор значения осуществляется поворотом энкодера, а переход к следующему значению, нажатием на энкодер.
Меню>таймеры: В данном разделе меню, поворачивая энкодер вправо или влево, можно выбрать один из установленных таймеров (для их редактирования) или разделы «НОВЫЙ ТАЙМЕР», «СТЕРЕТЬ ВСЕ ТАЙМЕРЫ», «ВЫХОД», для входа в требуемый раздел нужно нажать на энкодер. Установленные таймеры отображаются в виде строки из времени их старта/сброса и номера канала «00:00-00:00-0».
Меню>таймеры>новый таймер: Выбор данного раздела приведёт к созданию нового таймера, на экране отобразится надпись «НОВЫЙ ТАЙМЕР СОЗДАН» после чего Вам будет предложено ввести время старта/сброса и указать номер канала (который будет включаться данным таймером). Данный раздел меню недоступен если установлены все таймеры.
Меню>таймеры>стереть все таймеры: Выбор данного раздела приведёт к удалению всех таймеров, на экране отобразится надпись «ВСЕ ТАЙМЕРЫ УДАЛЕНЫ». Данный раздел меню недоступен если нет ни одного установленного таймера.
Меню>таймеры>00:00-00:00-0: Вместо «00:00-00:00-0» будет строка из времени старта/сброса таймера и номера канала которым он управляет. Данный раздел меню предназначен для редактирования выбранного таймера, поворачивая энкодер вправо или влево, можно выбрать разделы «ВРЕМЯ И КАНАЛ», «ПОВТОРЫ», «УРОВЕНЬ СИГНАЛА», «СТЕРЕТЬ ТАЙМЕР», «ВЫХОД», для входа в требуемый раздел нужно нажать на энкодер.
Меню>таймеры>00:00-00:00-0>время и канал: Этот раздел меню предназначен для установки (редактирования) времени старта/сброса таймера и номера канала которым он управляет. Устанавливаемый в данный момент параметр (час старта, минута старта, час сброса, минута сброса, номер канала) должен мигать. Выбор значения осуществляется поворотом энкодера, а переход к следующему значению, нажатием на энкодер.
Меню>таймеры>00:00-00:00-0>повторы: Этот раздел меню предназначен для установки (редактирования) повторов таймера по дням недели, в которые он должен срабатывать. Под устанавливаемым в данный момент параметром (ПН, ВТ, СР, ЧТ, ПТ, СБ, ВС) должен мигать курсор. Поворот энкодера устанавливает или сбрасывает стрелочку под устанавливаемым параметром, если она установлена значит в этот день недели таймер будет срабатывать, иначе он срабатывать не будет. Переход к следующему дню недели осуществляется нажатием на энкодер.
Меню>таймеры>00:00-00:00-0>уровень сигнала: Этот раздел меню предназначен для установки (редактирования) уровня сигнала на выбранном канале при срабатывании таймера. Выбор уровня сигнала от 5% до 100% осуществляется поворотом энкодера с шагом 5%, а нажатие на энкодер приведёт к выходу из данного раздела.
Меню>таймеры>00:00-00:00-0>стереть таймер: Выбор данного раздела приведёт к удалению выбранного таймера, на экране отобразится надпись «ТАЙМЕР УДАЛЕН».
Примеры:
Создание таймера который по будням, между 18:00 и 20:00, будет включать 4 канал с уровнем сигнала 100%:
- Нажмите на энкодер для входа в меню.
- Поворачивайте энкодер пока не увидите раздел «ТАЙМЕРЫ» и войдите в него нажав на энкодер.
- Поворачивайте энкодер пока не увидите раздел «НОВЫЙ ТАЙМЕР» и войдите в него нажав на энкодер.
- Введите «18:00-20:00 к4». Выбор значений осуществляется поворотом энкодера, а переход к следующему — нажатием.
- Поворачивайте энкодер пока не увидите раздел «ПОВТОРЫ» и войдите в него нажав на энкодер.
- Установите галочки под «ПН, ВТ,СР,ЧТ,ПТ» . Установка осуществляется поворотом энкодера, а переход — нажатием.
- Поворачивайте энкодер пока не увидите раздел «УРОВЕНЬ СИГНАЛА» и войдите в него нажав на энкодер.
- Установите значение «100%». Выбор значения осуществляется поворотом энкодера, а установка — нажатием.
- Поворачивайте энкодер пока не увидите раздел «ВЫХОД» и выйдите из редактирования таймера нажав на энкодер.
- Поворачивайте энкодер пока не увидите раздел «ВЫХОД» и выйдите из раздела «ТАЙМЕРЫ» нажав на энкодер.
- Поворачивайте энкодер пока не увидите раздел «ВЫХОД» и выйдите из «МЕНЮ» нажав на энкодер.
Теперь на экране отображается текущее время, дата и день недели, а по будням, с 18:00 до 20:00 в правом верхнем углу экрана будет отображаться цифра 4, при этом на 4 канале будет установлен уровень логической «1» (сигнал ШИМ со 100% заполнением). На остальных каналах будет уровень логического «0».
Создание таймера который между 19:00 и 21:00 каждого дня, будет включать 3 канал с уровнем сигнала 50%:
- Повторите все шаги из предыдущего примера, но:
- Вместо «18:00-20:00 к4» введите «19:00-21:00 к3» .
- Вместо «ПН, ВТ, СР, ЧТ, ПТ» установите галочки под всеми днями недели «ПН, ВТ, СР, ЧТ, ПТ, СБ, ВС».
- Вместо «100%» установите уровень сигнала «50%».
После того как Вы установите два таймера (из 1 и 2 примера): По будням с 18:00 до 19:00 в правом верхнем углу экрана будет отображаться цифра 4, при этом на 4 канале будет установлен уровень логической 1 (сигнал ШИМ со 100% заполнением). По будням с 19:00 до 20:00 в правом верхнем углу экрана будет отображаться цифра 3 и 4, при этом на 3 канале будет установлен сигнал ШИМ с 50% заполнением, а на 4 канале будет установлен уровень логической «1» (сигнал ШИМ со 100% заполнением). По будням с 20:00 до 21:00 и в выходные с 19:00 до 21:00, в правом верхнем углу экрана будет отображаться цифра 3, при этом на 3 канале будет установлен сигнал ШИМ с 50% заполнением.
Примечание:
Включение и выключение устройств осуществляется по установленным таймерам только в режиме просмотра времени. Это сделано для того, чтобы устройства «случайно» не включились во время редактирования текущей даты, времени или таймера.
Код программы:
Библиотека iarduino_Encoder_tmr использует второй аппаратный таймер, НЕ ВЫВОДИТЕ СИГНАЛЫ ШИМ НА 3 ИЛИ 11 ВЫВОД!
Таймеры и многозадачность на Ардуино
Сегодня мы поговорим о такой актуальной теме, как таймеры и организация многозадачности на Arduino. Поводом для написания этой статьи послужили лекции Олега Артамонова @olartamonov для студентов МИРЭА в рамках IoT Академии Samsung, а точнее, высказывание Олега, цитата (2-я лекция, 1:13:08):
«Есть, например, задачи на которых можно сломать большинство ардуинщиков, особенно начинающих, попросите их помигать пятью разными светодиодами с разной частотой и периодом и так, чтобы ещё период можно было индивидуально для каждого светодиода изменять. »
Судя по высказываниям Олега, у него весьма превратное представление об Arduino вообще и об «ардуинщиках» в частности. Мигание пятью светодиодами в означенных им режимах это абсолютно тривиальная задача для Arduino, а для Arduino Mega Server это вообще не задача, а сущее недоразумение — его штатными средствами организуется многозадачность, которая легко управляет сотнями различных сущностей (светодиодов, сервоприводов, шаговых моторов и т. д.) в реальном времени.
Давайте вместе разберёмся как организовать многозадачность на Arduino, а заодно поможем студентам МИРЭА избавится от навязанных им стереотипов восприятия по отношению к социо-культурному и технологическому феномену нашего времени под названием Arduino.
Лекции Олега Артамонова
Нужно отдать должное, сами лекции Олега хороши — в них даётся много полезной и хорошо структурированной информации о микроконтроллерах и я бы рекомендовал всем заинтересованным в этом вопросе с ними ознакомиться. Единственным недостатком этих лекций мне показался неприкрытый техно-снобизм в отношении Arduino, которая выступает в них в роли «мальчика для битья».
В частности, на протяжении всех лекций Олегом делаются безапелляционные заявления о непригодности Arduino для построения сложных многозадачных систем, что просто противоречит истине и реальной практике.
На Arduino можно делать потрясающие многозадачные системы в которых в (псевдо, естественно) многозадачном режиме одновременно работают десятки и сотни сущностей (светодиодов, датчиков, актуаторов, сервоприводов, шаговых моторов, беспроводных и проводных интерфейсов и т. д.).
Не будем далеко ходить за примерами. Вот проект Зимнего сада («Умной теплицы») в котором в реальном времени в многозадачном режиме работают следующие сущности:
Топология распределённого nRF24 контроллера с огромным числом подключённого и работающего в реальном времени оборудования. Пользователь имеет дело только с «базой», работа nRF24 партнёра полностью прозрачна для него. И, да, это Arduino.
— 7 сервоприводов
— 9 шаговых моторов
— 6 реле
— 3 датчика влажности почвы
— 2 датчика освещённости
— Датчик уровня воды
— Датчик влажности и температуры воздуха
На nRF24 удалённой части:
— 12 датчиков влажности почвы
— 12 реле
— 3 шаговых мотора
— 2 датчика освещённости
— Датчик уровня воды
Кроме этого, в реальном времени функционирует собственно сама nRF24 связь между двумя распределёнными частями системы и Ethernet интерфейс сервера и серверный движок, обеспечивающий веб-интерфейс пользователя системы.
Итого, в реальном времени, в многозадачном режиме на 8-битной Меге функционирует как минимум 60 сущностей (и это не считая множества сервисов самой операционной системы AMS, с ними число сущностей приблизится к сотне). Что очевидным образом никак не согласуется с высказыванием о том, что «на Arduino невозможна настоящая многозадачность и мигать даже пятью светодиодами на ней проблематично».
Пара слов в защиту Arduino
(Хотя очевидно, что Arduino как социо-культурный и технологический феномен с многомиллионной армией поклонников и многими тысячами потрясающих проектов в защите не нуждается.)
Я много раз говорил и ещё раз повторю, что Arduino в своей софтверной составляющей это, по сути, просто один из возможных уровней абстракции (как и любой другой) со своими достоинствами и недостатками. И пользователю нет абсолютно никакой разницы, что «крутится» внутри его маленького кусочка кремния — «чистая» Arduino, RTOS, RIOT OS, AMS или какая-то другая математическая абстракция представления и управления железными ресурсами контроллера.
Пользователю важно решение его проблем — чтобы контроллер поливал растения, включал свет, управлял шторами и т. д. И основная проблема не в инструментах, используемых в разработке, а в умении ими пользоваться и, банально, в воображении и инженерном видинии самого разработчика.
Как это работает?
Сама по себе многозадачность на микроконтроллерах может быть организована разными способами, в данном случае речь пойдёт о самом простом — процессы по очереди получают управление и добровольно отдают его после использования своего кванта времени. Этот способ, конечно, не лишён очевидных недостатков, но, как говорится, практика — критерий истины и он прекрасно зарекомендовал себя в реальных условиях: он используется как в стандартных дистрибутивах Arduino Mega Server, так и во множестве проектов на AMS Pro. И эти системы работают в режиме 24/7 и имеют подтверждённые аптаймы во многие месяцы беспроблемной работы.
Это индикация около сотни сущностей распределённой nRF24 системы, управляемых независимо друг от друга в реальном времени. Обратите внимание на два последних индикатора «CPU» — при этом даже на 8-битной Меге загрузка процессора ровна нулю (то есть система полностью свободна).
Немного о таймерах
Для организации управления сложными системами недостаточно просто передавать по очереди управление между процессами и наряду с автоматической передачей управления в AMS используются различные виды таймеров: циклические, циклические с заданным количеством повторений (пакетные), одиночные, рандомные, смешанные и т. д. Всё это организовано нативными средствами Arduino и не использует прерывания или прямое программирование таймеров микроконтроллера (но прерывания, конечно же, использоваться системой «по их прямому назначению»).
Что опять же вступает в прямое противоречие с высказыванием «На 3 светодиода железных таймеров хватит, с дальше у ардуинщиков начнутся проблемы». Не начнутся. Нам доступны любые типы таймеров в любом количестве. И, при желании, мы можем наделать себе ещё сколько угодно новых и сколь угодно экзотических.
Основной кейс
Основной кейс при данном типе организации многозадачности — это создавать так называемый «неблокирующий» код, то есть код, который не использует функцию delay(), которая просто приостанавливает выполнение программы на заданное время.
Реальное время
Описываемый способ реализации многозадачности можно охарактеризовать как «soft-realtime», типовое время задержки в системе составляет 10 мс (но пиковые задержки могут быть значительно больше и не нормируются). Это накладывает известные ограничения на спектр применения данного решения, но для большинства «бытовых» задач (и не только) он прекрасно подходит, см. пример выше.
Если требуется управление в более жёстком реальном времени, то это требует специальной оптимизации кода под конкретную задачу, перестройки архитектуры или, в совсем крайних случаях, выделения отдельного контроллера под специфические функции. Как пример, выделение отдельного контроллера эффектов умной светодиодной ленты.
Это общее теоретическое описание работы многозадачности в Arduino вообще и в AMS в частности, теперь перейдём к рассмотрению практических примеров.
Циклические таймеры
Рассмотрим реализацию самых простых циклических таймеров. Это таймеры (в терминологии AMS «cycles»), которые включаются через определённые, заранее заданные промежутки времени и используются для активации циклических процессов.
Вообще, таймеры программно лучше оформлять в виде объектов, но в стандартной поставке Arduino Mega Server эти таймеры реализованы в виде функций, поэтому, для начала, рассмотрим их в этой ипостаси.
Использовать циклические таймеры очень просто: достаточно поместить код, который нужно периодически выполнять, между скобками оператора if. Если нужно использовать другой интервал срабатывания, то просто используем нужную переменную вместо cycle1s. Различных циклов можно сделать сколько угодно — система даже на 8-битной Меге без проблем потянет обслуживание буквально сотен таких таймеров (только, естественно, нужно не забывать чтобы вызываемый код не был блокирующим).
Теперь организация работы таймеров. Определение управляющих переменных в главном файле:
Набор интервалов может быть расширен любыми нужными значениями от десятков миллисекунд до суток и более.
И далее код подключения этих таймеров в основном цикле. В начале главного цикла проверяется не сработал ли какой-либо из таймеров, а в конце все поднятые флаги таймеров сбрасываются. Любой системный код находится между этими двумя функциями и, что наиболее важно, любой из таймеров можно использовать многократно в любых частях кода системы.
Циклические таймеры в виде объектной библиотеки
Теперь рассмотрим организацию тех же таймеров, но в более правильном объектном виде, оформленном в готовую библиотеку. Назовём её myCycle.
Заголовочный файл в котором представлены объявления класса, методов и некоторых предопределённых констант:
И файл реализации в котором находится код библиотеки:
Использование этого варианта тоже просто и имеет некоторые преимущества перед «функциональным» вариантом: тут можно очень легко объявлять таймеры с нужными интервалами и не нужно заранее создавать множество таймеров «на всякий случай».
В главном файле:
Добавляем функции обслуживания работы таймеров:
В главном цикле используем объявленные таймеры в любом нужном месте кода:
Библиотека имеет несколько более широкий функционал, чем код, приведённый в первом варианте. Например, она содержит методы активации/дезактивации таймеров, установки и получения текущего значения, рестарта и реинициализации таймеров, что ещё больше расширяет возможности использования их в практических задачах.
Другие виды таймеров на Arduino
Чтобы не загромождать статью, я не буду здесь приводить код и разбирать работу всех возможных типов таймеров — все они строятся по одним и тем же принципам. Если эта тема будет интересна, то можно будет написать отдельную статью об этом. Здесь я только дам общее описание таймеров, которые используются в AMS и прекрасно себя зарекомендовали на практике.
Циклические с заданным количеством повторений (пакетные)
Это таймеры, которые срабатывают заранее определённое количество раз. Например, вам нужно делать 3 попытки отправки сообщения по беспроводному каналу nRF24. Таймер активируется только 3 раза и соответственное количество раз делаются попытки отправки сообщений.
Тут же возможны различные расширения функциональности типа активации/дезактивации таймера в зависимости от определённых условий и т. п.
Одиночные
Это различные вариации на тему «автозагрузки», когда какое-либо действие выполняется через определённый интервал времени после старта контроллера или какого-либо события.
Рандомные
Иногда требуется не строгая периодичность выполнения каких-то действий, а наоборот некий разброс срабатываний возле некоторого среднего значения, для этих целей применяются так называемые рандомные таймеры.
Например, у вас есть два распределённых контроллера, которые связаны друг с другом по беспроводному каналу. Если одна система будет посылать свои сообщения другой, согласуясь со срабатыванием обычного таймера, например, раз в 20 секунд, то эти сообщения будут приходить на вторую систему в строго определённой «фазе», которая может попадать в «проблемный» интервал работы цикла второго контроллера, в результате его работа может быть нестабильной. Если в этом случае использовать рандомный таймер, то он «размажет» по времени моменты прихода сообщений от первого контроллера и проблемы удастся избежать.
Это только абстрактный пример для понимания того, что собой представляют рандомные таймеры. И вы можете ознакомиться с их реализацией — стандартный дистрибутив Arduino Mega Server содержит код такого таймера.
Смешанные
Тут полная свобода действий, можно как угодно комбинировать работу различных типов таймеров, используя запуск одних таймеров от других и их встроенную логику типа активации/дезактивации по условиям, изменение периода срабатывания «на лету» и т. п.
Нет практически никаких ограничений на количество таймеров и логику работы — их может быть сотни, даже на 8-битном контроллере.
Межпроцессное взаимодействие
Межпроцессное взаимодействие, семафоры, почтовые ящики и прочие атрибуты многозадачных систем организуются на Arduino тоже без каких-либо проблем — их можно организовать любым удобным для вас способом — начиная от передачи параметров через статические переменные и заканчивая упаковкой логики в любые классы и объекты, тут нет абсолютно никаких ограничений и проблем.
Подробное описание межпроцессного взаимодействия выходит за рамки этой статьи, но вы можете скачать себе дистрибутив Arduino Mega Server для любой платформы и самостоятельно ознакомиться с его устройством и работой.
Заключение
В общем, можно сказать, что средствами Arduino можно создать любые виды таймеров, запускать любое их количество и использовать любое их сочетание, другими словами, Arduino может удовлетворить любой каприз по таймерному (псевдо) многозадачному управлению сложными микроконтроллерными системами.
И это не должно быть секретом для студентов МИРЭА, как будущих инженеров микропроцессорных систем, ведь эти принципы можно применять на любой платформе.