Технологии и методы тестирования и отладки щитов с автоматикой на ПЛК (Обработка IO, Тест IO, Имитация IO)

Проекту исполнилось 15 лет! Поддержать проект материально, проспонсировать проекты Автора или сделать ему подарок можно на этой странице: "Донаты и Спонсорство, Список Желаний".

Число просмотров: 16 148 

Щиты с автоматикой для квартиры в режиме тестирования IO (все нагрузки включены)

Щиты с автоматикой для квартиры в режиме тестирования IO (все нагрузки включены)

Этот пост зрел у меня, потому что я много раз на форуме ОВЕНа слышу «А вот как быть, если ошибки связи с устройствами иногда появляются, но на них надо реагировать только тогда, когда они идут часто, а случайные пропускать?». Ещё я заметил, что мало кто считает общую мощность потребления по +24V, чтобы правильно выбрать блок питания, и ещё заметил то, что когда я говорю о том, что тестирую щиты в режиме прогрева, включая все нагрузки на постоянную работу на неделю (например), то на меня на форуме ОВЕН смотрят как на идиота. А ведь эта идея стырена из старых шкафов автоматики, где была кнопка «Проверка ламп»! А ещё ведь надо защищать внешние цепи щита, бэкапить проекты… Уууу! Оказалось, что мало кто это делает.

В общем, после проклятого проекта Mail.Ru на СПК (про него я написал тут; я там и очередного коллегу-напарника выгнал нахер) у меня набралась куча материала и опыта, который я и расскажу в этом посте. Код программ на ПЛК я давать не буду, так как он у меня является моей интеллектуальной собственностью. Однако тех скриншотов и описаний, которые будут в посте, хватит для того, чтобы вы могли разобраться в алгоритмах и написать свой код под свои задачи. Часть опыта была наработана на щитах с Siemens Logo (все посты про него), часть — на щитах с ОВЕНом (все посты про ПЛК и про ПРки).

Ещё напомню вам пост о том, что должно быть в щитах с ПЛК. Там я упоминал разные монтажные мелочи, которые надо учесть при разработке таких щитов. А ещё сошлюсь на статью Евгения Кислова про отладку проектов в ПЛК и примеры разных багов, в том числе и идиотских. И ещё рекомендую его же статью про работу с системными журналами в ПЛК, на которую я буду ссылаться.

Содержание

1. Защита внешних и внутренних цепей щита предохранителями.

Первое, с чего я начну — это самое важное. Защита всех внешних цепей щита от замыкания или перегрузки. Эта задача — архиважная, и вот почему.

Во-первых, вы защищаете выходные элементы, при помощи которых ПЛК чем-то управляет. Это крайне важно делать, если вы используете транзисторные выходы (пост про такие выходы) для управления подсветками кнопок (пост про кнопки тут). Подсветки кнопок используются для тех случаев, когда ПЛК должен ими мигать или ещё каким-то образом показывать состояние автоматики: тёплого пола, вентилятора санузла, мастер-кнопки света или воды.

У ОВЕНа на одну группу из четырёх транзисторных выходов максимальный ток ограничен всего в 500 мА. Если начать потреблять больше — модуль ввода-вывода (общий пост про модули ввода-вывода от ОВЕН) выйдет из строя. И вы попадёте на ремонт, а щит будет простаивать…

Во-вторых, есть куча нерадивых монтажников, которые пытаются подключать щит тогда, когда он уже работает, и автоматика включена. Если на какой-то линии есть плюс и минус напряжения питания (+24V и GND), то нерадивые монтажники могут их случайно замкнуть.

Такое замыкание приведёт к трём вариантам:

  • Мощный блок питания не уйдёт в защиту, и будет подавать питание и дальше. Ток от блока питания, протекающий по линии с замыканием, будет её греть и сожгёт к чертям.
  • Блок питания уйдёт в защиту, и отключит весь щит, включая ПЛК, который от него же и питается.
  • Сгорит элемент, который управляет этой линией (реле или транзистор).

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

Лично я сталкивался и слышал про такие ситуации:

  • Мутный заказчик насобирал щит сам (я его послал из-за мутности) так, что перегрузил и сжёг транзисторные выходы в модуле дискретного вывода.
  • Тупые монтажники моего щита в ЖК HeadLiner развели кнопки витой парой и, подключая их, закоротили цепи питания. Заказчик звонил: «ПЛК завис, на кнопки не реагирует почему-то, а лампы горят». Заменили предохранитель — всё и заработало.
  • К заказчику в Долгопрудный, куда я собирал щит с управлением светом на импульсных реле (большой сборный пост про них), приехала бабушка. Она никогда не видела кнопок и импульсных реле, и ей показалось, что выключатели «отходят» и не держатся в нажатом состоянии. Ну, она и подсунула под них бумажки, чтобы свет горел.
    Парочка импульсных реле поджарилась и создала внутреннее замыкание в обмотке, от чего стала потреблять бОльший ток. Предохранитель в щите вовремя сгорел, а заказчик тоже звонил мне про «Чего-то в Гостиной кнопки не работают».

Для защиты всех цепей в своих щитах я использую клеммы с предохранителями (вот пост про них). Перед всякими санкциями я стал заказывать обычные серые для цепей AC 230V и оранжевые для цепей DC 24V. Выглядит это вот так:

Системные клеммы щита: для тестирования IO и для защиты внешних цепей (с предохранителями)

Системные клеммы щита: для тестирования IO и для защиты внешних цепей (с предохранителями)

Достоинства и приятности клемм с предохранителями вот в чём:

  • Они компактные. Клемма в среднем занимает по ширине 0,5 DIN-модуля (8 мм), что компактнее автомата;
  • Предохранители есть на очень малые номиналы — например на 0,1 или на даже 0,05 ампера (можно защитить вход или выход сигнала 4..20 мА). На автоматах такое не сделать вообще;
  • По стоимости клемма и предохранители дешевле автомата на такой же номинал;
  • Предохранители бывают быстродействующие, что нужно для электронных выходов, например, с твердотельными реле;
  • На время пусконаладки клемму можно открыть, и цепь, которую она защищает, отключится.

Что я защищаю предохранителями:

  • Все внешние цепи питания +24V, даже если они идут на датчики «Сухой Контакт» (напоминаю пост про них). Это позволяет отключать такие датчики и их цепи на время пусконаладки, чтобы они ложно не срабатывали;
  • Цепи питания кнопок управления светом и другими функциями. Логика — та же: отключить на время пусконаладки и защитить от короткого замыкания;
  • Цепи питания и входов датчиков 4..20 мА;
  • Цепи выходных сигналов 0..10V;
  • Цепи питания +24V датчиков Modbus и других внешних устройств (панели оператора, например);
  • Цепи исполнительных механизмов типа электромагнитных клапанов.

Для пользователей моих щитов в CS CRM (все посты про неё) в автоматически создаваемых инструкциях к щитам (пост про эту технологию) сделан целый пункт, посвящённый клеммам с предохранителями:

Фрагмент инструкции для клемм с предохранителями, где показано их использование (CS CRM)

Фрагмент инструкции для клемм с предохранителями, где показано их использование (CS CRM)

А в документации на щит автоматически генерируется таблица таких клемм, которая содержит их маркировку, номиналы, вид питания и пояснение.

Пример таблицы клемм с предохранителями с их номиналами и назначениями (CS CRM)

Пример таблицы клемм с предохранителями с их номиналами и назначениями (CS CRM)

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

2. Документирование сигналов ввода-вывода по модулям IO.

Раз уж я затронул документацию к щитам с автоматикой на ПЛК/ПР, то сделаю небольшой раздел про то, как я проектирую и оформляю таблицы сигналов ввода-вывода к своим щитам.

