Основные тезисы или о чем эта статья
Тема статьи — визуальное программирование ПЛК ShIoTiny для умного дома, описанного тут:
Очень кратко рассмотрены такие понятия, как узлы, связи, события, а также особенности загрузки и выполнения визуальной программы на ESP8266, который является основой ПЛК ShIoTiny.
Вступление или пара оргвопросов
В предыдущей статье по поводу своей разработки я сделал краткий обзор возможностей контроллера ShIoTiny.
Как ни странно, общественность проявила довольно сильную заинтересованность и задала мне довольно много вопросов. Некоторые товарищи даже сразу сходу предложили у меня купить контроллер. Нет, я не против того, чтобы немного заработать, но совесть не позволяет мне продавать ещё очень сырую в программном плане вещь.
Поэтому я выложил на GitHub бинарники прошивки и схему устройства:
Теперь каждый может прошить ESP-07 и самолично поиграться с прошивкой. Если кому очень хочется именно такую плату как на фото — то у меня есть их несколько штук. Пишите на почту [email protected]. Но, как говаривал незабвенный Огурцов: «Я ни за что не отвечаю!».
Итак, перейдём к сути: что такое «узел» (нода) и «событие«? Как выполняется программа?
Как обычно — начнём по порядку: с загрузки программы.
Как загружается программа
Начнем с того, что происходит, когда мы нажимаем кнопочку Upload в редакторе ElDraw и наша схема-программа, состоящая из красивых квадратиков улетает в устройство.
Во-первых, на основе нарисованной нами схемы строится её описание в текстовом виде.
Во-вторых, проверяется — все ли входы узлов соединены с выходами. «Висящих» входов не должно быть. Если такой вход обнаружен — схема в ShIoTiny не загрузится, а редактор выведет соответствующее предупреждение.
Если все прошло успешно, то редактор посылает в ShIoTiny текстовое описание схемы по одному узлу. Разумеется, существующая схема из ShIoTiny предварительно удаляется. Полученное текстовое описание сохраняется во FLASH-память.
Кстати, если вы хотите удалить схему из устройства, то просто загрузите в него пустую схему (не содержащую ни одного элемента-узла).
Как только вся схема-программа загружена в ПЛК ShIoTiny, она начинает «выполняться». Что это значит?
Отметим, что процессы загрузки схемы из FLASH-памяти при включении питания и при приёме схемы из редактора — идентичны.
Сначала идёт создание объектов-узлов на основе их описания.
Затем производится расстановка связей между узлами. То есть генерируются ссылки выходов на входы и входов на выходы.
И только после всего этого запускается основной цикл выполнения программы.
Писал я долго, но весь процесс -от «загрузки» схемы из FLASH-памяти до запуска основного цикла — занимает доли секунды для схемы из 60-80 узлов.
Как работает основной цикл? Очень просто. Сначала он ждёт возникновения события в каком-либо узле, затем обрабатывает это событие. И так без конца. Ну или пока не загрузят в ShIoTiny новую схему.
Уже несколько раз я упоминал такие вещи, как события, узлы и связи. Но что же это такое с программной точки зрения? Об этом и поговорим сегодня.
Узлы, связи и события
Достаточно взглянуть на примеры схем-программ для ShIoTiny, чтобы понять, что состоит схема лишь из двух сущностей — узлов (или элементов) и связей между ними.
Узел, нода или элемент схемы — это виртуальное представление какого-то действия над данными. Это может быть арифметическая операция, логическая операция или вообще какая угодно операция, какая придет нам в голову. Главное, что у узла есть вход и выход.
Вход — это то место, куда узел принимает данные. Изображения входов — это точки, находящиеся всегда с левой стороны узла.
Выход — это то место, откуда извлекается результат работы узла. Изображения выходов — это точки, находящиеся всегда с правой стороны узла.
У некоторых узлов нет входов. Такие узлы генерируют результат внутри себя. Например узел-константа или узел-датчик: им не нужны данные от других узлов, чтобы сообщить результат.
У других узлов, напротив, нет выходов. Это узлы, отображающие, например, исполнительные устройства (реле или еще какие-нибудь подобные). Они принимают данные, но не генерируют результата вычислений, доступного для других узлов.
Кроме того, есть еще уникальный узел-комментарий. Он ничего не делает, не имеет ни входов ни выходов. Его назначение — быть пояснением на схеме.
Что такое «событие»? Событие — это возникновение новых данных в каком-либо узле. Например к событиям относятся: изменение состояния входа (узел Input), приём данных от другого устройства (узлы MQTT и UDP), истечение заданного промежутка времени (узлы Timer и Delay) и так далее.
Для чего нужны события? Да для того, чтобы определить — в каком узле возникли новые данные и состояния каких узлов необходимо изменить в связи с получением новых данных. Событие, как бы «проходит» по цепочке узлов, пока не обойдет все узлы, состояние которых необходимо проверить и изменить.
Все узлы можно подразделить на две категории.
Узлы, которые могут генерировать события назовем «активные узлы».
Узлы, которые не могут генерировать события назовем «пассивные узлы».
Когда узел генерирует событие (то есть у него на выходе появляются новые данные), то изменяется в общем случае состояние всей цепочки узлов, подключенных к выходу узла-генератора события.
Чтобы было понятно, рассмотрим пример на рисунке.
Активные узлы тут — Input1, Input2 и Input3. Остальные узлы — пассивные. Рассмотрим что происходит, когда замыкается тот или иной вход. Результаты для удобства сведены в табличку.
Как видим, при возникновении события, строится цепочка от узла-источника события и до оконечного узла. Состояние тех узлов, которые не попадают в цепочку, не изменяется.
Возникает законный вопрос, а что же будет при возникновении двух или вообще нескольких событий одновременно?
Как любителя творчества Глеба Анфилова, меня так и тянет отправить любопытного вопрошателя к его книге «Бегство от удивлений». Это такая «теория относительности для самых маленьких», в которой хорошо рассказано, что такое «одновременно» и как с этим жить.
Но чисто практически все гораздо проще: при возникновении двух или вообще нескольких событий последовательно строятся и обрабатываются все цепочки от каждого источника события по очереди и никаких чудес.
Следующий вполне законный вопрос любопытного читателя — а что будет, если узлы соединить в кольцо? Или, как это принято говорить среди этих ваших умников — ввести обратную связь. То есть соединить выход одного из узлов со входом предыдущего узла так, чтобы состояние выхода этого узла влияло на состояние его же входа. Напрямую соединить выход узла с его же входом вам не позволит редактор ElDraw. А вот опосредованно, как на рисунке ниже — это сделать можно.
Итак, что же будет в этом случае? Ответ будет очень «определенный»: смотря какие узлы. Рассмотрим пример на рисунке.
Когда контакты входа Input1 разомкнуты на верхнем входе узла А — 0. На выходе узла А, тоже 0. На выходе узла Б — 1. И, наконец, на нижнем входе узла А — 1. Всё ясно. А кому не ясно — посмотрите ниже описание того, как работают узлы «И» и «НЕ».
Теперь замкнем контакты входа Input1, то есть подадим на верхний вход узла А единицу. Те, кто знаком с электроникой, знает, что фактически мы получим классическую схему генератора на логических элементах. И по идее, такая схема должна бесконечно выдавать на выходе элементов А и Б последовательности 1-0-1-0-1-0…. и 0-1-0-1-0-1-…. Ведь событие должно постоянно изменят состояние узлов А и Б, бегая по кругу 2-3-2-3-…!
Но на самом деле этого не происходит. Схема впадет в случайное состояние — или реле останется включенным или отключенным, а может и слегка прожужжать включаясь-отключаясь несколько раз подряд. Все зависит от погоды на южном полюсе Марса. И вот почему так происходит.
Событие с узла Input1 изменяет состояние узла А, потом узла Б и так по кругу несколько раз. Программа определяет «зацикливание» события и принудительно прекращает этот карнавал. После этого изменение состояния узлов А и Б блокируются до возникновения нового события. Момент, в который программа решит — «хватит вертеться по кругу!» — в общем случае зависит от многих факторов и его можно считать случайным.
Будьте осторожны, соединяя узлы в кольцо — эффекты будут не всегда очевидными! Хорошо представляйте что и зачем вы делаете!
А можно ли все же построить генератор на доступных нам узлах? Да, можно! Но для этого необходим узел, который сам умеет генерировать события. И такой узел есть — это «линия задержки». Посмотрим как работает генератор с периодом 6 секунд на рисунке ниже.
Ключевым элементом генератора является узел А — линия задержки. Если изменить состояние входа линии задержки с 0 на 1, то 1 на выходе появится не сразу, а только спустя заданное время. В нашем случае это 3 секунды. Точно так же, если изменить состояние входа линии задержки с 1 на 0, то 0 на выходе появится спустя те же 3 секунды. Время задержки задается в десятых долях секунды. То есть значение 30 и означает — 3 сек.
Особенностью линии задержки является то, что она генерирует событие после истечения времени задержки.
Предположим, что изначально на выходе линии задержки был 0. После прохождения узла Б — инвертора — этот 0 превращается в 1 и поступает на вход линии задержки. Сразу ничего не происходит. На выходе линии задержки как был 0 так и останется, но зато включается отсчет времени задержки. Проходит 3 секунды. И тут же линия задержки генерирует событие. На выходе у нее появляется 1. Эта единица после прохождения узла Б — инвертора — превращается в 0 и поступает на вход линии задержки. Проходит ещё 3 секунды… и процесс повторяется. То есть каждые 3 секунды состояние выхода линии задержки меняется с 0 на 1 и затем с 1 на 0. Реле щелкает. Генератор работает. Период импульсов составляет 6 секунд (3 секунды на выходе ноль и 3 секунды — единица).
Но, в реальных схемах, обычно не нужно использовать и этот пример. Существуют специальные узлы-таймеры, которые великолепно и без посторонней помощи генерируют последовательность импульсов с заданным периодом. Длительность «нуля» и «единицы» в этих импульсах равны половине периода.
Для задания периодических действий, используйте узлы-таймеры.
Отмечу, что такие цифровые сигналы, где длительность «нуля»и «единицы» равны, называются «меандром».
Надеюсь, я немного прояснил вопрос о том как происходит распространение событий между узлами и чего делать не стоит?
Заключение и ссылки
Статья получилась короткой, но это статья-ответ на возникшие вопросы по узлам и событиям.
По мере развития прошивок и появления новых примеров я буду писать о том, как программировать ShIoTiny небольшие статьи, покуда это будет интересно людям.
Как и ранее, схема, прошивка, примеры, описание узлов и все
Вопросы, пожелания, критика — это сюда: [email protected]
Источник: habr.com