Когда инженер приступает к разработке программы для программируемого логического контроллера, стандарт МЭК 61131-3 (IEC 61131-3) задаёт важную основу, но не превращается в подробную инструкцию по написанию каждой строки кода. Он определяет синтаксис и семантику языков программирования, применяемых в ПЛК, основные типы данных, а также структуру программных единиц — программ, функций и функциональных блоков.
В состав стандарта входят текстовые языки, в том числе Structured Text и Instruction List, графические языки Ladder Diagram и Function Block Diagram, а также элементы Sequential Function Chart, предназначенные для структурирования последовательных и параллельных алгоритмов.plcopen
Однако стандарт не отвечает на все практические вопросы, возникающие при разработке реального проекта. Например, он не устанавливает единственный правильный способ именования переменных, оформления комментариев, организации вычислений, ограничения сложности отдельных блоков или взаимодействия между задачами. Поэтому две программы могут соответствовать требованиям IEC 61131-3, но заметно различаться по читаемости, удобству сопровождения, переносимости и устойчивости к ошибкам.
Именно здесь возникает вопрос: «Как писать программу хорошо?» Одного формального соответствия стандарту недостаточно. В промышленной автоматизации важно, чтобы другой инженер мог быстро понять назначение переменных, логику функциональных блоков и порядок выполнения алгоритма. Не менее важно обеспечить повторное использование готовых компонентов, упростить диагностику и снизить вероятность ошибок при дальнейшем расширении системы.
Заполнить этот методический пробел призвана организация PLCopen, объединяющая участников отрасли промышленной автоматизации. Она разрабатывает рекомендации по созданию программного обеспечения, библиотеки функциональных блоков и правила программирования для систем, основанных на IEC 61131-3. В частности, PLCopen Coding Guidelines рассматривают соглашения об именовании, правила документирования, общую практику написания кода и рекомендации для отдельных языков, включая Structured Text.
Эти документы не заменяют IEC 61131-3 и не являются обязательными для каждого проекта. PLCopen прямо рассматривает их как набор правил и предложений, который разработчик или организация могут адаптировать под конкретное предприятие, тип оборудования и требования к качеству программного обеспечения.
Тем не менее рекомендации PLCopen стали важным ориентиром для инженеров, преподавателей и разработчиков библиотек, поскольку помогают выработать единый стиль и сделать программы ПЛК более понятными, предсказуемыми и удобными для сопровождения.plcopen
Таким образом, IEC 61131-3 отвечает прежде всего на вопрос, какими средствами и в рамках какой модели следует программировать контроллер, а рекомендации PLCopen помогают решить, как организовать этот код на практике.
Особенно это важно для Structured Text, который предоставляет разработчику большую свободу: один и тот же алгоритм можно записать кратко, но неясно, или структурированно, с понятными именами, комментариями и предсказуемой логикой выполнения. Именно сочетание требований стандарта и продуманного стиля программирования позволяет создавать качественные, масштабируемые и надёжные программы для систем автоматизации.
POU как единица мышления программиста
В основе стандарта лежит понятие Program Organization Unit - программной организационной единицы, сокращённо POU. Это функции, функциональные блоки и программы, из которых, как из кирпичей, складывается всё приложение контроллера. Функция выполняет чистое вычисление без сохранения состояния между вызовами, функциональный блок хранит внутренние данные и ведёт себя как объект с памятью, а программа объединяет несколько блоков в рамках одной задачи.
Ключевая идея, ради которой всё это придумано, - инкапсуляция. Любая POU может содержать локальные данные, недоступные снаружи: чтобы вызвать блок, достаточно знать его внешний интерфейс, а что происходит внутри - дело автора блока.
Эта идея пришла в промышленное программирование прямо из объектно-ориентированных языков, и именно она делает возможной коллективную разработку: один инженер пишет блок управления клапаном, другой - блок ПИД-регулятора, и пока интерфейсы согласованы, они могут работать параллельно, не заглядывая в код друг друга.
Руководство по кодированию PLCopen
В 2016 году рабочая группа PLCopen выпустила документ под названием Coding Guidelines - результат полутора лет обсуждений специалистов из Siemens, Omron, Phoenix Contact, CoDeSys и нескольких университетов. Документ разбит на пять разделов, и у каждого правила есть буквенный префикс:
|
Раздел |
Префикс |
Содержание |
|
Именование |
N |
как называть переменные, задачи, блоки, типы данных |
|
Комментарии |
C |
как документировать код |
|
Правила кодирования |
CP |
общие принципы написания логики |
|
Языки |
L |
особенности конкретных языков стандарта, включая ST |
|
Расширения |
E |
нестандартные возможности отдельных платформ |
Всего в документе около 30 пронумерованных правил, и у каждого указана степень важности - высокая, средняя или низкая, - а также примеры неправильного и правильного кода. Разработчикам рекомендуется не слепо копировать весь список, а сначала оценить зрелость своей организации и тип задачи, а затем составить собственный сокращённый набор правил на основе этого документа.
Как называть переменные и блоки
Правило N1 запрещает использовать в коде "голые" физические адреса вроде %QW10 - вместо этого нужно объявлять переменную с понятным именем. Причина прозаична: программа с адресами вместо имён превращается в ребус, который приходится разгадывать при каждом переносе на другой контроллер или даже другую версию прошивки того же производителя.
Дальше начинается область, где стандарт даёт свободу, но требует последовательности. PLCopen не навязывает конкретную систему префиксов, только просит её документировать. Тем не менее в практике сложилась венгерская нотация, привязанная к типам данных третьей редакции стандарта - часть этих обозначений приведена в таблице.
|
Тип данных |
Префикс |
Тип данных |
Префикс |
|
BOOL |
x |
REAL |
r |
|
INT |
i |
LREAL |
lr |
|
DINT |
di |
STRING |
s |
|
UINT |
ui |
TIME |
t |
|
BYTE |
by |
ARRAY |
a |
|
STRUCT |
st |
ENUM |
e |
Отдельная система префиксов существует для самих POU: функциональный блок принято обозначать префиксом fb, программу - prg, класс - cls. А вот регистр букв в составных именах - вопрос не менее принципиальный, чем сами префиксы.
PLCopen предлагает использовать UPPER_SNAKE_CASE для констант и пользовательских типов данных, а UpperCamelCase - для всех остальных составных имён, то есть каждое слово внутри идентификатора начинается с большой буквы без разделителей.
Многие производители, например Beckhoff в своей документации TwinCAT, применяют эту же логику: префикс объекта пишется прописными буквами и отделяется подчёркиванием, а дальше следует CamelCase без пробелов и дефисов.
Есть и практические ограничения на длину имени. PLCopen советует не опускаться ниже восьми символов и не превышать двадцати пяти, стремясь к пятнадцати как к разумному компромиссу - слишком короткие имена типа Go или aaa ничего не говорят о назначении переменной, а слишком длинные, вроде ReadAndScaleTheTemperatureInput, утомляют глаз при чтении кода.
Отдельное правило запрещает совпадение имён локальной и глобальной переменной: компилятор такую конструкцию, скорее всего, пропустит, но программист, читающий код через полгода, рискует перепутать, к какой именно переменной обращается конкретная строка.
Комментарии: объяснять намерение, а не пересказывать код
PLCopen формулирует эту мысль довольно строго: комментарий должен описывать назначение кода, а не повторять то, что уже видно из самого текста программы.
Комментарий вида "// увеличиваем счётчик на единицу" рядом со строкой Counter := Counter + 1 бесполезен - а вот пояснение, зачем именно в этом месте счётчик увеличивается и что произойдёт, когда он достигнет предела, экономит время следующему разработчику.
Синтаксис ST предлагает два инструмента: символы // для однострочного комментария и пару (* ... *) для многострочного блочного, и стандарт советует избегать вложенных блочных комментариев, поскольку они по-разному обрабатываются разными средами разработки.
Правила написания логики
Раздел Coding Practice - самый объёмный в документе PLCopen, и часть его правил касается вещей, о которых начинающий программист ST обычно не задумывается до первой серьёзной аварии на объекте.
Все переменные должны получать начальное значение до первого использования - неинициализированная переменная в контроллере, в отличие от настольного компьютера, может унаследовать случайное значение из памяти, оставшееся от предыдущего цикла работы другой программы.
Сравнивать значения с плавающей точкой, а также величины времени и физических измерений, на точное равенство или неравенство запрещается: округление при вычислениях делает такое сравнение ненадёжным, вместо него стандарт рекомендует проверять, попадает ли разность значений в допустимый диапазон.
Отдельная группа правил касается многозадачности, что особенно актуально для контроллеров, где несколько программ работают на разных временных циклах.
Одну и ту же переменную не должны одновременно записывать несколько задач, а физический выход контроллера следует записывать ровно один раз за цикл выполнения программы - иначе результат работы устройства начинает зависеть от порядка выполнения задач, что превращает отладку в угадывание.
Использование операторов JUMP и RETURN стандарт советует ограничивать, а каждая POU должна иметь единственную точку выхода - тогда логику завершения блока видно сразу, без необходимости просматривать весь текст в поисках скрытых выходов посередине кода.
По той же причине PLCopen рекомендует ограничивать применение глобальных переменных: каждая из них, теоретически, может быть изменена любой частью программы, и чем их больше, тем труднее локализовать источник ошибки.
Особенности синтаксиса Structured Text
Для самого языка ST PLCopen выделяет отдельный раздел с девятью правилами. Одно из первых требований - определить общие правила форматирования кода и придерживаться их во всём проекте: отступы, расстановка пробелов вокруг операторов, оформление вложенных блоков IF и CASE.
Само по себе форматирование не влияет на работу программы - язык не чувствителен ни к регистру, ни к количеству пробелов, - но именно отступы делают структуру кода видимой глазу, а не только компилятору.
Отдельное правило касается циклов FOR: переменную-счётчик нельзя изменять внутри тела цикла и нельзя использовать за его пределами, поскольку после завершения цикла её значение по стандарту считается неопределённым.
Для порядка вычислений в сложных выражениях рекомендуется явно расставлять скобки, даже там, где приоритет операций формально понятен без них - двойное толкование выражения a + b * c намного опаснее в контроллере, управляющем реальным оборудованием, чем в учебном примере.
А каждая конструкция IF должна, по возможности, включать ветку ELSE, чтобы явно определить поведение программы для всех случаев, а не только для тех, что автор держал в голове при написании кода.
Зачем всё это нужно на практике
Стоимость промышленного программного обеспечения по оценкам самой PLCopen составляет до половины стоимости внедрения автоматизированной системы, а сопровождение забирает от 40 до 80% затрат за весь жизненный цикл проекта.
За этими цифрами стоит простая логика: код на ST живёт годами, его читают и правят не только автор, но и коллеги, которые придут после него, часто без возможности спросить у первоначального разработчика, что он имел в виду в той или иной строке.
Правила PLCopen - это, по сути, попытка договориться заранее о языке, на котором инженеры будут разговаривать друг с другом через код, вне зависимости от того, на каком контроллере он в итоге окажется запущен.
Подробный гайд в PDF: Какие лучшие практики ST рекомендует IEC 61131-3
Коллекция учебных материалов по автоматизации и программированию ПЛК
Андрей Повный