Мой процесс проектирования щита происходит так: я беру Excel и выписываю на один из листов все входные и все выходные сигналы в столбцы. После этого считаю их количество, примерно оцениваю количество модулей ввода-вывода и копирую эти сигналы на другой лист, где у меня нарисованы ячейки шаблонов под разные ПЛК и модули ввода-вывода, сразу привязывая сигналы к нужным каналам.

Вот пример такой таблицы для готового щита. Здесь показаны входы и выходы ПЛК110:

Пример таблицы сигналов ввода-вывода для ПЛК с их назначением в щите

Пример таблицы сигналов ввода-вывода для ПЛК с их назначением в щите

Удобство этой таблицы для меня в следующем:

  • Наглядно видно, какие входы и выходы сгруппированы по общим контактам «SS» и «COMx» (у модулей ввода-вывода ОВЕН входы и выходы группируются по 4 штуки). Например, я могу подать на сигналы «SS» нужных групп входов напряжение +24V и сделать так, чтобы эти входы активировались сигналом «Открытый Коллектор» — замыканием на GND (пост про такие сигналы). Это сразу будет видно в таблице (пример — ниже).
  • Можно копировать названия сигналов в комментарии к проекту ПЛК прям отсюда, включая номера входов и выходов.
  • В простых проектах можно прозвонить кабель кнопок, в котором одна общая жила и по жиле на каждую кнопку, не пользуясь тестером: замыкать жилу с общей и смотреть, светодиод какого входа включается.
  • Собирать по ней щит, так как в ней указано то, куда или откуда идёт сигнал в щите: клемма, реле, контакт.

Вот продолжение таблицы для модулей входов и выходов. Здесь как раз наглядно видна группировка входов по SS так, чтобы входы с 21 по 32 срабатывали от GND.

Пример таблицы сигналов ввода-вывода для модулей IO с их назначением в щите

Пример таблицы сигналов ввода-вывода для модулей IO с их назначением в щите

3. Расчёт мощностей блоков питания. Разделение блоков питания.

А раз мы затронули проектирование щитов с автоматикой, то не лишним будет упомянуть и то, что для цепей +24V необходимо считать мощности всех потребителей и подбирать блоки питания так, чтобы они укладывались в эту мощность.

Я беру максимальные потребляемые мощности из инструкций к оборудованию и свожу их в табличку, а потом распределяю их по блокам питания. Табличка использует формулу «СУММЕСЛИ», которая суммирует значения в ячейках по заданному условию. Поэтому я могу онлайн распределять нагрузки по блокам питания, сразу видя их суммарную мощность.

Пример расчёта мощности для всех элементов автоматики щита

Пример расчёта мощности для всех элементов автоматики щита

Здесь мы видим, чтто один блок питания нагружен на 133 Ватта, а другой — на 78 Ватт. Значит, можно использовать компактные и мощные блоки питания Mean Well серии HDR (пост про все блоки питания Mean Well), которые отлично ставятся на DIN-рейку, а их максимальная мощность — 150 Ватт. Здесь можно применить два блока питания: на 150 и на 100 Ватт.

Крайне важно правильно выбирать мощности блоков питания так, чтобы их точно хватило на питание всего оборудования. Дальше в посте я буду рассказывать про режим тестирования всего IO, который как раз и нужен для того, чтобы включить все-все-все нагрузки и выходов ПЛК в щите и тем самым дать максимальную нагрузку на блоки питания.

А ещё важно разделять некоторые нагрузки и цепи в щите по разным блокам питания, если щит сложный и должен быть очень надёжным.

Во-первых, стоит отделять внутреннее питание ПЛК и его модулей ввода-вывода от внешнего питания разных нагрузок. Если мощности компонентов в щите позволяют использовать блоки питания на 100 и 150 Ватт (не больше их), то я делаю так, как показано в табличке мощностей выше: все реле и внешние нагрузки щита выношу на отдельный, второй, блок питания. Кросс-модули для этих питаний я делаю на базе трёхуровневых клемм (пост про них здесь), и если в щите есть два вида питания, то получается очень удобно: нижний уровень клеммы — это GND, второй — питание +24V, третий — питание +24R (Relay — реле).

Во-вторых, следует выделить на отдельный блок питания такие элементы, которые могут создавать помехи и выбросы напряжения при их работе. Это касается, например, мощных реле или электромагнитов (клапанов). На постоянном токе любой электромагнит во время его выключения из-за самоиндукции создаёт импульс высокого напряжения, который может сжечь некоторые чувствительные цепи. Например, цепь питания измерительного входа датчиков 4..20 мА.

У Bayk так было, когда входы и электромагнитные клапаны работали от общего блока питания. Нажал кнопку «Аварийный стоп», все электромагниты разом выключились, и датчики на аналоговых входах умерли.

Вы знаете о том, что в цепи питания электромагнитов включают диоды в обратной полярности (минус — к плюсу, плюс — к минусу), которые и должны принять на себя импульс напряжения от самоиндукции и погасить его. Для маленьких реле (серии ABB CR-P и CR-M и их аналогов; пост про такие реле) есть индикаторные модули с таким диодом внутри. Но иногда лучше и удобнее выделить отдельный блок питания под такие нагрузки, как я чаще всего и делаю.

В-третьих, обратная история: чтобы нам в щите что-то не сожгли. Например, я часто регулирую яркость света через аналоговые выходы 0..10V (напоминаю пост про выходы такого типа). В нескольких проектах я закладывал термоэлектрические приводы отопления Oventrop с сигналом управления 0..10V, и привод вентиляционной заслонки Belimo тоже с 0..10V.

Некоторые из этих устройств получают питание 230V, и клеммы силового питания и сигнала 0..10V у них расположены рядом. Какова вероятность того, что кто-то что-то не туда подаст? Если аналоговые выходы питаются от общего блока питания, то плохо может быть сразу всем элементам щита, включая ПЛК и модули ввода-вывода.

Можно запитать такие выходы от маленького блока питания Mean Well HDR-15-24 (на 15 Ватт), который будет не жалко. Да, вместе с таким блоком питания выгорит ещё и модуль аналоговых выходов — но не весь щит вместе с ПЛК.

4. Групповая обработка сигналов входов и выходов (битовые маски). Переменные IO.

Следующий вопрос, с которым я столкнулся — это то, как работать с сигналами входов и выходов в программах ПЛК. Так как я начинал программировать с Siemens Logo (все посты про них по тэгу) и с логических реле ABB CL (пост про них), то я привык к тому, что все входы и выходы в программе доступны в виде переменных по их номерам типа I1, I25, Q14 и так далее.

А ещё я привык давать переменным и объектам в программах понятные имена, и хотел бы, чтобы мои сигналы назывались не %I.W.1 или Q14, а «BtnMasterLight», «BtnLampKuhnaBra», «ValveHVSOpen» и так далее. В ПЛК на базе CodeSys можно создать свои переменные и привязать их к некоторым входам и выходам вручную. Это отлично!

Когда я программировал на CodeSys 2.3 в первый раз в 2016 году (вот пост про этот щит), то я столкнулся с тем, что встроенные входы и выходы ПЛК110 можно адресовать по отдельности в конфигурации ПЛК, а «внешние» входы и выходы (битовые маски с модулей ввода-вывода) надо разбирать побитно в коде программы, что ни фига не удобно и не наглядно.

Дерево конфигурации ПЛК на CodeSys 2.3, где видны плюсики на встроенных входах и выходах. Их можно развернуть и адресовать побитно

Дерево конфигурации ПЛК на CodeSys 2.3, где видны плюсики на встроенных входах и выходах. Их можно развернуть и адресовать побитно

