О чем эта статья

Продолжаем цикл статей о ShIoTiny — визуально программируемом контроллере на базе чипа ESP8266.

В этот статье рассказано о часах реального времени в контроллере ShIoTiny, синхронизации времени и использовании узлов работы с часами.

Сайт проекта ShIoTiny

Предыдущие статьи серии.

ShIoTiny: малая автоматизация, интернет вещей или «за полгода до отпуска»

ShIoTiny: узлы, связи и события или особенности рисования программ

ShIoTiny: вентиляция влажного помещения (проект-пример)

ShIoTiny и окружающий мир: подключение датчиков к бинарным входам, дребезг контактов и другие вопросы

ShIoTiny и окружающий мир: аналоговые датчики или АЦП для самых маленьких

Бинарные прошивки, схема контроллера и документация

Вступление


Сегодня мы поговорим о времени. Не о времени, в том смысле, в котором о нем веками спорят философы и конца-края этому спору не видно. А о том времени, которое мы видим на часах и согласно которому идем на работу, в школу или спешим на свидание.

Вся штука в том, что энергонезависимые часы реального времени в чипе ESP8266 и контроллере ShIoTiny — отсутствуют. Эта родовая травма контроллера ShIoTiny — целиком и полностью моя вина. Но, что сделано — то сделано.

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

Так как ошибки надо исправлять, и, на этот раз хотя бы не кровью, то я пошел навстречу все возрастающему числу пользователей моей прошивки и сделал то что смог. А именно — я добавил в прошивку контроллера ShIoTiny узлы, позволяющие более-менее удобно с этим работать с реальным временем.

О часах ShIoTiny


Как уже было сказано, «часов с батарейкой» в ShIoTiny нет. Но в то же время, отсчет секунд, начиная с 1 января 1970 года реализован.

Это то самое время, которое называется UNIX-time, хранится в переменных типа time_t языков С/C++ и которое в 32-битных системах должно закончится 19 января 2038 года.

Но, не бойтесь. Я думаю, что к 2038 году все успеют сделать тип time_t 64-битным и на ближайшие примерно 292 миллиарда лет проблема будет решена. Ну а там еще что-нибудь придумаем.

Заметим, что время в формате time_t называется иногда (и у меня в статье тоже) — timestamp или, по-русски временная метка.

Но вернемся к нашему контроллеру. Итак, часы в нем есть, но эти часы сбрасываются в 0 после отключения питания. Отсюда следует тривиальный вывод, что главной проблемой отсчета времени в контроллере ShIoTiny является необходимость синхронизации часов контролера при включении питания. Остальное — чисто технические проблемы

Синхронизация времени


Давным давно устоявшийся способ синхронизации времени в интернете — это NTP-сервера. И первой идеей было сделать узел, который синхронизирует время с заданным NTP-сервером.

Но, немного подышав свежим воздухом и покумекав своей тыковкой я понял, что этот подход идеологически неверный.

Ведь не факт, что пользователь захочет вытащить контролер с прошивкой ShIoTiny в интернет. И время для синхронизации может присылаться не только с NTP-сервера но и по UDP-multicast или при известном качестве связи — по MQTT.

Поэтому было принято судьбоносное решение — разделить узлы получения времени с NTP-сервера и установки системного времени.

Всего для синхронизации времени было разработано два узла: узел получения времени с NTP-сервера NTP Time



и узел установки системных часов Set Time



Узел получения времени с NTP-сервера в качестве параметров получает имя или IP-адрес NTP-сервера и, через запятую, период запроса времени с NTP-сервера в минутах. По умолчанию время запрашивается с NTP-сервера каждые 60 минут или 1 час. На выходе этот узел выставляет 0 до тех пор, пока время не синхронизировано или временную метку — результат последней синхронизации с сервером.

Узел установки системных часов получает на вход временную метку и и устанавливает системные часы в соответствии с этой меткой.

Простейшая схема синхронизации системных часов с NTP-сервером приведена на рисунке.



Период синхронизации не задан и по умолчанию равен 60 минут. На рисунке показана временная метка.

Отмечу, что более одного узла получения времени с NTP-сервера и более одного узла установки системного времени на схеме-программе быть не может.

Если вам нужна экзотическая схема синхронизации — то можно использовать UDP-multicast или MQTT. Схемы при этом полностью аналогичны.

Для синхронизации по UDP-multicast, примерно такая, как на рисунке.



А для синхронизации по MQTT (не советую, конечно, но на крайний случай) — такая.



Надеюсь, теперь все понятно с синхронизацией времени системных часов контролера ShIoTIny. Перейдем к узлам получения и обработки времени.

Который час?


Вопрос простой, но ответить на него, порой, не просто. Ведь время в каждой точке Земли — разное. Наша необъятная Родина включает от Калининграда до Камчатки аж 11 часовых поясов.

NTP-сервер, в зависимости от настроек, может возвращать временную метку, привязанную к различным часовым поясам. Как правило, эта временная метка привязана к UTC — всемирному времени.

