Времена нынче суровые. Откуда «прилетит» непонятно, но то, что «прилетит», сомневаться уже не приходится. Вот оно и … «прилетело». В связи с определенными обстоятельствами (возможно, вы даже догадываетесь какими) предложено рассмотреть переход с ПЛК фирмы Delta на ПЛК от Haiwell. Мы, как говорится, и не такое переживали, а потому качаем среду проектирования HaiwellHappy и пытаемся ее освоить. Самих ПЛК, хотя они уже заказаны (?!), пока нет, но есть симулятор. Но для начала этого вполне достаточно…
Путь проторенный. А потому в целях обучения и одновременно внедрения технологии автоматного программирования создаем – что? - правильно, модель RS-триггера. Почему? – см. статью [1]. Но, если кратко, то триггер - это фактически мизерный проект, от которого пользы – ну, просто туча. В этом и предстоит далее убедиться.
Однако, смотрим, на что же позарились наши менеджеры?… Цена ПЛК – хорошая! Ну, то есть – относительно небольшая. Для нормального менеджера этого, видимо, уже достаточно. Но работать-то – программистам! Ставим среду и создаем наш первый проект. Это, как уже было сказано, модель реального RS-триггера.
Оставим в стороне всякие мелочные придирки к среде проектирования (обсудим их по ходу), а приведем сразу код проекта. Благо он, как уже было тоже сказано, мизерный. Его внешний вид приведен на рис. 1.
![Рис. 1. Проект RS-триггера в среде HaiwellHappy Рис. 1. Проект RS-триггера в среде HaiwellHappy](https://habrastorage.org/getpro/habr/upload_files/8b8/98a/5d1/8b898a5d1f0ae57e8618b4f7c68c7eda.png)
Рассмотрим код составляющих проект частей. Основной код – PGB FlipFlop, представляющий собственно модель RS-триггера, уже приведен. Он выше на рис. 1. Код PGB CopyStates, копирование состояний автоматов, демонстрирует рис. 2, код модели элемента И-НЕ – подпрограмма AND-NOT (тип модуля Sub) рис. 3, а код инициализации проекта - Initializase представлен на рис. 4. Поясним нюансы их создания.
Поскольку типа данных «массив» в языке обнаружено не было (после ПЛК Delta это уже странно), принято решение моделировать массивы диапазонами переменных типа INT. Пусть адреса переменных от 0 до 49 будут текущие состояния, а от 50 до 99 – теневые (резервируем для 50-ти автоматов). В рассматриваемом проекте используются состояния с «индексами» 0 и 1. Отражая это, выглядят коды, составляющие проект. Инициализация устанавливает в начальное состояние массивы, делая это один раз при запуске ПЛК, а PRG-модуль CopyStates копирует теневые состояния в текущие состояния на каждом цикле ПЛК.
![Рис. 2. CopyStates Рис. 2. CopyStates](https://habrastorage.org/getpro/habr/upload_files/cc3/a69/e6f/cc3a69e6f619e3c49a976165abdecaa4.png)
![Рис. 3. Модель элемента И-НЕ Рис. 3. Модель элемента И-НЕ](https://habrastorage.org/getpro/habr/upload_files/0f5/f0e/30f/0f5f0e30f0a2818ab0e50ce5bfcb2ee5.png)
![Рис. 4. Диалог создания локальных переменных ФБ Рис. 4. Диалог создания локальных переменных ФБ](https://habrastorage.org/getpro/habr/upload_files/d7d/dec/153/d7ddec153c5c19c370daa93824862b4e.png)
Локальные переменные, входные и выходные каналы функционального блока (ФБ) модели элемента И-НЕ представлены диалогом на рис. 4, в рамках которого они и создаются.
Тестирование
Запустив симулятор, получим первые результаты, которые представлены на рис. 5. Ожидается явно не то (при нулевых значениях входов – X0, X1 выходы триггера – Y0, Y1 должны быть в единичных состояниях). А это грубая ошибка и дальше можно не продолжать тестировать, а сразу заняться поиском проблем. Тем не менее, ради любопытства попробуем поиграть входами. Ели это будет 0, 1 (X0=0, X1=1), триггер войдет режим генерации (какой ужас!). Более того, значение входов 1, 1 не повлияет на этот безобразный «дребезг». Входы 1, 0 приведут, правда, в устойчивое состояние 0, 1 (Y0=0, Y1=1), а состояние входов 0, 0, которое уже было при запуске проекта, состояние выходов триггера не изменит (см. рис. 5). Таким образом, в единичное устойчивое состояние (Y0=1, Y1=0) наш триггер никак не попадает. Таким образом, у нас получился явно «ненормальный», можно даже сказать, «взбесившийся», RS-триггер.
![Рис. 5. Запуск проекта в режиме симуляции ПЛК Рис. 5. Запуск проекта в режиме симуляции ПЛК](https://habrastorage.org/getpro/habr/upload_files/cc7/d39/595/cc7d3959585b238d9bdaf4799d7dcf29.png)
В порядке эксперимента создадим еще одну модель элемента И-НЕ. Такую же, как и первая. Сразу же выясняется, что в отличие от ISP Soft Delta, мы не можем просто так размножить модель. А кто обещал, что будет легко? А потому – закатываем рукава. Создав по новой еще одну модель, тестируем проект уже с ней в составе. Получаем фактически тот же результат.
Что опять не так? При этом, заметим, в качестве второго входа ФБ выступает номер состояния. Мы не рассматриваем результаты с логическим типом второго входа триггера. На самом деле это были самые первые эксперименты, но они были столь же неудачными, а потому был сделан переход к более надежному коду.
И тут, надо признаться, наступил полный ступор. Но сдаваться - не наш вариант. Известно, что «даже отступая, мы всегда идем вперед». Поэтому попробуем изучить код на языке IL. Благо в среде есть соответствующая конвертация.
Такой код приведен на рис. 6. В чем-то он только больше запутывает, т.к., с одной стороны, каких-то проблем не видно. А, с другой стороны, он «подсказывает», что с помощью оператора CALL можно создать два одинаковых ФБ из одной подпрограммы (см. Sub program). Может, создание копии элемента было лишним? Но что это меняет, а потому … если уж создали, то пусть пока будет. Там посмотрим, что с ним делать, т.к. удалить, как убеждает практика работы со средой, все же будет проще, чем создавать еще раз то же самое.
Путем «плясок с бубном», методом «научного тыка» и еще какой-то там «матери» было выявлено, что переменные, подключенные к выходным каналам ФБ (тип переменных OUT), сбрасываются подпрограммой в ноль даже, если не используются в процессе работы блока. А это меняет окружение подпрограммы, даже если по логике работы она не должна его менять. Выход был найден следующий: не использовать выходные каналы, а устанавливать переменные (теневые состояния) напрямую в ФБ.
![Рис. 6. Код проекта на языке IL Рис. 6. Код проекта на языке IL](https://habrastorage.org/getpro/habr/upload_files/26b/f4d/621/26bf4d62183af32167fde83418088e73.png)
Это явно не лучшее решение, но другого придумано не было. И теперь код RS-триггера стал таким, как на рис. 7 (показан в режиме отладки), а коды отдельных элементов И-НЕ представлены соответственно на рис. 8 и рис. 9. И в таком виде модель триггера заработала «как часы».
![Рис. 7. Новый код проекта в режиме отладки Рис. 7. Новый код проекта в режиме отладки](https://habrastorage.org/getpro/habr/upload_files/b45/20e/966/b4520e9663822cf80f27191b65bd91c1.png)
![Рис. 8. Код первого элемента И-НЕ в режиме отладки Рис. 8. Код первого элемента И-НЕ в режиме отладки](https://habrastorage.org/getpro/habr/upload_files/0ea/7aa/cd9/0ea7aacd95aa95ac49f6f442e5bc885f.png)
Выводы
С одной стороны, мы поставленную задачу решили. Не сказать, чтобы решение удовлетворяло, т.к. использование теневых состояний внутри блоков все же нарушает принципы блочного программирования. Использовать одну подпрограмму для создания на ее базе нескольких ФБ уже не получится. Поэтому, кстати, интуитивно мы правильно поступили, когда не удалили модель второго элемента И-НЕ. Но, может, есть другое решение? Пока что-то путное в голову не приходит.
В целом переход на ПЛК Haiwell восторга не вызывает. По многим причинам. Чем-то можно, конечно, поступиться, но что-то явно не дотягивает до целей эффективного и удобного программирования. А это уже настораживает, если не сказать - отторгает. И даже простое сравнение объемов кода среды HaiwellHappy с объемом кода ISP Soft для ПЛК Delta явно указывает на их совершенно разные возможности. Детали перечислять просто не имеет смысла, да и не входит в цели статьи.
Не хочется, как говориться, возводить напраслину, но первое впечатление от ПЛК Haiwell именно такое… - негативное. Но, если бы не RS- триггер, думаю, в этом было бы разобраться, а уж, тем более, что-то доказать, сложно. А тут, как говорится, все по полочкам.
А вы говорите – RS-триггер, RS-триггер… Ну, RS-триггер! А вы можете предложить более простой и эффективный вариант? Или хотя бы пример, аналогичный ему по возможностям? Только не надо про этот, как его, … «Hello, World»!