Второе неудобство, с которым я столкнулся, следует из первого. Если у нас часть переменных для входов и выходов привязывается прямо в дереве конфигурации ПЛК или других устройств, а часть — в коде проекта, то будет сложно их искать и понимать, где что расположено. Ну, согласитесь со мной: хочется иметь один список, где будут все-все переменные ввода-вывода, а не рыться по разным местам проекта.

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

  • Константы — системные настройки проекта, которые не меняются никогда, но нужны для того, чтобы в коде не было магических чисел (статья про них в Википедии) — цифр, которые не очевидны, но используются в нескольких местах кода. При изменении таких цифр (значений) легко пропустить какую-то из них, и потом удивляться багам в работе.
  • Настройки — RETAIN-переменные с настройками разных режимов работы проекта для пользователя — время работы вентиляторов, время гашения экрана СПК, выдержка работы приводов кранов воды и так далее. Ещё тут могут храниться экземпляры FB для управления, например, освещением: тогда, если питание ПЛК пропадёт и снова появится, свет включится так, как был до отключения.
  • Ввод-Вывод — переменные и экземпляры функциональных блоков для всех устройств и каналов ввода-вывода проекта.
  • Важные значения — PERSISTENT-переменные, которые не должны сбрасываться при загрузке проекта в ПЛК. В них хранится время наработки устройств, статистика показаний с датчиков и другие значения, которые очень важны. Обычно память под такие переменные ограничена, поэтому я чаще использую RETAIN-переменные под множество не слишком важных значений.

Вот примеры переменных в моих проектах:

Списки глобальных переменных для удобной организации кода (в том числе для сигналов IO)

Списки глобальных переменных для удобной организации кода (в том числе для сигналов IO)

Благодаря такой технологии, все переменные в VarsIO будут идти по списку по группам примерно так:

Объявление переменных каналов модулей ввода-вывода для их будущей привязки

Объявление переменных каналов модулей ввода-вывода для их будущей привязки

Вот тут-то и сгодилась моя таблица в Экселе, из которой я могу скопировать все комментарии =)

А дальше я делаю лютый изврат, который помогает мне решить задачу того, как сделать привязку всех переменных ввода-вывода в одном месте. Вместо того, чтобы привязывать переменные к внутренним битовым каналам ПЛК, я привязываю туда общие, групповые переменные.

На скриншоте показано, как я создал переменные по именам встроенных входов и обозначению компонентов в щите (W1, W2, W3 и так далее). Например, тут привязана переменная W1_DIA, которая содержит в себе битовую маску для входов с 5 по 12.

Назначение переменных для внутреннего IO в CodeSys 2.3 по группам, а не по каналам

Назначение переменных для внутреннего IO в CodeSys 2.3 по группам, а не по каналам

Для внешних модулей ввода-вывода, работающих по ModBus, я делаю так же: назначаю групповые переменные на битовые маски.

Назначение переменных для внешнего IO в CodeSys 2.3 по группам, а не по каналам

Назначение переменных для внешнего IO в CodeSys 2.3 по группам, а не по каналам

А потом я в одном месте (обычно эта программа называется «TaskIO» и выполняется первой) разбираю все битовые маски и привязываю нужные переменные из VarsIO к этим маскам.

Привязка переменных ввода-вывода к групповым переменным IO (CodeSys 2.3)

Привязка переменных ввода-вывода к групповым переменным IO (CodeSys 2.3)

На CodeSys 3.5 это выглядит так же:

Привязка переменных ввода-вывода к групповым переменным IO (CodeSys 3.5)

Привязка переменных ввода-вывода к групповым переменным IO (CodeSys 3.5)

Такой способ сложен, но удобен для меня вот чем:

  • Всё объявление переменных сделано в одном месте программы (VarsIO);
  • Вся привязка переменных происходит в одном месте программы (TaskIO);
  • Тут же можно сделать контроль ошибок связи, валидности данных от датчиков и много чего другого;
  • Если ты ошибся и надо поменять позицию в битовой маске для какого-то входа или выхода — это делается легко, без изменения конфигурации ПЛК. В некоторых случаях изменения можно загрузить даже при помощи онлайн-обновления проекта без полной его загрузки с остановкой ПЛК.

В будущем у меня есть мысль на базе Visual Basic накатать простую и тупую программку для создания списков VarsIO и TaskIO под разные системы опроса модулей.

Я пока сделал только интерфейс и занялся основной работой по щитам и проектам.

Идея: прототип программы для генерации объявлений и назначений IO

Идея: прототип программы для генерации объявлений и назначений IO

Задумка такая: набиваем в программу Проект IO, а потом она генерирует объявления, код опроса модулей и разбор битовых масок с разными вариантами — CodeSys 2.3, CodeSys 3.5, SysCom, OwenCommunicationLibrary (OCL), ModBus.Lib и так далее.

5. Режим тестирования IO щита (Sys_TestOuts) и управление выходами модулей IO. Защита от множественной записи выходов.

А теперь, после того как я рассказал концепт работы со входами, поговорим о том, как я работаю с выходами и получаю такие вот красивые фотографии, где все выходы ПЛК и все реле работают.

Красивая фотография щита на ПЛК (тестируем все выходы)

Красивая фотография щита на ПЛК (тестируем все выходы)

Для выходных переменных я использую тот же концепт, который описал в прошлом разделе — собираю все выходы в битовые маски и присваиваю их битам значения переменных из VarsIO, а заодно решаю две задачи.

Первая — это защита от множественной записи выходов в ПЛК. Контроль множественной записи включается в настройках компилятора или статического анализатора кода и нужен для того, чтобы полностью исключить мерзкие ошибки, связанные с тем, что вы присваиваете значение какой-то переменной в разных местах кода или в разных задачах (а это прям актуально для многозадачных ПЛК). Если компилятор обнаружит такое множественное присваивание, то выдаст ошибку и не даст вам скомпилировать такой код.

Во всех моих проектах эта опция всегда включена. Минус этого контроля в том, что он сработает на код в двух ветках оператора IF — ELSE или на работу с битовой маской, которой я и пользуюсь. Чтобы обойти это, я сделал хитрость, про которую расскажу чуть ниже.

Вторая — это проверка всех исполнительных реле и элементов щита, включая блоки питания. Выше я говорил про то, как важно правильно рассчитывать мощность блоков питания для щитов на ПЛК, а режим тестирования всех выходов позволит проверить этот расчёт, включив всё на максимум.

Для того, чтобы заложить в проект возможность включить такой режим тестирования IO, я выделяю для этого один из входов ПЛК, который вывожу на клемму внутри щита (обычно она находится рядом с клеммами с предохранителями на 24V DC). Если замкнуть контакты клеммы перемычкой — то вход активируется, и включается режим тестирования IO. В программе ПЛК этот вход подключается через логическое «ИЛИ» («OR») ко всем выходам.

Что даёт режим тестирования IO в моих щитах?

  • Проверку работы всех блоков питания внутри щита: правильно ли они выбраны, держат ли нагрузку?
  • Проверку работы всех модулей выходов и исполнительных реле. На этом этапе можно выявить нерабочие выходы модуля или реле, которые не включаются или не переключают свои контакты.
  • Если цепи входов ПЛК (кнопки, датчики) ещё не подключены, то можно в тестовом режиме поуправлять разными нагрузками при помощи включения автоматов в щите. Это актуально для освещения: включил ПЛК в TestIO, включил нужные автоматы освещения — и проверил их.

Самым ОПАСНЫМ минусом этой идеи является то, что ПЛК включит ВСЕ выходы вне зависимости от их назначения и режима работы. Если это будет тёплый пол — он будет постоянно греться, если это будет мотор — он будет постоянно вращаться и что-то вращать или двигать.

Всё это, включая правила безопасности, тоже описано в инструкциях к моим щитам:

Фрагмент инструкции для клеммы тестирования IO (CS CRM)

Фрагмент инструкции для клеммы тестирования IO (CS CRM)

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

В программе TaskIO (той самой, где мы разбираем групповые и битовые маски входов) я объявляю временные буферы нужных типов (обычно BYTE, WORD, DWORD) и собираю в эти буферы битовую маску выходов для какого-то канала или модуля. Если же у нас включен режим TestIO, то я записываю в эту битовую маску 0xFF, 0xFFFF или 0xFFFFFFFF соответственно (все биты в TRUE), а потом однократно записываю эту маску в переменную выхода.

