Графический автомат светофора и его код
Графический автомат светофора и его код

Немного теории

Конечные автоматы, с позиции программирования, это секции кода с одним входом и одним выходом, называемые состояниями или вершинами. Вершины соединяются между собой направленными переходами, в результате автомат обладает хорошей структурированностью и замечательной наглядностью. В графическом представлении, разумеется. Изображенная на чертеже программа сама по себе является документом описания проекта, что удобно как при индивидуальной, так и при групповой работе.

Программный комплекс V2S использует парадигму Автоматного программирования, предложенную А.А.Шалыто. Графическая часть базируется на Microsoft Visio, программный код написан на VBA (Visual Basic for application), т.е. код полностью открыт для просмотра и редактирования, можно лично убедиться в отсутствии вредоносной составляющей.

Существенную помощь программисту оказывают макрокоманды - операторы V2S, которые в процессе трансляции преобразуются в достаточно сложный программный код, фрагменты которого разбросаны по результирующей программе. В частности, макрокоманда AFTER(iVar, iTime) позволяет выполнить переход с задержкой, отсчет которой начнется с момента, когда iVar станет отличным от нуля. Макрокоманда WAIT(iTime, iCount) определяет задержку iTime при переходе, положительное значение аргумента iCount задаст количество повторений переходов. Следует иметь ввиду, что iCount имеет практический смысл только если речь идет о петле, так как область действия аргументов макрокоманд задержки лежит в пределах вершины, из которой и выходят их дуги.

Дальнейшее описание V2S будет привязано к практической задаче, в качестве примера рассмотрим одиночный светофор.

Алгоритм "Светофора"

Пусть алгоритм работы одиночного светофора будет полноценным, хотя и сокращенным по времени для удобства демонстрации:

  1. Включен зеленый свет на 2с.

  2. Мигающий зеленый 2с.

  3. Желтый 2с.

  4. Красный 2с.

  5. Красный + желтый 2с.

  6. Повторить с пункта 1.

Временные интервалы заданы условно, могут быть изменены произвольным образом.

Создание проекта "Светофор" под Arduino

Прежде всего, определимся с "железом": принимаем Arduino Uno. На самом деле, можно использовать любую доступную платформу, это не окажет влияния на конечный результат. Подключаем три светодиода: красный, желтый и зеленый, не забывая токозадающие резисторы. Идеально, если есть готовые Led модули Arduino, в которых всё необходимое уже установлено.

Схема подключения  LED модулей к Arduino Uno
Схема подключения LED модулей к Arduino Uno

Led модули подключены к пинам D2 (красный), D3 ( жёлтый) и D4 (зелёный), как показано на схеме, но можно выбрать и собственные номера. Соответственно принятым настройкам, определим функцию инициализации пинов микроконтроллера:

void led_init(void)
{
    pinMode(2, OUTPUT);  pinMode(3, OUTPUT);  pinMode(4, OUTPUT); // D2, D3, D4 == LED
}

Что бы сократить число используемых функций и улучшить наглядность, управление цветами светофора сведем воедино:

void led(int iColor)
{
   if (iColor & RED)    digitalWrite(2, HIGH); else digitalWrite(2, LOW);
   if (iColor & GREEN)  digitalWrite(4, HIGH); else digitalWrite(4, LOW);
   if (iColor & YELLOW) digitalWrite(3, HIGH); else digitalWrite(3, LOW);
}

В функции led() используется операция побитового "и" с масками цветов RED, GREEN и YELLOW. Благодаря этому, аргумент iColor может получить сразу несколько цветов простым суммированием масок, например:

led(GREEN);        // Светить только зелёным светодиодом
led(RED + YELLOW); // Светить красным и жёлтым одновременно
led(OFF);          // Потушить всё

Маски цветов требуется определить. Самое простое - использовать #define:

#define OFF	    0
#define RED	    1
#define GREEN	2
#define YELLOW	4

Обратите внимание: значения, к которым соотносятся маски, представлены степенью числа 2. Именно поэтому мы можем пользоваться побитовым "И" в функции led().

Создание автомата "Светофор"

Создадим проект Arduino, в результате чего появиться новая папка с именем проекта. Предполагается, что свежая версия V2S в составе файла графических примитивов auto.vssx и файла графического документа aTrafficLight.vsdm скачаны. Файлы следует разместить в эту папку. Если вы хотите попробовать разработку самостоятельно, то следует удалить существующий автомат, размещенный в документе-примере aTrafficLight.vsdm. Тогда, после очистки, создайте "быстрый" автомат с названием "Светофор" и заполните его согласно рисунка.

Процесс создания автомата "Светофор"
Процесс создания автомата "Светофор"
Процесс создания автомата "Светофор"

Графическая форма автомата "Светофор"
Графическая форма автомата "Светофор"

Пояснения по графической форме автомата "Светофор"

Конечный автомат включает в себя шесть вершин. Одна выполняет инициализацию, а пять соответствуют состояниям светофора, заданным в условии. Задержки между переходами выполняет макрокоманда WAIT(2000), время в миллисекундах также определено в задании. Интерес представляет макрокоманда AFTER, она выполняет отсчёт времени начиная с момента истинности первого аргумента. В первый аргумент помещается переменная iBlink, которая определяет фазу "мигания". Две петли, срабатывая поочередно, обеспечили мигание светофора зелёным цветом. Время свечения 400мс и паузы 200мс было задано эмпирически, из соображений наглядности.

