Что такое ПЛК и почему это не просто "мощный Arduino"
ПЛК (Программируемый Логический Контроллер) — это специализированный промышленный компьютер, разработанный для управления технологическими процессами в реальном времени. Главное отличие от обычного компьютера или Arduino — детерминизм: гарантированное время реакции на входные сигналы, независимо от загрузки процессора.
Когда на производстве нужно, чтобы насос включился строго через 50 мс после срабатывания датчика — это ПЛК. Когда допустима задержка в секунду — можно обойтись более дешёвыми решениями. Когда вопрос в надёжности и работе в условиях вибраций, пыли, температур от -40 до +70°C — снова ПЛК.
Другие ключевые отличия:
Цикличность: программа выполняется повторяющимися циклами (обычно 1–100 мс). Каждый цикл: считать все входы → выполнить программу → записать все выходы
Гальваническая развязка входов/выходов: промышленные сигналы (24В DC, 220В AC) изолированы от внутренней логики
Горячая замена модулей: во многих системах можно менять I/O-модули без остановки контроллера
Встроенная диагностика: ПЛК сам следит за собственным здоровьем
Архитектура ПЛК: как это устроено
Центральный процессорный модуль (CPU)
Выполняет программу, управляет обменом данных, содержит основную память. В S7-1200 CPU также имеет встроенные входы/выходы, Ethernet порт и возможность расширения.
Модули ввода-вывода (I/O Modules)
Дискретные входы (DI): Воспринимают сигналы "есть напряжение / нет напряжения". Обычно 24В DC или 220В AC. Примеры источников: кнопки, концевые выключатели, датчики приближения (индуктивные, ёмкостные), фотодатчики, реле.
Дискретные выходы (DO): Управляют исполнительными устройствами. Бывают транзисторные (24В DC, быстрые) и релейные (любое напряжение до 250В AC, медленные, но универсальные).
Аналоговые входы (AI): Принимают непрерывные сигналы: 4–20мА, 0–10В, термопары (тип K, J, T...), термосопротивления (Pt100, Pt1000). Преобразуют в число (обычно 0–27648 для диапазона 0–100%).
Аналоговые выходы (AO): Выдают аналоговые сигналы для управления частотниками, регулирующими клапанами, позиционерами.
Память ПЛК (на примере Siemens)
Область | Обозначение | Описание |
|---|---|---|
Входы | I, %IX | Образ входов, обновляется каждый цикл |
Выходы | Q, %QX | Образ выходов, пишется в физику после цикла |
Меркеры | M, %MX | Внутренние биты/байты/слова — "рабочая память" |
Таймеры | T (S7-classic) / IEC-timer | Отсчёт времени |
Счётчики | C (S7-classic) / IEC-counter | Счёт импульсов |
Data Blocks | DB | Блоки данных: рецепты, уставки, история |
Стандарт МЭК 61131-3: пять языков программирования
Международный стандарт определяет пять языков для ПЛК. Хороший инженер знает минимум два-три.
1. Ladder Diagram (LD) — Релейно-контактная схема
Исторически первый язык — имитация схем из физических реле. Читается слева направо, как электрическая цепь. Левая шина — "фаза", правая — "ноль". Ток "течёт" если путь замкнут.
I0.0 I0.1 Q0.0
Пуск Стоп (НЗ) Выход насос
──┤ ├────┤/├──────────( )──
Q0.0 (самоподхват)
──┤ ├──
Эта схема — классика: кнопка ПУСК (I0.0) запускает насос (Q0.0), контакт самоподхвата удерживает его включённым, кнопка СТОП (I0.1, нормально-закрытый) его отключает.
Преимущества LD: Понятен электрикам без IT-образования, визуально отображает логику цепей, легко отлаживать онлайн (подсвечиваются активные цепи).
Недостатки: Громоздкий для сложных вычислений и работы с данными.
2. Function Block Diagram (FBD) — Диаграмма функциональных блоков
Программа строится из готовых блоков (AND, OR, NOT, таймеры, счётчики, ПИД-регуляторы), соединённых сигнальными линиями. Хорошо подходит для управления потоками сигналов.
I0.0 ──┐
├──[AND]──── Q0.0
I0.1 ──┘
3. Structured Text (ST) — Структурированный текст
Язык высокого уровня, похожий на Pascal/Ada. Самый мощный для математических вычислений, работы с массивами, строками.
(* Программа управления насосом с ПИД *)
IF Start AND NOT Stop THEN
Running := TRUE;
END_IF;
IF Stop THEN
Running := FALSE;
END_IF;
(* Расчёт ПИД *)
IF Running THEN
Error := Setpoint - Feedback;
Integral := Integral + Error * CycleTime;
Integral := LIMIT(-100.0, Integral, 100.0); (* Ограничение интеграла *)
Output := Kp * Error + Ki * Integral + Kd * (Error - PrevError) / CycleTime;
Output := LIMIT(0.0, Output, 100.0);
PrevError := Error;
ELSE
Output := 0.0;
Integral := 0.0;
END_IF;
4. Instruction List (IL) — Список инструкций
Ассемблер для ПЛК. Устаревший язык, в новом стандарте МЭК 61131-3 третьей редакции официально deprecated. Знать необязательно.
5. Sequential Function Chart (SFC) — Диаграмма последовательных функций
Похоже на блок-схему или граф состояний. Идеален для описания технологических последовательностей: шаг 1 → условие перехода → шаг 2 → условие → шаг 3...
Реальный проект: управление насосной станцией
Разберём полноценный пример — система управления двумя насосами с чередованием и защитами.
Техническое задание:
2 насоса, работают поочерёдно для равномерного износа
Автоматическое включение второго при отказе первого
Защита от сухого хода (датчик уровня)
Защита от давления (реле давления)
Ручной/автоматический режим
Счётчик моточасов каждого насоса
Распределение входов/выходов:
ВХОДЫ:
I0.0 — Кнопка ПУСК (автоматический режим)
I0.1 — Кнопка СТОП
I0.2 — Переключатель Авт/Ручной
I0.3 — Датчик уровня (нижний предел — сухой ход)
I0.4 — Датчик уровня (верхний предел — бак полон)
I0.5 — Реле давления насос 1 (авария — нет давления)
I0.6 — Реле давления насос 2
I0.7 — Тепловое реле насос 1 (перегрев)
I1.0 — Тепловое реле насос 2
I1.1 — Ручное управление насос 1 (в ручном режиме)
I1.2 — Ручное управление насос 2
ВЫХОДЫ:
Q0.0 — Контактор насос 1
Q0.1 — Контактор насос 2
Q0.2 — Лампа "Работа авто"
Q0.3 — Лампа "Авария"
Q0.4 — Сирена (авария критическая)
Программа на Structured Text (ST):
PROGRAM PumpStation
(* ===== ПЕРЕМЕННЫЕ ===== *)
VAR
// Входы
btnStart AT %I0.0 : BOOL;
btnStop AT %I0.1 : BOOL;
swAutoManual AT %I0.2 : BOOL; // TRUE = авто
snsLevelLow AT %I0.3 : BOOL; // TRUE = уровень низкий (авария)
snsLevelHigh AT %I0.4 : BOOL; // TRUE = бак полон
relPressure1 AT %I0.5 : BOOL; // FALSE = нет давления (авария)
relPressure2 AT %I0.6 : BOOL;
thmRelay1 AT %I0.7 : BOOL; // TRUE = перегрев (авария)
thmRelay2 AT %I1.0 : BOOL;
btnPump1Manual AT %I1.1 : BOOL;
btnPump2Manual AT %I1.2 : BOOL;
// Выходы
outPump1 AT %Q0.0 : BOOL;
outPump2 AT %Q0.1 : BOOL;
lampAutoRun AT %Q0.2 : BOOL;
lampFault AT %Q0.3 : BOOL;
siren AT %Q0.4 : BOOL;
// Внутренние переменные
SystemRun : BOOL := FALSE;
ActivePump : INT := 1; // Какой насос сейчас основной
Fault : BOOL := FALSE;
FaultCode : INT := 0;
Pump1Fault : BOOL := FALSE;
Pump2Fault : BOOL := FALSE;
// Таймеры
TimerPumpStart : TON; // Задержка пуска насоса
TimerRotation : TON; // Таймер чередования (8 часов)
TimerAlarmDelay : TON; // Задержка подтверждения аварии
// Счётчики моточасов
Hours_Pump1 : DINT := 0;
Hours_Pump2 : DINT := 0;
TimerH_Pump1 : TON;
TimerH_Pump2 : TON;
END_VAR
(* ===== ЛОГИКА АВАРИЙ ===== *)
// Авария сухого хода — критическая, немедленная остановка
IF snsLevelLow THEN
Fault := TRUE;
FaultCode := 1; // Сухой ход
SystemRun := FALSE;
END_IF;
// Задержанные аварии давления (3 секунды для исключения ложных срабатываний)
TimerAlarmDelay(IN := (outPump1 AND NOT relPressure1) OR
(outPump2 AND NOT relPressure2),
PT := T#3S);
IF TimerAlarmDelay.Q THEN
IF outPump1 AND NOT relPressure1 THEN
Pump1Fault := TRUE;
FaultCode := 2; // Нет давления насос 1
END_IF;
IF outPump2 AND NOT relPressure2 THEN
Pump2Fault := TRUE;
FaultCode := 3; // Нет давления насос 2
END_IF;
END_IF;
// Тепловая защита
IF thmRelay1 THEN
Pump1Fault := TRUE;
FaultCode := 4; // Перегрев насос 1
END_IF;
IF thmRelay2 THEN
Pump2Fault := TRUE;
FaultCode := 5; // Перегрев насос 2
END_IF;
// Оба насоса в аварии
IF Pump1Fault AND Pump2Fault THEN
Fault := TRUE;
SystemRun := FALSE;
END_IF;
(* ===== КОМАНДЫ ПУСК/СТОП ===== *)
IF btnStart AND NOT Fault THEN
SystemRun := TRUE;
END_IF;
IF btnStop OR snsLevelHigh THEN // Стоп или бак полон
SystemRun := FALSE;
END_IF;
// Квитирование аварии (нажать СТОП для сброса)
IF btnStop THEN
Fault := FALSE;
FaultCode := 0;
Pump1Fault := FALSE;
Pump2Fault := FALSE;
END_IF;
(* ===== АВТОМАТИЧЕСКИЙ РЕЖИМ ===== *)
IF swAutoManual AND SystemRun THEN
// Чередование каждые 8 часов
TimerRotation(IN := SystemRun, PT := T#28800S); // 8 часов = 28800 секунд
IF TimerRotation.Q THEN
IF ActivePump = 1 THEN
ActivePump := 2;
ELSE
ActivePump := 1;
END_IF;
TimerRotation(IN := FALSE); // Сброс таймера
TimerRotation(IN := TRUE);
END_IF;
// При аварии основного насоса — переключаемся на резервный
IF ActivePump = 1 AND Pump1Fault AND NOT Pump2Fault THEN
ActivePump := 2;
ELSIF ActivePump = 2 AND Pump2Fault AND NOT Pump1Fault THEN
ActivePump := 1;
END_IF;
// Задержка пуска 1 секунда (защита от дребезга)
TimerPumpStart(IN := SystemRun, PT := T#1S);
outPump1 := TimerPumpStart.Q AND (ActivePump = 1) AND NOT Pump1Fault;
outPump2 := TimerPumpStart.Q AND (ActivePump = 2) AND NOT Pump2Fault;
(* ===== РУЧНОЙ РЕЖИМ ===== *)
ELSIF NOT swAutoManual THEN
outPump1 := btnPump1Manual AND NOT Pump1Fault;
outPump2 := btnPump2Manual AND NOT Pump2Fault;
ELSE
outPump1 := FALSE;
outPump2 := FALSE;
END_IF;
(* ===== СЧЁТЧИКИ МОТОЧАСОВ ===== *)
TimerH_Pump1(IN := outPump1, PT := T#1S);
IF TimerH_Pump1.Q THEN
Hours_Pump1 := Hours_Pump1 + 1;
TimerH_Pump1(IN := FALSE);
TimerH_Pump1(IN := TRUE);
END_IF;
TimerH_Pump2(IN := outPump2, PT := T#1S);
IF TimerH_Pump2.Q THEN
Hours_Pump2 := Hours_Pump2 + 1;
END_IF;
(* ===== ИНДИКАЦИЯ ===== *)
lampAutoRun := SystemRun AND swAutoManual;
lampFault := Fault OR Pump1Fault OR Pump2Fault;
siren := Fault; // Сирена только при критической аварии
END_PROGRAM
Таймеры и счётчики: подробно
Таймеры и счётчики — основа любой программы ПЛК. В стандарте МЭК 61131-3 они реализованы как функциональные блоки.
Типы таймеров
TON (Timer On Delay) — таймер с задержкой включения:
TimerFan(IN := MotorRun, PT := T#5S);
// Q становится TRUE через 5 секунд после включения MotorRun
FanStart := TimerFan.Q;
TOF (Timer Off Delay) — таймер с задержкой выключения:
TimerFan(IN := MotorRun, PT := T#30S);
// Q остаётся TRUE ещё 30 секунд после выключения MotorRun
// Используется для дополнительного охлаждения после остановки
FanRun := TimerFan.Q;
TP (Timer Pulse) — таймер импульса:
TimerBuzzer(IN := AlarmNew, PT := T#2S);
// При фронте AlarmNew генерирует импульс 2 секунды
// Независимо от того, сколько ещё держится AlarmNew
Buzzer := TimerBuzzer.Q;
Счётчики
CTU (Count Up) — счётчик вперёд:
CounterBottles(CU := BottleSensor, R := ResetButton, PV := 100);
// Считает бутылки, при достижении 100 — Q=TRUE
BatchComplete := CounterBottles.Q;
CurrentCount := CounterBottles.CV; // Текущее значение
CTD (Count Down) — счётчик назад:
CounterProducts(CD := ProductSensor, LD := LoadButton,
PV := OrderQty); // PV загружается при LD=TRUE
OrderComplete := CounterProducts.Q; // Q=TRUE когда CV=0
Работа с аналоговыми сигналами
Масштабирование аналогового входа
Аналоговый модуль S7-1200 возвращает значение 0–27648 для диапазона 0–100% входного сигнала (4–20мА или 0–10В). Для получения реального значения нужно масштабирование:
FUNCTION_BLOCK ScaleAnalog
VAR_INPUT
RawValue : INT; // Сырое значение от АЦП (0..27648)
RawMin : INT; // Мин значение АЦП (обычно 0 или 5530 для 4мА)
RawMax : INT; // Макс значение АЦП (обычно 27648)
PhysMin : REAL; // Физический минимум (например, 0.0 бар)
PhysMax : REAL; // Физический максимум (например, 16.0 бар)
END_VAR
VAR_OUTPUT
PhysValue : REAL; // Результат в физических единицах
Broken : BOOL; // Обрыв линии (значение ниже 4мА)
END_VAR
// Проверка обрыва линии (для 4-20мА: ниже ~5% = обрыв)
Broken := (RawValue < (RawMin - 1000));
IF NOT Broken THEN
// Линейное масштабирование
PhysValue := PhysMin + (REAL(RawValue - RawMin) / REAL(RawMax - RawMin))
* (PhysMax - PhysMin);
// Ограничение выхода
PhysValue := MAX(PhysMin, MIN(PhysMax, PhysValue));
ELSE
PhysValue := PhysMin; // При обрыве — безопасное значение
END_IF;
END_FUNCTION_BLOCK
Использование:
// Датчик давления 4-20мА, диапазон 0-16 бар
PressureSensor(
RawValue := %IW64, // Адрес аналогового входа
RawMin := 5530, // 4мА соответствует 5530
RawMax := 27648, // 20мА соответствует 27648
PhysMin := 0.0,
PhysMax := 16.0
);
Pressure := PressureSensor.PhysValue; // Давление в барах
PressureAlarm := PressureSensor.Broken; // Авария обрыва линии
IF Pressure > 12.0 THEN
HighPressureAlarm := TRUE;
END_IF;
Организационные блоки и структура программы
Профессиональная программа ПЛК разделена на функциональные блоки:
Организация в TIA Portal (Siemens):
OB1 (Main) — Главный цикл
├── FC10: ReadInputs — Чтение и нормализация входов
├── FC20: SafetyLogic — Приоритетные защиты (всегда первыми!)
├── FB30: PumpControl [DB30] — Управление насосами (с памятью)
├── FB40: PIDControl [DB40] — ПИД-регулятор
├── FC50: WriteOutputs — Запись выходов
└── FC60: Diagnostics — Диагностика и коммуникации
OB35 (Cyclic Interrupt, 10ms) — Быстрые задачи
└── FB35: FastCounter — Высокоскоростной счётчик
OB82 (I/O Error) — Обработка ошибок I/O-модулей
OB121 (Programming Error) — Обработка ошибок программы
Принцип: защиты и аварии — всегда в начале главного цикла. Они должны отработать независимо от состояния остальной программы.
Отладка и диагностика программы
Онлайн-мониторинг
В TIA Portal при подключении к ПЛК все блоки отображают реальные значения переменных. В Ladder Diagram активные цепи подсвечиваются зелёным — мгновенно видно что работает.
Форсирование переменных (Force)
Можно принудительно установить значение входа или переменной для тестирования. Внимание: принудительные значения перекрывают реальные физические сигналы. Не забудьте снять форсирование перед вводом в эксплуатацию!
Трассировка
Запись значений переменных в реальном времени с временной меткой. Незаменима для поиска редко возникающих ошибок — включаете запись и ждёте появления проблемы.
Типичные ошибки начинающих:
1. Использование выходных катушек несколько раз в Ladder
НЕПРАВИЛЬНО:
Цепь 1: I0.0 → Q0.0 (катушка)
Цепь 2: I0.1 → Q0.0 (катушка снова!)
Вторая катушка перезаписывает первую. Результат Q0.0 определяется только второй цепью.
ПРАВИЛЬНО:
Цепь 1: I0.0 ──┐
├── Q0.0
Цепь 2: I0.1 ──┘
2. Гонка состояний при SET/RESET
// ОПАСНО: порядок операций важен
IF Condition1 THEN SET(Coil); END_IF;
IF Condition2 THEN RESET(Coil); END_IF;
// Если оба условия TRUE — RESET побеждает (последний)
// Убедитесь, что это желаемое поведение!
3. Деление на ноль
// ВСЕГДА проверяйте делитель
IF Denominator <> 0.0 THEN
Result := Numerator / Denominator;
ELSE
Result := 0.0; // Безопасное значение
END_IF;
Коммуникация ПЛК с внешним миром
Modbus TCP (через Ethernet)
Большинство современных ПЛК поддерживают Modbus TCP "из коробки". Это самый распространённый протокол для связи с SCADA, HMI и частотниками.
В S7-1200 для Modbus TCP используются системные функциональные блоки:
MB_CLIENT— ПЛК как Modbus-мастер (опрашивает устройства)MB_SERVER— ПЛК как Modbus-сервер (отвечает на запросы SCADA)
OPC UA
Современный открытый протокол для промышленной коммуникации. Поддерживает семантику данных, безопасность, публикацию/подписку. Все серьёзные ПЛК последних поколений имеют встроенный OPC UA сервер.
PROFINET/EtherCAT
Промышленные реальном-временные сети. PROFINET — стандарт Siemens и Profibus International. EtherCAT — от Beckhoff, исключительно быстрый (цикл 250 мкс). Используются для связи с распределёнными I/O-модулями, сервоприводами, vision-системами.
Советы по надёжности программы
Всегда инициализируйте переменные — не полагайтесь на "нулевое" начальное значение
Используйте watchdog-таймер — если программа "зависла", таймер переводит выходы в безопасное состояние
Документируйте каждую переменную — через полгода вы забудете что значит переменная
b47Разделяйте задачи по функциональным блокам — один блок = одна задача
Тестируйте на симуляторе перед загрузкой в реальный ПЛК
Делайте резервные копии программы перед каждым изменением — версионирование спасало многих
Стандартизируйте именование:
btnStart— кнопка,snsLevel— датчик,outPump— выход,tmrDelay— таймер
Заключение
Программирование ПЛК — это отдельная инженерная дисциплина на стыке электротехники, автоматики и программирования. Ключевой принцип: программа управляет реальным оборудованием, и любая ошибка может привести к аварии или травме. Поэтому надёжность, защиты и понятность кода здесь важнее красоты архитектуры.
Начните с Ladder Diagram — он прозрачен и хорошо отлаживается онлайн. Освойте Structured Text для сложных вычислений. Используйте SFC для технологических последовательностей. И всегда: сначала безопасность, потом функциональность.
Хорошая программа ПЛК должна безопасно остановить оборудование при любой нештатной ситуации — потере связи, пропадании питания, выходе из строя датчика. Проектируйте с расчётом на отказ.
Create an account or sign in to leave a review
There are no reviews to display.