Назначение выходных переменных на групповые вместе с режимом тестирования IO (CodeSys 2.3)

Назначение выходных переменных на групповые вместе с режимом тестирования IO (CodeSys 2.3)

В OwenLogic, где программирование происходит в виде схемы, переменная Sys_TestIO (может называться по разному) подключается через OR ко всем выходам.

Назначение выходных переменных на физические выходы вместе с режимом тестирования IO (Owen Logic)

Назначение выходных переменных на физические выходы вместе с режимом тестирования IO (Owen Logic)

6. Обработка ошибок устройств ModBus и их каналов измерений (AI). Экраны диагностики IO.

Этот раздел поста, как мне кажется, самый важный, так как он связан с предусмотрительностью и перестраховками на случай того, чего может долго не случаться, а потом произойти неожиданно — сбоем устройств ModBus или датчиков. Часть этой темы я затрагивал в третьей части постов про ПР200 и ПР102, где мы опрашивали модуль аналоговых входов по ModBus, получая температуру с датчика ДТС014 (пост про такие датчики температуры вот здесь).

Там, где датчики используются только для отображения информации (например, температуры на улице или температуры стояка горячей воды), поломка датчика или обрыв связи с ним не так опасны: у нас только лишь пропадут показания с этого датчика. А вот если данные с этого датчика используются для управления каким-то оборудованием, то тогда будет очень плохо, если не предусмотреть защиты и обработку ошибок: насос накачает слишком много воды, и она куда-то польётся, трубы лопнут от большого давления, тёплый пол перегреется и сгорит, газовый котёл будет работать на полную мощность и устроит пожар или взрыв пара. Мне рассказывали, что в результате сбоя датчика стальная дымовая труба на одной промышленной котельной раскалилась докрасна, так как автоматика котла думала, что в котле +20 градусов, и надо вжарить газ на полную…

Чтобы этого избежать, в программе ПЛК нужно предусмотреть следующие проверки и алгоритмы обработки аварий:

  • Наличие связи по ModBus (или другому протоколу) с устройством. Устройство должно корректно отвечать на запросы без таймаутов, а данные, которые мы получаем от него, должны проходить проверку CRC.
  • Состояние измерительного канала и датчика. Большинство датчиков подключаются к ПЛК через измерительные модули, которые отслеживают обрыв или замыкание датчика. Программа в ПЛК должна обрабатывать эти ошибки.
  • Готовность данных с датчика. Некоторые датчики (например, датчики климата WirenBoard WB-MSW, про которые я писал здесь) при подаче питания не сразу отдают верные данные, так как им надо провести калибровку внутренних сенсоров. В своих проектах я отслеживаю пропадание связи с такими датчиками и делаю выдержку перед сбором данных с них. На момент выдержки используются последние корректные значения с этих датчиков. Такой приём используется, например, в моих FB для вычисления средних и минимальных-максимальных значений, про которые я расскажу в этом посте позже.
  • Значение с датчика. Датчик — это измеритель, и его можно поместить в такие условия, что он намеряет ерунду. Более того, вокруг того места, где стоит датчик, может возникнуть пожар, потоп или другая внешняя авария. Нужно проверять значения с датчиков на их логику и применимость.
    Например, масса одного батона колбасы явно не должна быть 50 кг, давление воды в трубе стояка горячей воды — минус 787999.79545921119 бар, а температура на улице — +300 градусов. Это явные ошибки, и их нужно фильтровать и не реагировать на них или, если они возможны (пожар в зоне датчика температуры) — выдавать сигнал аварии.
  • Скорость изменения значения с датчика (обратная связь). Этот алгоритм проверки мне подсказали опытные разработчики. Суть его в том, чтобы следить за тем, как меняется значение с датчика во время работы программы управления тем, что измеряет этот датчик.
    Например, если мы по датчику температуры включили тёплый пол на нагрев, но через час времени его температура не изменилась — то это явная авария, потому что хоть на градус за час, но пол должен был нагреться. Такие проверки используются в системах отопления, работы насосов и вентиляторов при помощи реле давления (пост про них и датчики давления) и даже в атомных реакторах (защита по скорости роста мощности в активной зоне — это знают все, кто интересовался аварией на Чернобыльской АЭС). Ещё делают проверку работы контакторов (пост про них): сигнал с дополнительного контакта подаётся на вход ПЛК, и при помощи этого ПЛК отслеживает то, включился ли в реальности контактор, или нет.

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

Я знаю один случай (который я упоминал в посте про ЦТП), где алгоритм фильтрации ошибок по времени очень бы помог. В ЦТП (Центральный Тепловой Пункт, на обычном языке — «Бойлерная») городское отопление в многоквартирных домах регулируется по датчику температуры воздуха на улице. Если она упала — то отопление чуток прибавляется, а если поднялась — то убавляется.

Этот датчик может стоять прям открыто на стенке ЦТП (и быть доступен любому идиоту с зажигалкой, которой его можно нагреть). Вообще его ставят повыше для защиты от дураков и на северной стороне ЦТП, чтобы солнце его не нагревало. Примерно вот так:

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

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

Но в одном проекте идиоты поставили его над входной дверью в ЦТП. Зимой в ЦТП жарко, если сравнивать с улицей. И, если открыть входную дверь, то горячий воздух из ЦТП пойдёт на улицу, заодно нагревая датчик. Сдали эту ЦТП с третьего раза, потому что никто не мог понять, что за херня происходит: пришла комиссия, открыла дверь, ходит, смотрит. И вдруг фигак — и отопление выключается к чертям. Зимой в лёгкий морозец! Комиссия ушла, дверь закрыли — отопление заработало. И так ещё раз! =)

Проблему решили через жопу: поставили на дверь ЦТП концевик и изменили программу в ПЛК так, что при открытии двери панель оператора гаснет, и комиссия не видит, что цифры на параметрах отопления изменились. А ведь фильтрация данных с датчика здесь могла бы помочь. Например, можно было бы создать алгоритм вида «Если температура резко скакнула, то в течение 20 минут используем предыдущее значение, пока она не вернётся в норму».

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

Как получить статус связи с устройством по ModBus в ПЛК на базе CodeSys?

Тут я пишу о штатных средствах опроса устройств — через Конфигурацию ПЛК (дерево объектов). Если вы опрашиваете устройства ModBus через библиотеки (OCL, Modbus, SysCom) — то вы сами должны создать себе возможность получать ошибки связи от устройств.

Для CodeSys 2.3 в дереве ModBus Master есть два узла, общие для всех устройств: «Last Address» и «Last Error». Во время опроса каждого из устройств в «Last Address» выдаётся ModBus-адрес текущего устройства, а в «Last Error» — код ошибки, равный 0, если обмен данными с устройством прошёл успешно.

Достаточно привязать переменные к этим узлам в конфигурации ПЛК и написать код, который будет проверять «Last Error» на ноль и, если он не равен нулю, получать «Last Address» и реагировать на него.

Диагностика ошибок ModBus в CodeSys 2.3: переменные адреса и кода ошибки для каналов

Диагностика ошибок ModBus в CodeSys 2.3: переменные адреса и кода ошибки для каналов

В CodeSys 3.5 всё немного сложнее, но одновременно более удобно и более неудобно.

Удобно то, что теперь каждому элементу конфигурации ПЛК — интерфейсу связи, драйверу ModBus Master/Slave и самому устройству — можно дать понятное имя и обращаться в коде программы по этому имени, получая статус обмена и ошибок.

Для того, чтобы получать расширенную информацию об обмене с устройством ModBus, нужно установить галочку «Включить диагностику для устройств» на вкладке «Установки ПЛК» текущего устройства в проекте:

Диагностика ошибок ModBus в CodeSys 3.5: включение режима диагностики

