Наконец‑то мы добрались до конечной цели — графики, которая достаточно близко к реальности моделирует интересующие нас объекты. Речь пойдет об объектах систем управления (СУ). Это датчики, переключатели, индикаторы, моторы, конвейеры, объекты типа рассматриваемой нами гильотины и т. д. и т. п.
Создание заготовки проекта
Пойдем проторенным путем, когда из заранее подготовленной конфигурации будем копировать объекты. Но сначала из проекта ExampleGuillotine, созданного в предыдущей части [1], создадим конфигурацию, которую назовем GuillotineSimulation. Как это делается мы уже представление имеем.
Удалим из «заготовки» проекта объекты из пространства Models и их визуализатор — ViewButtonsAndGuillotine из SysDlg. Они больше не понадобятся. Здесь же удалим InputCanals и Schema. Их мы позаимствуем позже уже из донорской конфигурации.
Копирование автоматов
Выберем для копирования донорский проект — конфигурацию Guillotine2Src. В первую очередь перенесем из ее пространства ViewTrends автоматы графических окон: окно для элементов гильотины — VC_Guillotine и окно для пульта управления — VC_ControlPanel. Они откроются сразу же по мере их копирования.
Из пространства FsaWorld2 «донора» скопируем графические элементы (далее их будем также называть контролами). Это нож гильотины — CS_GuilKnife, датчики гильотины — CS_SnsDown, CS_SnsUp и кнопка запуска гильотины — PB_Guillotine. Их графические образы будут отображаться по мере переноса (отображение происходит просто потому, что они уже настроены на перенесенные окна графики, а их настройки копируются вместе с самими объектами).
Добавим также новую модель гильотины (ее подробно мы рассмотрим далее). Для этого переходим в пространство Models и копируем модель гильотины — ModelsGuillotine, а из пространства SysDlg визуализатор — ViewModelGuilotine2. Отсюда же скопируем InputCanals и Schema, которые мы удалили выше. При этом откроется диалог входных каналов, имеющий вид, как на рис. 1. В нем будет убрана лишняя информация и останется только наиболее существенное — управление режимом работы гильотины, задержками и датчиками гильотины.
Пересечение контролов
Одна из фишек текущего проекта, да и собственно имитационного моделирования в рамках ВКПа, это определение моментов пересечения образов контролов. Аналог этому в реальной жизни, например, пересечение светового потока от датчика оборудованием. А в тех же игрушках подобное сплошь и рядом: наезд на препятствие, поражение объекта выстрелом, алебардой или чем там они еще воюют и т. д. и т. п. Следовательно, актуальность в подобной функциональности не подлежит сомнению. Ведена она и в ВКПа — компонента FCommWithSensors в библиотеке fsagdip.
Итак, из пространства Sensors копируем автоматы, которые определяют моменты пересечения графических образов. В данном случае — ножа с датчиками. Это автоматы: WS_InstSnsDown для нижнего датчика и WS_InstSnsUp — для верхнего датчика, созданные на базе упомянутой выше компоненты. Их настройки показаны рис. 2.
Контрол, по отношению к которому определяется пересечение, помечается флагом Active. Имя переменной, которая будет установлена при пересечении образов и сброшена в обратном случае указывается в локальной переменной автомата — strNameSensor (см. настройку автоматных переменных на рис. 3). В нашем случае это локальные переменные snsDown и snsUp процесса Sensors2.
Схема приложения
Для удобного и быстрого доступа к элементам конфигурации в ВКПа можно использовать, так называемые, «картинки» (в среде ВКПа их можно открыть две). Они созданы на базе визуализатора состояний автоматов. Вызвать, например, картинку, представляющую схему приложения, можно через меню среды ВКПа Fsa‑ инструменты /Картинки/Схема приложения. Внешний вид схемы готовится в графическом редакторе, путь к которому указывается в настройках визуализатора (см. рис. 4). Также через диалог настройки к «картинке» прикрепляются компоненты проекта. В результате к ним можно получить доступ. Это гораздо удобнее, чем помнить в каком пространстве объекты находятся.
Выше мы объект схемы — Schema уже скопировали. А поскольку он был настроен в «доноре», то теперь его достаточно вызвать, чтобы открыть объект модели гильотины — ModelGuillotine, а уже через него — визуализатор модели.
Модель гильотины
Граф модели гильотины имеет вид, показанный на рис. 5.
По команде движения вниз (предикат x1) координата образа ножа — FC_GuilKnife.y увеличивается на значение скорости перемещения — nSpeed, а модель при этом находится в состоянии 1. По команде движения вверх — x2 автомат переходит в состояние 0, а текущая координата уменьшается. При отсутствии команд — условие ^x1^x2 автомат перейдет в состояние 2 и координата ножа перестанет изменяться. Из состояния 2, когда поступит новая команда — x1 или x2, автомат перейдет в соответствующее состояние, т. е. 0 или 1.
Модель гильотины может быть даже проще — рис. 4. Тем не менее, функционально она будет эквивалентна первому алгоритму, но только ее текущее состояние уже не будет отражать состояние гильотины.
Тестирование проекта
Приведем вид приложения к виду, показанному на рис. 7. Теперь у нас есть возможность запустить гильотину с помощью кнопки импровизированного пульта управления. При этом, используя диалог входных каналов, можно управлять режимом, переключая с автоматического на ручной и обратно. Можно также изменять значение задержек, а, изменив дискретное время пространства Models, повлиять на скорость работы гильотины.
Создадим аварийную ситуацию, когда оба датчика активны. Для этого датчик нижнего положения переместим вверх, установив координату по вертикальной оси равной 180. Делаем это через диалог настройки окна гильотины, выбрав датчик нижнего положения гильотины. Запускаем гильотину, а она ... работает?! Этого не должно быть. Причем во время подъема гильотина приподнимется выше исходного положения и ошибка будет фактически скомпенсирована. У реальной гильотины это, скорее всего, будет по-другому. Зафиксируем возникшую проблему.
Сымитируем еще одну аварию - превышение времени работы. Для этого опустим датчик до y=250 и увеличим дискретное время пространства Models в 10 раз. Убеждаемся, что в состоянии 4 система управления явно не контролирует время работы гильотины, что не правильно. При этом в состоянии 2 такой контроль осуществляется. Запомним и это.
Из состояния ошибки гильотина выводится нажатием кнопки Start. После этого автомат переходит в состояние 2, выдавая гильотине команду движения вверх, где ожидается срабатывание датчика верхнего положения.
Индикатор аварийной ситуации
Проекту явно не хватает индикатора аварии. Перенесем его из "донора" - проекта с именем Guillotine2S. Из его пространства FsaWorld2 скопируем автомат CS_AlarmPress. В отличие от предыдущих объектов, он не отображается. Чтобы это произошло, ему нужен сигнал управления - входной сигнал. Его будем получать от элемента ИЛИ, объединяющего признаки ошибок, который скопируем из пространства InitFsaWorld "донора". Это объект с именем Or1. Диалог его настройки показан на рис. 8, где сигнал управления индикатором аварии указан в поле адрес группы Выход.
Входными сигналами элемента ИЛИ являются две переменные, отражающие состояния аварии (по умолчанию это состояния с именем 33), которых у нас пока еще нет. Создадим их для автоматов GuillotineCtrl и Sensors2.Это будут локальные переменные с именем (33) типа fsa(state).
Вставляем индикатор ошибки в импровизированный пульт управления. Получаем - рис. 8.
Тестируем гильотину на превышении паузы (см. выше). Видим, что индикатор авария загорается (отображается желтым цветом) только при движении гильотины вверх. Повторное нажатие кнопки ошибку снимает, поскольку автомат покидает состояние 33 и переходит состояние 2.
Коррекция алгоритмов
Выше в СУ гильотины были обнаружены недочеты. Их мы исправили, создав проект Gullotine2S. Он показан на рис. 9. Изменения, коснувшиеся моделей, выделены красным цветом. Индикатор аварии горит, т.к. автомат управления датчиками - Sensors2 находится в состоянии 33. Теперь можно проверить, как работает гильотина в разных режимах. В том числе и в аварийных ситуациях.
Создадим ситуацию, когда гильотина находится изначально в промежуточном положении... Легко! Однако, раздвинуть датчики - полдела: проект "завис" в состоянии 2 автомата Sensors2. Это не очень радует, т.к. только по внешнему виду проекта не определить проблему, которая явно есть: индикатор ошибки не горит, а движения гильотины нет сколько не жми на кнопку запуска гильотины! Похоже, нужно как-то "перевести стрелку" из состояния 2 в состояние аварии 33.
Учтя сказанное, создадим новый проект Gullotine2S_1, в котором из состояния 2 введем переход в состояние аварии по условию ^x3^x4x5. Однако, ... индикатор активно заморгал?! Дело в том, что автомат Sensors2 из состояния 2 переходит в 33 и тут же возвращается обратно (см. граф автомата Sensors2). Т.е. индикатор исправно реагирует на "посещение" состояния 33, но при этом создается цикл между состояниями пока гильотина находится в промежуточном состоянии. Причем гильотина по-прежнему не подчиняется кнопке!
Поскольку задержка маленькая, то "заходы" в состояние 33 будут даже при нормальной работе гильотины. Введем еще одну задержку - время перемещения гильотины. Для управления ею добавляем в автомат Sensors2 сигнал ее запуска - локальную переменную bStartDelay2. Затем добавляем модель задержки в пространство TimerModels. Значение самой задержки может быть достаточно длительным (с запасом по отношению к времени перемещения гильотины). Нужно также не забыть добавить предикат в Sensors2, проверяющий сигнал запуска задержки, и, конечно, действие по его установке.
В результате таких манипуляций автомат Sensors2 примет следующий вид (рис. 10):
На графе автомата изменения выделены красным цветом. По сравнению с исходным вариантом в автомат Sensors2 было добавлено состояние ошибки - 33 и переход в него при одновременно уставленных датчиках, а также выходы из него. Ну и, конечно, наиболее значимые изменения связаны с введением еще одной задержки и управления ею - это предикат и действия, а также сама модель задержки.
Для понимания работы алгоритма поясним работу действий y5 и y6. Они работают с локальными переменными, имеющими тип Out. Данный тип - имитация операции типа OUT, характерной для ПЛК. Переменная этого типа при переходе в состояние, к которому она приписана, устанавливается в единицу, а при выходе из него сбрасывается в ноль. Таким образом, при переходе в состояния 2 и 33 переменные bStartDelay и bStartDelay2 принимают единичное значение, в других - нулевое. В результате сигналы запуска задержек сбрасываются, с одной стороны, моделями задержек, а, с другой стороны, переходами в другие состояния (состояния 0, 1).
Окончательный вид проекта в форме нового проекта Guillotine2S_2, в котором учтено все что можно (на текущий момент, конечно) показан на рис.11. Теперь, если замечаний нет, можно приступать и к преобразованию его в код для ПЛК.
Например, как описано в статье [1].
Заключение
Мы не рассматривали создание донорских проектов. Данный процесс во многом аналогичен рассмотренному. Только, если, например, выше мы из «донора» почти мгновенно переносили готовые объекты, то в рамках донорских проектов на их настройку затрачивается определенное время. Оно не такое значительное, да и сами по себе их настройки достаточно просты и интуитивно понятны. Например, — установить координаты графических элементов, указать пути к х графическим образам, установить размеры и т. п.
Признаюсь, я испытываю удовольствие от работы с автоматами в ВКПа. Это чувство многократно укрепляется после знакомства со статьями, посвященными проблемам современного параллельного программирования. Да, я не оперирую сотнями тысяч и миллионами процессов, но для большого числа задач, если не подавляющего числа реальных задач вообще, этого и не надо. Обычно их число не превышает нескольких сотен (см. примеры ниже) и этого вполне хватает, чтобы обеспечить необходимое качество управления. Одновременно я, оперируя взаимодействующими (!) процессами, не испытываю нужны в «совершенных» механизмах этого самого современного параллелизма, от слова совсем. Может, это плохо. Но сам я так, конечно, не считаю. Хотя есть опыт использования многопоточности и планы как‑то ее использовать, но, если уж честно, то не до этого, т.к. пока хватает того, что есть. А на то, чтобы просто «лопатить код» нужно время, желание и, главное, необходимость.
Основную нагрузку на процессор создает графика. Когда ее нет, то фактически нет и проблем со скоростью. Так, созданный нами проект в окончательном виде со всеми открытыми диалогами и окнами графики (см. к примеру рис.7) имеет минимальную длительность такта 5 мсек, а при полном их закрытии — 0.5 мсек. А если еще аккуратно подчистить проект от лишних процессов, то время падает до 0.15 мсек. Измерено на Intel Core™ i5–2400 CPU @2.50GHz. А, если поискать, то можно найти и еще резервы... Все это к тому, чтобы показать, что скорость программы во многом зависит от интерфейса, ну и, безусловно, от числа параллельных процессов. Но при их числе до несколько сотен для систем управления реальными объектами их влияние на скорость во многих случаях не столь существенно.
Литература
ВКПа. Введение, ч. 2. Копирование автоматов и начала имитационного моделирования. [Электронный ресурс], Режим доступа: https://habr.com/ru/articles/795953/ свободный. Яз. рус. (дата обращения 24.02.2024).
Технология автоматного программирования для ПЛК на языке LD.. [Электронный ресурс], Режим доступа: https://habr.com/ru/articles/690690/ свободный. Яз. рус. (дата обращения 21.11.2023).
P.S.
В рамках обсуждения предыдущей статьи было высказано мнение, что, мол, «это не учебные программки про гильотина создавать, тут намного все сложнее». Не затрагивая тему сложности алгоритмов, поговорим о числе процессов и проблемах имитационного моделирования, сравнив учебные и реальные решения. Так ли уж существенна разница?
В СУ гильотины параллельных процессов чуть более 40. При этом это не учебный проект, а часть вполне реального. Из их числа всего лишь два объекта реальные — автомат управления гильотиной и автомат датчиков. Остальные — «обслуга» для процесса проектирования: системные процессы среды ВКПа, графические элементы, модели самих объектов, индикаторы, кнопки и т. д. и т. п. Многое из этого будет использовано в аналогичных проектах. А потому, чем больше опыт, тем меньше затраты на проектирование.
Исходя из соотношения рабочих процессов и «обслуги», очевидна проблема сложности имитационного моделирования. Поэтому в реальной жизни программистов «натурное программирование» зачастую единственный подход к проектированию промышленной системы. При этом понятно, что самолет и линия прокатки — явно разные по сложности примеры систем. Потому‑то для разработка авионики давно ведется на моделях и/или на специализированных стендах и тренажерах. Но и в случае линии проката работа на ней без оглядки на экономию металла рано или поздно вызовет к программисту вполне обоснованные вопросы.
Поэтому, если под рукой есть среда, позволяющая реализовать с малыми затратами имитационное моделирование, то вам, без сомнения, крупно повезло. Например, в моем случае, комбинация имитатора пульта управления, энкодера и имитация датчиков позволили организовать почти весь процесс проектирования, не выходя буквально из‑за стола. И лишь какие‑то вещи, и не столь уж часто, приходилось дорабатывать на реальном оборудовании.
Но одно дело — разработать модель, залить ее в ПЛК, а затем протестировать на импровизированном стенде, и совсем другое — проектирование на программном имитаторе объекта. Последние можно загнать в любой режим, не боясь повредить и без оглядки на экономию металла. Выше, на примере гильотины, это показано, надеюсь, достаточно убедительно. В нашем случае были выявлены проблемы, пропущенные при проектировании с применением стенда. Заметим, не такого уж сложного объекта.
Удобство — одна из причин популярности систем визуального проектирования. Другое дело,что не все они позволяют проектировать на лету и в реальном времени. Для ВКПа это, зачастую, ее обычный режим работы. Другие подобные системы, каюсь, мне не известны. Попробуйте убедить в обратном.
И еще. «Ходят слухи тут и там», что программистов скоро заменят нейронки. Не верю я в это. От слова совсем. Причем, и на это указывают многие, даже ясно почему. Тем не менее, хотелось бы ей (нейронке) задать буквально пару вопросов. Итак, что ей известно про автоматное программирования? А каким будет будущее программирование? Не общими словами — типа ля‑ля, а конкретно — строго сформулировать вычислительную модель будущего? Если кто может — задайте. Посмотрим. Тем ли мы занимаемся?
Или, может, нейронка уже сейчас способна предъявить (по простому запросу!?) программный код среды — аналога ВКПа? Было бы интересно сравнить. Ну, очччень любопытно! А то мы уже озаботились на самом Высоком уровне развитием «генеративных нейронных сетей» и собираемся «влить» туда просто немыслимые суммы. Чтобы — зачем? В очередной раз «попилить» и/или «вляпаться»?
Ниже приведены примеры реальных и учебных проектов, созданных в ВКПа, с указанием числа параллельных процессов. Можно ли после этого утверждать, что учебный проект заведомо проще реального? А может ли уже сейчас или в обозримом будущем «генеративная нейронка» создать аналоги?