Заслуживают особого внимания взаимные приоритеты переходов. Если их два и больше, то совсем не очевидно, какой именно дуге отдаст предпочтение микроконтроллер. Особенно в случае, если условия переходов могут быть истинными одновременно. В классических автоматах эту дилемму разрешают, размещая взаимодополняющие переменные (например, "Х" и "NOT Х") в конкурирующих дугах. Получается, чем больше переходов, тем больше переменных надо "дополнить" в соседних ветвях, тогда как вставка дополнительных переменных требует от программиста специальных усилий и чревата трудно обнаружимыми ошибками.

Было принято решение отказаться от "дополнений" с помощью принципа приоритета перехода, т.е. путем задания порядка опроса условий в программном коде. Первой опрашивается дуга с наивысшим приоритетом, а затем по мере убывания. По умолчанию все дуги имеют средний приоритет Midle, хотя и не визуализируют его в текстовом виде. Но при необходимости, для любого перехода приоритет можно задать явно: VH (очень высокий), H (высокий), M (средний), L (низкий), UL (крайне низкий). Появляется текстовая метка и одновременно изменяется толщина линии, что подчеркивает разницу визуально.

Изменение приоритета перехода
Изменение приоритета перехода
Изменение приоритета перехода

Собираем проект Arduino

Размещаем определения масок цветов и код функций в соответствующие текстовые поля V2S. Можно было бы это сделать и в коде Arduino, но так будет нагляднее.

Текстовые поля VARIABLE и HEADER
Текстовые поля VARIABLE и HEADER
Текстовые поля VARIABLE и HEADER

Копируем рекомендации по интеграции в проект Arduino (находятся в документе Microsoft Visio); вставим их в программный код INO файла.

#include "aTrafficLight.h"

void setup() {
}

void loop() {
  // put your main code here, to run repeatedly:
   aTrafficLight();       //  Шаг проекта Светофор
   aTrafficLight_Mills(); //  Обработка таймеров проекта Светофор
}

Весь добавленный код занимает три сточки. Компилируем программу.

Компиляция

Ошибки в графической части проекта

Ошибки неизбежны. V2S старается их отловить еще на этапе трансляции, но касается это в основном графических недочетов.

Обнаружение ошибок подключения переходов
Обнаружение ошибок подключения переходов

Тем не менее, некоторые синтаксические ошибки все-таки могут быть выявлены.

Обнаружение некоторых типичных синтаксических ошибок
Обнаружение некоторых типичных синтаксических ошибок

Работа светофора

Работа светофора согласно программе конечного автомата
Работа светофора согласно программе конечного автомата

Заключение

Возможности программного комплекса V2S не ограничиваются только лишь задержками и приоритетами переходов. В наличии также таймеры, подпрограммы, средства трассировки и другие полезные "фичи". Все это может быть разобрано в последующих частях, если разработка покажется сообществу интересной.

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


  1. gt-fox
    24.08.2023 02:34

    Я бы добавил состояние "Желтый мигающий" и из него переход в "Красный". :)


    1. DonEgen Автор
      24.08.2023 02:34

      Разумеется! Вы можете изменять алгоритм произвольным образом, ведь это всего лишь учебный пример. Но, да, о желтом мигающем я и не вспомнил, спасибо.


      1. gt-fox
        24.08.2023 02:34
        +2

        Это один из примеров преимущества визуального Автоматного программирования

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


        1. DonEgen Автор
          24.08.2023 02:34
          +2

          Еще немаловажно, что все это можно легко повторить и через год, и через два, если вдруг понадобиться модернизировать алгоритм. А еще, программу легко обсуждать с заказчиком/руководством, которые зачастую в программировании ничего не понимают, но в визуальном виде хотя бы воспринимают что там происходит. Это тоже очень важно, так как много раз сталкивался, что заказчик сам не знает чего хочет, откуда вытекают многочисленные доработки. Но даже "дорабатывать" программу в визуальном виде гораздо проще. Для этого есть даже специальная фича: перенумерация состояний (пункт 2 в меню трансляции). Т.е. вставили блок номер 11 между блоками 10 и 20, а затем:

          Расширение номеров вершин
          Расширение номеров вершин

          И получили номера 10, 20, 30, все остальные также сдвинулись. И, забегая вперед, так же сдвинулись номера внутри блоков GOTO.

          Использование блока GOTO для сокращения длины переходов
          Использование блока GOTO для сокращения длины переходов

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


  1. Surrogate
    24.08.2023 02:34

    Картинки у вас огонь!!! Особенно последняя (светофор с анимацией).

    Подскажите как вы создаёте такую красоту?


    1. DonEgen Автор
      24.08.2023 02:34
      +1

      Если Вы загляните внутрь папки Github, то обнаружите там еще одну папку, где лежат остальные файлы проекта. В том числе, файл, который и создает "светофор с анимацией". Установив соответствующее ПО (его название начинается на Pro..), Вы получите ту же анимацию. Мало того, сможете добавить кнопку и запустить расширенный до "мигания желтым" проект от gt-fox. Название ПО не пишу по очевидной причине, и Вас прошу этого не делать.

      Остальные анимированные картинки - GIF, сделано при помощи LICEcap - полностью бесплатной программы. Скриншоты - LightShot, также бесплатно.