Диагностика ошибок ModBus в CodeSys 3.5: включение режима диагностики

После этого можно обращаться к нашему устройству по его имени через точку и получать информацию.

Диагностика ошибок ModBus в CodeSys 3.5: переменные флага ошибки и номера канала опроса

Диагностика ошибок ModBus в CodeSys 3.5: переменные флага ошибки и номера канала опроса

Нам могут быть интересны такие переменные:

  • Для драйвера ModBus Master:
    • uiNumberOfCommunicatingSlaves — количество устройств ModBus Slave в работе в штуках. Можно использовать для самой простой проверки: если число устройств в работе равно нужному числу устройств (например, 20 датчиков) — то ошибок нет.
    • xAllSlavesOk — Флаг, который показывает что все ModBus Slave-устройства корректно работают. Его тоже можно использовать для простой диагностики вида «Всё в порядке».
  • Для конкретного устройства ModBus:
    • xEnable — Включить (TRUE) или Отключить (FALSE) устройство из опроса. Для отключенного устройства флаги ошибок связи не формируются.
    • iChannelIndex — Номер канала, который сейчас опрашивается или где произошла ошибка.
    • xBusy — Признак того, что устройство опрашивается именно сейчас. Можно использовать как флаг активности.
    • xError — Признак того, что при опросе текущего канала возникла ошибка.
    • byModbusError — Код ошибки опроса текущего канала.

Номер канала — это физический номер тех строк, которые внесены в таблицу в свойствах устройства на вкладке «Канал Modbus Slave»:

Диагностика ошибок ModBus в CodeSys 3.5: номер канала опроса

Диагностика ошибок ModBus в CodeSys 3.5: номер канала опроса

И вот с этими каналами и штатным драйвером опроса в CodeSys 3.5 есть огромное грёбаное и неудобное западло. Евгений Кислов очень ждёт моего поста про работу штатного драйвера ModBus в CodeSys 3.5, но пока пост не выйдет: мне надо заработать денег, чёрт побери (донаты приветствуются всегда).

Западло состоит в том, что Драйвер CodeSys 3.5 опрашивает каналы устройства последовательно, и флаги работы опроса и ошибок тоже выставляет последовательно! Старый CodeSys 2.3 работал проще: устройство не ответило на любой (самый первый) запрос — устройство в ошибке, опрашиваем следующее. Здесь же происходит следующая хрень, если устройство не отвечает на запросы:

  • Сбросили флаг ошибки;
  • Опросили Канал 0;
  • Выждали таймаут — нет ответа. Выставили флаг ошибки;
  • Сбросили флаг ошибки;
  • Опросили Канал 1;
  • Выждали таймаут — нет ответа. Выставили флаг ошибки;
  • Сбросили флаг ошибки;
  • Опросили Канал 2;
  • Выждали таймаут — нет ответа. Выставили флаг ошибки;

И так далее! В итоге, если таймаут, например, равен 100 мсек, а каналов опроса в устройстве четыре — то вся линия связи зависнет на 400 мсек, что приведёт к сильным тормозам опроса остальных устройств.

Но для нашего алгоритма отслеживания и фильтрации ошибок это означает вот что: если устройство не отвечает, то его флаг xError будет дёргаться между TRUE/FALSE на каждую попытку его опроса, и точное и стабильное значение вида «Устройство не отвечает» для применения в программе мы не получим.

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

Алгоритм, на самом деле, простой. Нам требуется два таймера: TOF (задержка выключения) и TON (задержка включения). На первый таймер мы подаём флаг xError от устройства, чтобы формировать импульс ошибки подлиннее, как только она возникнет. Второй таймер запускается по выходу с первого и включится тогда, когда число импульсов ошибок за заданное время будет таким большим, что таймер TOF будет постоянно ими подпинываться и не выключаться.

Вот мой код для этого фрагмента:

Код алгоритма реакции на продолжительные серии ошибок Modbus для фильтрации ложных ошибок

Код алгоритма реакции на продолжительные серии ошибок Modbus для фильтрации ложных ошибок

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

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

Блоки обработки ошибок и сбора статистики для Дискретных и Аналоговых каналов опроса

Блоки обработки ошибок и сбора статистики для Дискретных и Аналоговых каналов опроса

Мои FB ещё и статистику опроса считают и, что актуально для CodeSys 3.5, сразу же формируют строку состояния устройства или канала опроса для интерфейса пользователя, включая среднее время опроса (считается по скользящему между текущим и предыдущим значением). А для каналов датчиков обрабатывается не только числовое значение показаний, но ещё и строковое, которое форматируется, дополняется единицей измерения, а при ошибке датчика выводит значение «Err.».

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

Константы времён фильтрации кратковременных ошибок устройств

Константы времён фильтрации кратковременных ошибок устройств

А потом (это тоже мой стандарт) я создаю в своих проектах такое диагностическое окно, которое и показывает статистику опроса всех устройств и их ошибок.

Страница диагностики устройств ModBus: устройства работают нормально, а на одном датчике были ошибки

Страница диагностики устройств ModBus: устройства работают нормально, а на одном датчике были ошибки

На скриншоте выше хорошо видно, что Тёплый пол Кабинета (термостат с AliExpress с ModBus; про них был пост) отваливался 39 раз, но сейчас его опрос идёт стабильно.

А вот вам другая страница диагностики. Это — дополнительный щит санузла, где все четыре модуля ввода-вывода (верхняя рамка на скриншоте) работают отлично (модуль W1 даже прям опрашивается — «Req»), а вот большинство датчиков в ошибке.

Страница диагностики аналоговых входов и устройств ModBus: устройства работают нормально, есть сбои аналоговых датчиков

Страница диагностики аналоговых входов и устройств ModBus: устройства работают нормально, есть сбои аналоговых датчиков

На самом деле ошибки датчиков выдаются из-за того, что я в это время программировал свой щит, и датчики ещё даже не были подключены.

И вот мы пришли к интересному вопросу. Как быть, если датчиков нет (или они показывают не то, что нужно), а алгоритм работы надо отладить?

7. Режим имитации работы аналоговых датчиков. Генерация сигналов.

На своём большом проекте я столкнулся с тем, что мне надо было написать не простые алгоритмы вида «Если вода открыта, а давление в стояке упало — закрой воду», а более сложные. Например, для промывки фильтров оценивалась разница давлений до и после фильтра, а для автоматического перехода на водонагреватель оценивалась температура стояка горячей воды: если она низкая в течение заданного времени, то надо включить водонагреватель.

Я знаю, что можно сделать! Взять и подставить нужные числа в прям в коде. А потом удалить их, когда проект будет закончен. Да? НЕТ! Это приведёт к потенциальным ошибкам, которые для проектов в автоматике будут критичны и опасны. Вдруг вам для отладки понадобится накрутить вашу программу так, что аварий по датчика газа (пост про них) у вас нет, а потом вы забудете это убрать из программы?!

У себя я поступил следующим образом. В библиотеке UTIL есть FB «GEN», который может генерировать различные формы сигналов: меандр, синус, пила, треугольник. Я взял его за основу и создал свой блок CSAIValueProducer, который принимает на вход структуру с описанием режима генерации сигнала.

Возможности блока такие:

  • Генерировать отвалы датчика (ошибки канала измерения) через заданные периоды;
  • Генерировать постоянное или меняющееся с заданным периодом значение с датчика;
  • Генерировать Синус или Треугольник по форме значения (решил, что двух хватит);
  • Задавать базовое значение и дельту его изменений в режиме генерации.

Дальше мне снова остаётся определить правила формирования отладочных значений в константах кода обработки модулей IO:

Код для имитации корректной работы аналоговых датчиков в режиме отладки (задаём режимы имитации)

Код для имитации корректной работы аналоговых датчиков в режиме отладки (задаём режимы имитации)