Но обычно нам нужно местное время того региона где работает наш контроллер. Как тут быть?

А очень просто — для получения временной метки системных часов контролера ShIoTIny был разработан узел Get Time, в котором можно задать часовой пояс в виде смещения времени от -12 часов до +12 часов относительно системных часов контроллера.

Предположим, мы получаем время с сервера pool.ntp.org и синхронизируем системные часы, как в нашем примере ранее. Этот сервер возвращает всемирное время. Нам нужно местное, например Томское, как у меня. Я знаю, что Томск находится в часовом поясе UTC+7. Значит, зададим в узле получение времени смещение +7 или просто 7. Как на рисунке ниже.



А если бы мы жили в Канадской провинции Альберта — то смещение было бы -7 часов. Главное запомните — часовой пояс задается в узле получения времени в часах. И задается он в виде смещения относительно времени системных часов. На выходе узла получения времени выставляется временная метка. Узлов получения времени на схеме может быть несколько.

Сверим часы


Машине очень удобно работать с временем в формате временных меток time_t. Ведь это просто целое число, которое показывает число секунд относительно начальной точки — 1 января 1970 года. В этом формате можно легко находить расстояние между двумя временными точками, отсчитывать периоды и так далее. Это всего лишь сложение и вычитание целых чисел.

Но человек — не машина. Ему гораздо удобнее привычное представление времени в виде года, месяца, числа, часов, минут и секунд. Так уж мы, люди, устроены.

Поэтому были введены узлы перевода временной метки в привычные человеку единицы изменения времени и наоборот — синтеза временной метки из понятных человеку единиц изменения времени. Называются эти узлы, соответственно, Split Time и Synth Time.

Как все это работает — понятно из рисунка ниже.



Отмечу, что узлы Split Time и Synth Time месяцы (month) и дни недели (wday) отсчитывают с нуля. Для месяцев: 0-январь, 11-декабрь. Для дней недели 0-воскресенье, 6-суббота.
Остальные выходы: день месяца (day), year (год), hour (час), min (минута), sec (секунда) — отсчитываются в привычном виде. Часы, минуты, секунды — от 0 до 59. День месяца — в зависимости от месяца от первого числа до 30го или 31го и, для февраля, до 28 или 29го.
Ну а год — он и есть год. 2019й сейчас.
Надеюсь, все понятно.

Пример системы


Чтобы не быть голословным, приведу пример использования часов. Разумеется, упрощенный.

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

Попробуем это реализовать.



Все кусочки схемы нам знакомы. Время синхронизируется с сервера NTP. Пока оно не синхронизировано — узел NTP Time возвращает 0 и реле включения вентилятора — отключено. За это отвечает верхний по схеме элемент И.

Как только время синхронизировалось, включение-отключение вентилятора определяется текущим временем и уровнем влажности. Как только уровень влажности превысит 70% и время будет от 23:00 до 06:00 — вентилятор включится и не мешая никому проветрит помещение.

Разумеется, константы времени и влажности в реальном проекте лучше заменить на параметры, сохраняемые во FLASH и устанавливаемые, например по MQTT. Да и текущее состояние системы — уровень влажности, текущее, время, состояние вентилятора — тоже не повредит опубликовать в сети, чтобы контролировать систему со смартфона. Но это уже я оставляю простор для вашей фантазии.

Заключение


Вот мы и познакомили поближе наш контроллер с реальным временем.

Хочу выразить благодарность всем, кто присылал мне письма с конструктивной критикой и советами по модернизации программного обеспечения. Спасибо, ребята!

Как обычно — конструктивная критика приветствуется. Кроме этого приветствуются замечания и предложения.

Отправлять всю критику, замечания, предложения можно как обычно в комментарии или на почту: shiotiny@yandex.ru.

Комментарии (2)


  1. madcatdev
    15.09.2019 22:27
    -2

    Интересная статья, спасибо.
    Но само по себе визуальное программирование микроконтроллеров — тема сомнительная, имхо, и работает только для несложных схем. Стоит алгоритму усложниться — и разбираться в нем становится очень сложно.


    1. shiotiny Автор
      16.09.2019 05:39

      Интересная статья, спасибо.


      Спасибо за теплые слова.

      работает только для несложных схем. Стоит алгоритму усложниться — и разбираться в нем становится очень сложно.


      Тут я с вами согласен. Так и задачи у микроконтроллеров в большинстве случаев — несложные. Собрать данные, управлять несколькими реле, включать-выключать что-то в зависимости от показаний датчиков или команд по сети.

      Кстати, а вы задумывались, почему «стоит алгоритму усложниться — и разбираться в нем становится очень сложно»?

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

      То есть, если ввести концепцию мета-узлов — то есть узлов, включающих несколько других узлов и выглядящих на схеме как один узел со своими входами-выходами — то трудность построения сложных алгоритмов должна снизиться, как мне кажется.

      Не знаю, смогу ли я такую концепцию реализовать и запихать в ESP8266, но думаю над этим.

      Ну и люди, которые начали использовать мою прошивку — здорово помогают баги искать и советами чего не хватает.