Определение конечного автомата
Одно из определений конечного автомата (FSM) заключается в том, что конечный автомат — это математическая модель последовательности событий и действий, описывающих определенный (логический) процесс. В инженерной практике можно найти бесчисленное количество таких процессов, начиная с очень простого процесса управления электродвигателем с помощью пары кнопок и заканчивая очень сложной системой FSM, контролирующей очень сложный производственный процесс

Из определения и картинки понятно что это такое. С точки зрения автоматизации это и есть конечные состояния нашей системы. Больше теории вам даст википедия, а мы тут пойдем в сторону минимальной практики.
Реализация конечного автомата через CASE OF
Проведя опрос, среди целевой аудитории, в количестве трех человек, за что им огромное спасибо, мы выяснили, что реализовывать обход всего этого графа, а это граф, все 100% респондентов будут путем CASE-ов и IF-ов.
UPD. 5 человеков. 2 решили реализовать через SFC(они нам больше не друзья)
UPD. 6 человек. 1 — FBD и &, что я просто не понимаю.
Я тоже не святой и точно также все это реализовываю. И выглядит такое безобразие для рандомной системы примерно следующим образом.


Короче, как видно из примеров это все очень громоздко, сложно сопровождается, если где-то есть ошибка, то здрасьте приехали.
Но зато быстро реализуется. А метод «в лоб» нам иногда очень помогает. Но что если у вас очень много свободного времени, оперативной памяти на ПЛК и есть ресурс по ЦП?
УЛУЧШЕННАЯ РЕАЛИЗАЦИЯ
Сразу оговорюсь. Не я автор такого прекрасного решения. Я просто взял код и статью ВОТ ПО ЭТОЙ ССЫЛКЕ, перевел её и пару дней адаптировал код.
Однако моя реализация оперирует мифическими состояниями и действиями. Так что надо будет придумать какой-нибудь процесс. Прям хочется взять из оригинала, но надо иногда и самому подумать.
Второй день мыслительного процесса подходит к концу. По этом будем пользоваться великим изобретением человека — АБСТРАКЦИЕЙ.

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

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

Следующим шагом нам надо создать абстрактное описание событий и действий, которые нам далее понадобятся, а для этого воспользуемся Интерфейсами.
Интерфе́йс (англ. interface) — программная/синтаксическая структура, определяющая отношение между объектами, которые разделяют определённое поведенческое множество и не связаны никак иначе
ВИКИПЕДИЯ
Нам потребуется создать два интерфейса, один интерфейс будет служить для реализации логики поведения таких объектов как Событие, а другой для таких объектов как Действия. А чтобы было проще объект — это FB.
Создание интерфейса в Codesys
Для создания Интерфейса нам потребуется пройти нелегкий путь через пкм, указанный на картинке.

Пройдя по нему будет открыто окно создания интерфейса, где нам потребуется ввести имя этого интерфейса.

И еще добавим к этому всему Метод. Можно ли без метода? Да, но я не хочу.
Так что на нашем интерфейсе ПКМ и далее по навигационной карте

Так как по событиям у нас будет осуществляться переход, то наши события нам должны возвращать TRUE или FALSE. Так что возвращаемый тип BOOL для нас просто оптимален. Так что в появившемся окне дайте имя методу и поставьте тип возвращаемого значения.
И повторим процедуру для создания интерфейса itfAction с методом Action(только не списывайте точь в точь) и пускай он возвращает любое значение — нам не принципиально.
Описание перехода
Теперь нам необходимо засунуть в одну структуру все что потребуется для перехода из состояния А в состояние Б. В структуре должно быть начальное состояние, конечное состояние посчитано максимальное количество событий и максимальное количество действий при переходе.
В нашем случае там всегда есть одно событие и одно действие, но мы заложим потенциал для расширения, чтобы для перехода нам потребовалось два условия и мы бы смогли выполнить два действия. Да мы можем оставить по одному блоку и туда напихивать нужные команды и условия, но мы же хотим потом еще и без боли сопровождать это все.
Список для перехода:
- Начальное состояние
- Событие 1
- Событие 2
- Действие 1
- Действие 2
- Конечное состоя
Создаем структуру прям как мы и описали)

Гляди как похожи, даже родная мать с трудом отличит.
Структура системы
А теперь нам надо представить как эта системы будем умещаться в одной структуре. В целом система представляет собой нынешнее состояние и массив всех переходов. Чтобы понять какой нам потребуется массив просто считаем стрелочки…
Я насчитал десять

Создание событий
Теперь у нас начинается механическая нудятина. Нам потребуется создать список всех событий. Если событие выполнено, то возвращаем TRUE.
Список событий системы:
- Нет события
- Запуск системы
- Сбой системы
- Система в норме
- Система запущена
- Выключение системы
- Система остановлена
- Ошибка сброшена
В итоге мы имеем 8 событий. Я покажу как создать два, а остальное по аналогии.
Первым делом событие «Нет событий». Это событие заглушка, которое всегда возвращает true.
1)Откроем окно создания POU через контекстное меню.

2)В окне созданиz указываем имя, ставил галочку в окошке напротив слова Implements и выбираем нужный нам интерфейс.

3)Жмем добавить и в появившемся FB открываем метод getEvent и туда прописываем возврат True.

Готово. Осталось удалить текстовую прагму.
Теперь тоже самое для события запуск системы, но тут в ФБ нам потребуется одна переменная ввода. Которая будет событийной.


Дальше все по накатанной.
ВНИМАНИЕ
При создании фб, описанных выше, перед названием поставил буквы мс.
ПЕРЕМЕННАЯ bStartCommand перенесена в раздел var
Создание действий
По факту у нас два действия, которые система должна совершить вовремя переходов. Это либо включить механизмы, либо выключить, либо никаких действий.
Создание аналогично событиям, но теперь наследуемся от интерфейса itfAction ну и в методе будем прописывать необходимые действия.
Логика
Как в этому системе будет работать логика. 1)Мы нарушим парочку рекомендаций от PLCOpen 2) Будем обходить все по циклу 3)Если нынешнее состояние системы будет соответствовать одному из списка то проверяем события. 4)если они выполнены то выполняем действия и переходим на следующую стадию 5)Если нет идем дальше

Подготовка объектов
А теперь нам требуется собрать весь этот конструктор в какую-то одну вменяемую структуру.
Я предлагаю в данном случае воспользоваться возможностями глобальных данных.
1)Создадим экземпляры для всех ФБ и необходимые переменные.

2)А теперь нам надо описать каждый из 10 переходов.

Вот так туда все это и заполняется. Весьма долгий первоначальный процесс.
3)Формируем массив опроса.

4) Ну и где-то в программе исполнения делаем запуск этого безобразия

И тут я компилирую и у меня выползает 11 ошибок, но мы их исправляем.
Теперь можно грузить ПЛК и проверять. Щас только напишем визуализацию)))
Вывод
Весьма удобный способ управления конечными состояниями. Долгий в реализации. Не щадит по памяти, но если ее достаточно и система имеет много состояний то велком. А главное легко масштабируется.
Если есть вопросы, пожелания, претензии велком или в комментарии или на почту: info@engcore.ru
GIT: https://github.com/sudak-91/StateMachine-for-PLC.-Codesys-3.5