Мои FB сделаны таким образом, что они вызываются прямо из FB обработки каналов аналоговых датчиков (для каждого датчика — свой экземпляр отладочного FB).

Общая структура проекта получается такой: если включен режим Sys_TestIO (Sys_TestOuts), то аналоговые датчики обрабатываются через имитацию их значений. Если же режим тестирования IO щита выключен — то датчики работают штатно. Этот приём позволяет ничего не менять в коде программы после выпуска финальной версии, а, следовательно, убирает вероятность того, что где-то в коде останется подстановка временных значений с датчиков для отладки проекта.

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

Страница журнала тревог с событиями корректной работы датчиков и имитации их аварийных значений

Страница журнала тревог с событиями корректной работы датчиков и имитации их аварийных значений

А вот так выглядят графики этих отладочных значений вместо реальных. Провалы значений — это имитация ошибок датчиков.

Вид на графики температур и давлений датчиков, которые находятся в режиме имитации

Вид на графики температур и давлений датчиков, которые находятся в режиме имитации

Я хочу сказать, что такие вот страницы диагностики и журналы тревог — это очень важная часть проекта на ПЛК, и она помогает в пусконаладке щита и поиске проблем в будущем. Уже проверено!

8. Сбор статистики Min/Max/Avg для аналоговых синалов и других переменных.

Следующая технология, которую я для себя разработал — это FB для вычисления скользящего среднего и статистики минимума и максимума для значений с датчиков. Смысл этих FB был в том, чтобы хранить статистику и использовать её в разных алгоритмах. Ну например, если текущее показание с датчика отличается от среднего за какой-то период — то это будет являться признаком аварии. Или, если средняя уличная температура за неделю стала ниже заданной — то считаем, что наступили холода.

Блоки сбора статистики и средних значений данных с датчиков за разные периоды

Блоки сбора статистики и средних значений данных с датчиков за разные периоды

Эти FB выдают как числовые значения, так и строковые, так как это актуально для CodeSys 3.5, где строки могут выводиться на экран визуализации. Вместо того, чтобы их вручную форматировать и фильтровать в случае сбоя датчика, можно сразу забрать готовые данные с этих FB в строковом формате. Ещё это помогает снизить нагрузку на процессор ПЛК с визуализацией, так как у них есть одна идиотская особенность: каждая перезапись строковой переменной (даже одним и тем же значением) переобновляет визуализацию, в которой используется эта переменная, и это дико грузит процессор ПЛК. Мои FB обновляют эти переменные раз в секунду и этим снижают нагрузку на процессор.

У самих блоков есть входы bValueOK и bValueReady, которые управляют работой блоков таким образом, чтобы блоки не учитывали в статистике значения при сбое датчиков или тогда, когда датчики не вышли на рабочий режим (например, датчики WirenBoard WB-MSW начинают измерять CO2/VOC через 5-10 минут после подачи питания на них). У меня флаг vValueReady формируется с выдержкой после каждого обрыва связи с датчиком, чтобы дать ему время перезапуститься, если обрыв связи был из-за отключения его питания.

Внутри блока CSValAverage объявлен блок CSValMinMax, который даёт доступ ко всем значениям минимума и максимума за разные периоды.

Алгоритм блоков привязан к дате и времени, которые есть в ПЛК. Идея хранения данных для расчёта средних значений по срезам стырена из реализации системы сбора данных с датчиков тока ABB CMS (пост про неё), которая использовала пополняемые буферы для разных срезов данных. По истечении дня текущее среднее за день записывается в недельный массив, по истечении недели — в месячный и так далее. Вычисление минимумов и максимумов делается ещё проще: каждый раз при смене величины, по которой делается срез данных (час, день, неделя, месяц), значения за этот срез заменяются на текущие, чтобы они сбросились. В остальное время идёт их обновление.

В итоге с такими FB можно поступать нагло и просто: объявить их в PERSISTENT-переменных и вызывать в коде с нужными данными =)

Объявление PERSISTENT-переменных для хранения значений статистики

Объявление PERSISTENT-переменных для хранения значений статистики

Вот так работают мои FB в моём тестовом домашнем ПЛК. Данные с датчиков давления не фильтруются, поэтому там в значениях есть дичь =)

Пример вывода статистики (отладочный ПЛК у меня дома)

Пример вывода статистики (отладочный ПЛК у меня дома)

9. Сложные FB обработки Modbus-устройств (датчиков).

Для сложных датчиков, которые я опрашиваю по ModBus, я разработал большие FB, которые поддерживают разбор сырых данных с датчиков (непосредственные значения регистров), отдают на них команды (тоже в виде значений регистров), обрабатывают все данные до удобоваримого формата и отдают их в числовом и строковом виде.

Блоки обработки информации с датчиков Modbus (Sentera ODTHM, WirenBoard WB-MSW)

Блоки обработки информации с датчиков Modbus (Sentera ODTHM, WirenBoard WB-MSW)

Такие FB родились по нескольким причинам. Во-первых, некоторые датчики в своих регистрах возвращают не только значение, а код ошибки. Например, тот же датчик WirenBoard WB-MSW отдаст 0xFFFF, если сенсор CO2 не готов или ещё не прошёл калибровку при включении датчика. Блоки фильтруют и правильно обрабатывают эти значения.

Во-вторых, экземпляры этих FB можно объявить в списке переменных ввода-вывода (VarsIO) и обращаться к ним так же, как к переменных обычных входов и выходов.

В-третьих, такие FB могут реализовывать механизм управления этими же устройствами — выставлять нужные значения регистрам.

10. Вывод сообщений в журнал ПЛК CodeSys 3.5.

Благодаря статье Евгения Кислова про работу с системными журналами ПЛК (ссылка на неё), я подсел на эту функцию и стал ей активно пользоваться. В той статье рассказано про то, как можно зарегистрировать свой журнал ПЛК и свои компоненты для записи событий. Это удобно, если нам хочется просматривать свои события и группировать их по логическим частям (условно, свет, тёплые полы, опрос датчиков, насосы, котлы и так далее). Запись в журналы поддерживается только в кодировке ANSI (английские буквы), а функции записи принимают тип строки STRING.

Для простых проектов я использую более простой способ — вызов функции VisuElements.Visu_Output(), которая принимает два аргумента: текст, который надо записать в журнал в формате STRING (не путать с WSTRING) и тип записи, который выбирается из перечисления VisuElems.LogClass — LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_EXCEPTION. Все сообщения в журнале при таком вызове будут опубликованы от имени компонента IECVisualization.

Первым делом я закосил под серверные системы и написал простой код, который примерно раз в час пишет в лог о том, сколько ПЛК проработал. Такая фишка обычно называется HeartBeat. Я создал для этого отдельный FB и забираю с него информацию.

Код для использования функции VisuElems.Visu_Output, которая добавляет строку в системный журнал ПЛК

Код для использования функции VisuElems.Visu_Output, которая добавляет строку в системный журнал ПЛК

Не могу не запостить свою кошочку, которая реализует функцию ConCat, которая используется для склеивания строк типа STRING. Одна лапка — это Con, другая — Cat. Это она так на тёплом полу у меня уютно легла, а её фоточка сразу покорила всех в ОВЕНе =)

Кошочка изображает функцию ConCat (одна и другая лапка)

Кошочка изображает функцию ConCat (одна и другая лапка)

Вот так выглядит лог с нашими записями, которые добавлены туда программно:

Пример вывода сообщений в журнал ПЛК: время HeartBeat (признак активности системы)

Пример вывода сообщений в журнал ПЛК: время HeartBeat (признак активности системы)

А вот сообщения о том, через какое время запустился ПЛК после простоя. Это было нужно для обнуления некоторой статистики, которая не должна храниться, если ПЛК выключали больше чем на сутки: вдруг его включат через пару месяцев, и он неверно насчитает средние значения с данными за прошлый период?

