Типичные ошибки при программировании ПЛК и их решение
5 ошибок в коде ПЛК (и как их исправить)

Объект сдан, акты подписаны. Но через неделю звонит заказчик: «ПЛК ушел в стоп», «Значения уставок слетели после перезагрузки», «Насос дергается». Вы открываете проект и видите не инженерную логику, а набор «костылей».
В программировании промышленных контроллеров действуют жесткие законы реального времени. Здесь нельзя просто «подождать». Здесь каждый байт памяти на счету.
Разберем типичные архитектурные ошибки, которые допускают даже опытные специалисты при переходе с релейной логики на ST.
1. Попытка организовать задержку через циклы (Убийство Watchdog)
Самая частая ошибка при миграции программистов с C++ или Python. В IT, чтобы подождать 5 секунд, пишут паузу. В ПЛК новички пытаются сделать это через цикл WHILE или REPEAT, ожидая, пока переменная изменит состояние.
Почему это фатально: ПЛК работает циклически. Чтение входов -> Выполнение программы -> Запись выходов. Если программа «застрянет» в цикле WHILE внутри одного скана дольше, чем разрешено (обычно 100-500 мс), сработает аппаратный сторожевой таймер (Watchdog Timer). Контроллер уйдет в ошибку EXCEPTION и остановит всё производство.
Как правильно (ST): Для задержек используются только таймеры (TON, TOF, TP). Они не останавливают выполнение кода, а работают параллельно с ним, считая время между вызовами.
Неправильно (Блокировка цикла):
Правильно (Таймер):
2. Сравнение REAL «в лоб»
Вы пишете условие: IF rTemperature = 50.0 THEN .... На панели оператора вы видите ровно 50.0. Но условие не срабатывает.
В чем проблема: Числа с плавающей точкой (REAL/LREAL) хранятся в формате IEEE 754. Из-за особенностей двоичной математики число 50.0 в памяти может выглядеть как 49.9999999 или 50.0000001. Оператор равенства = вернет FALSE.
Как правильно: Всегда используйте «зону нечувствительности» (Deadband) или функцию ABS (модуль числа).
Правильно (ST):
3. «Спагетти-код» на флагах вместо CASE
Когда нужно реализовать последовательность (Шаг 1: Налить воду -> Шаг 2: Нагреть -> Шаг 3: Слить), новички часто плодят десятки булевых переменных: bStep1_Done, bStep2_Active.
Через месяц в таком коде невозможно разобраться. Условия конфликтуют, появляются «гонки сигналов» (Race Condition), когда два шага включаются одновременно.
Как правильно: Используйте конструкцию CASE (Машина состояний / State Machine). Это стандарт де-факто для реализации алгоритмов управления.
Пример (ST):
4. Выход за границы массива (Array Out of Bounds)
В CODESYS (и в ПЛК СТАБУР на его базе) объявление массива выглядит так: arrValues : ARRAY [1..10] OF INT;. Если в цикле FOR вы по ошибке обратитесь к arrValues[11], компилятор может пропустить это, но во время работы произойдет запись в чужую область памяти. Это может перезаписать соседние переменные, вызвать сбой ядра или непредсказуемое поведение выходов.
Решение:
- Внимательно следите за индексами циклов.
- Используйте функцию CheckBounds. В CODESYS можно добавить специальный POU CheckBounds, который будет перехватывать любые обращения за пределы массивов и ограничивать их. Это немного увеличивает время цикла, но спасает от критических сбоев.
5. Потеря данных при рестарте (Retain vs Persistent)
Частая боль: оператор настроил уставки ПИД-регулятора, ночью на заводе моргнул свет, ПЛК перезагрузился — все настройки сбросились в ноль.
В чем ошибка: Программист объявил переменные просто как VAR. При перезагрузке (Reset Warm/Cold) они инициализируются дефолтными значениями.
Как правильно:
- VAR_RETAIN: Данные сохраняются при выключении питания (хранятся в NVRAM или на батарейке). Но сбрасываются при «Заводском сбросе» (Reset Origin).
- VAR_PERSISTENT: Данные сохраняются даже при загрузке новой программы (если структура переменных не изменилась).
Для ПЛК СТАБУР, работающих в ответственных узлах (ТП, котельные), критические уставки всегда должны быть в области RETAIN.
Итог
Качественный код для АСУ ТП — это не тот, который «просто работает», а тот, который:
- Не блокирует цикл (использует таймеры и CASE).
- Предсказуем (учитывает погрешности REAL).
- Безопасен (проверяет границы массивов).
- Живуч (помнит уставки после аварии питания).
Используйте возможности среды разработки (Statemachine diagram, CheckBounds), а не изобретайте велосипеды, которые потом ломаются на реальном объекте.