Пример вывода сообщений в журнал ПЛК: тип запуска ПЛК и режим сброса статистики

Пример вывода сообщений в журнал ПЛК: тип запуска ПЛК и режим сброса статистики

11. Списки переменных для наблюдения в CodeSys 2.3.

Для удобной отладки сложных программ в CodeSys 2.3 есть возможность создать несколько списков переменных для наблюдения за их значениями. Разница между обычным просмотром онлайн-значений переменных в том, что в этот список можно внести переменные из разных участков проекта, для просмотра которых надо было бы открывать кучу окон и располагать их на экране.

Этот функционал доступен на вкладке «Ресурсы» в разделе «Менеджер просмотра». Он открывается по двойному щелчку на элементе в дереве.

Пример создания списка переменных для наблюдения (CodeSys 2.3)

Пример создания списка переменных для наблюдения (CodeSys 2.3)

Если щёлкнуть правой кнопкой мыши на области окна слева, то можно добавить, удалить или переименовать нужный список переменных. Сами переменные вписываются в него так же, как обычно — со ссылкой на POU, из которого их надо взять. Глобальные переменные (включая те, которые привязаны к элеменам в дереве конфигурации ПЛК) записываются здесь через точку перед их именем.

12. Директивы сообщений компилятора в CodeSys 3.5.

Для работы над проектом в CodeSys 3.5 есть удобные директивы компилятора, которые позволяют выводить сообщения в лог компиляции проекта.

Эти директивы соответствуют по названиям тем типам сообщениям, которые надо вывести: info, warning, error. Они записываются маленькими буквами в фигурных скобках, а текст, который надо вывести, берётся в одинарные кавычки.

Выглядит это примерно так:

  • {info 'Здесь значение можно поменять.'}
  • {warning 'Проверить работу алгоритма!'}

Удобство этих приёмов в том, что все тексты, которые написаны в этих директивах, выводятся в лог компиляции и действуют так же, как обычные записи в этом логе: по двойному щелчку мышки можно перейти к строке кода с такой директивой.

Вот здесь я записал себе идею для доработки:

Директивы сообщений (Info): пример вывода текста ToDo

Директивы сообщений (Info): пример вывода текста ToDo

А здесь через директиву warning записал ToDo, которое надо сделать в ближайшее время.

Директивы сообщений (Warning): пример вывода текста доработок кода

Директивы сообщений (Warning): пример вывода текста доработок кода

13. Сворачивание участков кода в CodeSys 3.5 (директива «region»).

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

Записывается она тоже в фигурных скобках, а текст — в двойных кавычках:

  • {region "Название региона"} — начало участка кода
  • {endregion} — конец участка кода

Это очень удобно для длинного кода или списка переменных, который можно сворачивать по частям. Директива имеет и баг: в участках, ограниченных этой директивой, плохо работает автоотступ кода — он всегда съезжает вправо лесенкой.

Директива Region: пример деления кода на участки и сворачивания ненужных

Директива Region: пример деления кода на участки и сворачивания ненужных

14. Инкрементальные резервные копии проектов с сохранением предыдущих версий.

Ну и самая последняя, но и самая важная технология — это РЕЗЕРВНОЕ КОПИРОВАНИЕ ИСХОДНЫХ ФАЙЛОВ ПРОЕКТОВ С СОХРАНЕНИЕМ ПРЕДЫДУЩИХ ВЕРСИЙ.

Большинство разработчиков уже забыли про старые компы, который не имели аккумулятора и вырубались при пропадании сетевого питания, и отвыкли каждую секунду нажимать Ctrl+S. У меня эта привычка въелась на всю жизнь, и я жму Ctrl+S автоматически везде и всюду.

Я заметил по форуму ОВЕНа то, что разработчики в основном оставляют резервные копии предыдущих версий проекта после того, как что-то там глобально меняют. Это хорошо и правильно, но мне — недостаточно. Я помню, как потерял исходники автоооткрывалки для старого подъездного домофона из-за того, что пересохранил какие-то файлы поверх них.

На форуме ОВЕНа я читал о том, как дико глючит OWEN Logic (накидал новых элементов в проект — и он перестал открываться) и как иногда сбой Windows или отключение питания во время сохранения проекта CodeSys навсегда повреждает его.

В посте про старые и нужные программы я писал про удобную для меня программу KLS Backup, старые версии которой отлично ищутся в торрентах (я использую ‘2013). Она позволяет делать резервные копии с сохранением предыдущих версий файлов. Я пользуюсь этим вовсю и резервирую все свои папки с личными проектами и проектами для заказчиков.

Пример использования программы KLS Backup для ведения архивов версий проекта после каждого изменения

Пример использования программы KLS Backup для ведения архивов версий проекта после каждого изменения

Рекомендую вам найти удобную для вас программу и пользоваться ей постоянно, чтобы по какой-нибудь случайной глупости не потерять результаты ваших трудов!

Проекту исполнилось 15 лет! Поддержать проект материально, проспонсировать проекты Автора или сделать ему подарок можно на этой странице: "Донаты и Спонсорство, Список Желаний".

15 Отзывов на “Технологии и методы тестирования и отладки щитов с автоматикой на ПЛК (Обработка IO, Тест IO, Имитация IO)”


  • По 14 пункту: странно, если до этих разработчиков до сих пор системы версионирования, типа Git, SVN и пр., не добрались. Git, который сейчас уже не только в IT-компаниях повсеместно используется, но и в конструкторских бюро и т.п., как раз полностью решает эти задачи.

    У нас вон сейчас в работе идет двойное, а то и тройное резервирование важных наработок: и посредством подготовки архивных копий файлов с переименовкой и выставлением версий, и последующим их помещением в Git (как актуальных, так и архивных версий), и последующим бекапированием уже внутреннего сервера, на котором репозиторий развернут.

  • 2 a_b  [Московская область, Истринский район]

    Meldir, поддержка Git в Codesys есть только в профессиональной версии (подписка 550 евро в год) или через сторонние сервисы (copia.io, ценник непубличный, но судя по упоминаниям в сети, не дешевле и только пакетами на много пользователей).
    Увы, эта сфера по проникновению удобных инструментов и методик разработки отстаёт от обычного программирования лет на 20.

  • a_b, так, не очень понял а зачем где-то на стороне поддержку Git в Codesys покупать? Git ведь вообще ни к чему не привязан и бесплатен: достаточно развернуть инфраструктуру где-то на локальном сервере (или воспользоваться готовой типа GitHub) клиенты для синхронизации на каждой рабочей машине, с которой нужно иметь доступ к репозиторию.

    А что мы уж там делать дальше с реплзиторием будем — это наше дело. И какие файлы в него закачивать. Можно хоть файлы Word и графические изображения (кто-то, кстати, прям целиком содержимое компа делает реплзиторием и резервирует, т.к. возможность позволяет).

    У меня вон лично развернут Git на сервере клиентская часть на рабочей машине графический клиент Tortoise Git (потому что удобно мне через контекстное меню все делать, а не через командную строку) и все: и файлы от Siemens Logo, всякие проекты с автоматикой и прочим, программный код на C/Delphiи т.п., документы по договорам и пр. — все это потом в репозиторий (или репозитории) заливается.

  • 4 CS  [Москва]

    Meldir О, давно тебя не было. Мне аж интересно, что за повод был написать!
    Ты не в курсе, что у CodeSys и OwenLogic все файлы проектов — упакованные двоичные в своих форматах. Они НЕ текстовые, поэтому всякие GIT их нормально не обработают и изменения не отследят.
    Разворачивать, как ты пишешь, сервак для дома ради одного проекта я считаю излишним: ну, будет проект коммититься на сервак. А дальше что? С сервака кто будет бэкапить? И кто коммит будет жать? Не автоматика же!
    Поэтому для простых вещей проще софтину использовать.

  • CS Дак читаю статьи, когда есть возможность: раньше не по чему было ничего потенциально полезного сказать, а вот сейчас вот появилось, вот и повод.

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

    А вот сервак ради одного проекта — это я согласен. Тут конечно потенциально возни больше, чем пользы. И вообще тут много чего организационного действительно возникает. Но если проект уже не один, то имеет смысл подумать.

    Коммит, кстати, жать может и автоматика) Можно настроить так, что коммит будет происходить, например, по какому-то событию.

  • 6 CS  [Москва]

    Meldir Я думал, ты давно на всё заби и не читаешь.
    Ну, я не понимаю, как можно сравнить файл, где всё хранится в бинарном виде:
    а) У CodeSys 2.3 это просто бинарный файл, где открытым текстом среди кучи бинарных данных лежит только текст на языке ST. Если он есть.
    б) У CodeSys 3.5 это ZIP-архив (архивирование делается на уровне среды разработки: без сжатия, со сжатием, с шифрованием), внутри которого есть разные бинарные потоки, CRC которых проверяется. То есть, не получится вставить в этот ZIP-архив свои данные. Среда разработки скажет, что проект повреждён.
    в) У OwenLogic в первой версии был вообще бинарник, а во второй — ZIP-архив текстового файла. Но там снова все компоненты связаны, и нарушение этого файла ведёт к повреждению проекта.
    В общем, эти три среды наружу ничего текстового не отдают.

  • CS Ну действительно никак, кроме как визуальным сравнением.
    Но я тут вот какую мысль пытаюсь донести: смотри, пускай есть репозиторий, в котором находится бинарный файл с именем «Файл 1». Пускай есть два коммита, связанные с этим файлом «Коммит 1» и «Коммит 2». У каждого из коммитов есть обязательный атрибут, который представляет собой текстовое сообщение, в котором мы, когда делаем коммит, должны написать какую-то информацию об изменениях, приведших к появлению этого коммита (т.е. по идее это краткое, лаконичное и информативное изложение изменений, которые мы сделали в файлах, во всяком случае я и сам так делаю, и тех, кто со мной работает, так учу).
    Т.е. и у «Коммит 1» и у «Коммит 2» должен быть вот этот вот текст, указывающий хотя бы приблизительно какие изменения, в каких местах и почему произошли (т.е. на что смотреть-то). И вот тут мне, например, без разницы бинарный файл или нет. Т.е. если у меня есть вот эти два коммита, и к ним есть описание, то я просто добываю из этих двух коммитов две версии файла «Файл 1» и сравниваю их визуально, открыв в программе, которая эти файлы может открыть. Но при этом, если текстовое сообщение было написано к коммитам корректно, то это сравнение мне провести гораздо легче.
    Например, в описании к «Коммит 2» написано что-то типа «Изменена константа уставки датчика расхода для регулятора расхода в напорном трубопроводе чистой воды с 250 кг/с на 350 кг/с. Добавлен алгоритм нейтрализации дребезга контактов для кнопки 1» и все, я понимаю, что мне надо посмотреть в «Коммит 1» алгоритм, связанный с датчиком расхода в напорном трубопроводе чистой воды и посмотреть алгоритмы, связанные с кнопкой 1.

    А то, что они в таком формате все хранят — это не хорошо. Как раз-таки невозможность использования систем версионирования будет в каких-то моментах ограничивать использование этих программ.

  • 8 rimas79  [Краснодар]

    @Meldir, GIT это хорошо, тоже хотел написать этот вопрос, но не успел :)
    Но git (и прочие VCS) не заменяет бэкап:
    1) git позволяет удобно работать одновременно нескольким людям (или одному человеку поддерживать несколько версий)
    2) бэкап автоматически «прячет в надежное место»
    В теории по Ctrl+S можно создавать отдельный коммит, но я бы не хотел никогда увидеть такую репу…
    Бинарные исходники — зло!

  • rimas79 А я поэтому и пишу про тройное, а иногда и четверное (хотя я не знаю, есть ли организации, которые это нормально организовали) резервирование. Но и все-таки системы контроля версий и бекапирование — это разные вещи, направленные на разное.
    Поэтому я там выше и написал, что мы сервер с репозиториями бекапим, а я еще бекаплю свой комп дополнительно (хотя и редко), хотя самые важные вещи в репозиториях лежат.
    Я бы сказал, что все-таки системы контроля версий направлены на повышение прозрачности истории изменений с одновременной организацией приемственности этих изменений. А бэкап — это исключительное сохранение данных с привязкой ко времени.

  • 10 CS  [Москва]

    Блин… вот лучше бы ты что-то умное написал про обработку датчиков, данных всяких и защиты.
    Развели трёп про несуществующие фишки. А ща получается так, что если НЕ разворачивать сервак (про который стало ясно, что он не нужен), то тот же Commit делается в программе кнопкой «Backup»…

  • 11 nik425

    За контроль версий. Я эту фишку нихрена не понял. Я тупо сам проект сохраняю с префиксом типа «V01, V02» и ты пы. Если чета важное — приписываю типа «V01_ModBus FC_INV_WRK» и мне все ясно. А эти Git и прочее — хз, куда оно и че сохраняет.
    За CoDeSys. Я думаю, актуально в 3.5 работать. Больше возможностей и удобнее интерфейс. Я в ПЛК тупо по максимуму все делаю через переменные, которые отображаю (маппирую) на модбас-адреса. Сильно удобно для отладки с использованием HMI. Константа/переменная — в HMI адрес вбил и пожалуйста — доступ.
    Отдельно отмечу, что CoDeSys — ПЛК классная штука. Неважно, какая аппаратная часть, у тебя единый CoDesys- стандарт. Конкретно какой уже не упомню.
    На фоне этого от софта под микроПЛК типа STM32 волосы дыбом встают. Куча софта как коммерческого, так и фришного, и все конфигурируется по разному, еще и хер найдешь, как правильно. Лютая дичь. Я тут сдуру сунулся было под STM32 попрогать. Ага. После CoDeSys долго думал.

  • 12 CS  [Москва]

    nik425 Я тоже сохраняю некоторые куски проекта вручную, типа «Stable Water», «Stable UI» и так далее.
    Бэкап мне нравится, чтобы предыдущие версии сохранялись автоматически. В KLS можно даже запустить задание и сказать, чтобы он погасил комп после завершения работы.

    Я тоже топлю за CodeSys, потому что там есть все языки (недавно ХАМСКИ И НАГЛО на CFC портировал код из ПРки, не переводя его на ST), и проект сделан в виде единого, ОДНОГО файла. А в 3.5 можно вообще весь проект + библиотеки сохранить в Архив и развернуть всё на новом компе, не лазая по сайтам и не качая таргеты и библиотеки.
    НО! Есть несколько нюансов, и про них будут посты, саркастичные и злые. CodeSys 3.5 имеет уёбищные драйвера для Modbus, которые адски тормозят так, что даже простой опрос кнопок на них нормально сделать не получается вообще никак (про это и будет пост). Это надо учитывать, и здесь драйвера для Modbus в CodeSys 2.3 рулят очень круто!
    Да!! И мне вот и нравится то, что в 3.5 можно переменные сразу на визуализацию привязывать, а не трахаться в отдельным программированием панели оператора, мать её (когда из-за одного изменения правишь два проекта, а не один).

  • 13 eteh  [Санкт-Петербург]

    CS интересен пункт 8:
    Много ли ложноположительных срабатываний? Или расчет идет без ведения каких-то баз данных?

  • 14 CS  [Москва]

    Пункт 8 — это статистика Min/Max/Avg.
    Что такое ложноположительные срабатывания в этом ключе? Не понимаю.

  • 15 eteh  [Санкт-Петербург]

    CS

    Да я попозже прочитав еще раз врубился — это просто статистика, а не эвристический анализ, о котором я думал… П -Профдеформация)

Оставить отзыв

Вы должны войти на блог, чтобы оставить комментарий.