Codesys 3.5 Обучение программированию.
263 subscribers
38 photos
13 videos
1 file
63 links
Download Telegram
🤖 Создал ООП-проект ПЛК в CODESYS 3.5 с помощью искусственного интеллекта

Я записал видео, в котором с нуля создаю полноценный учебный проект на языке Structured Text с применением ООП.

Начинаем с пустого проекта, продумываем архитектуру и последовательно создаём:

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

Главная идея видео — проверить, способен ли искусственный интеллект помочь инженеру АСУ ТП создать архитектуру проекта и написать рабочий код для CODESYS 3.5.

Получилось интересно: ИИ действительно заметно ускоряет разработку, но его код всё равно необходимо понимать, проверять и дорабатывать.

🎬 Смотреть видео:
https://youtu.be/-j8io3dqLOQ

Полезные материалы:

📊 Курс «Обработка аналоговых сигналов ПЛК в CODESYS 3.5»:
https://codesys3-5.skillspace.ru/l/obrabotka-analogovyh-signalov-plk-0b9b92

📘 Курс «Программирование в CODESYS 3.5. Основы»:
https://codesys3-5.skillspace.ru/l/programmirovanie-v-srede-codesys-3-5

💬 Telegram-чат специалистов по CODESYS 3.5:
https://t.me/codesys35

🎓 Telegram-канал по обучению программированию в CODESYS 3.5:
https://t.me/codesys4

Как считаете, сможет ли ИИ в будущем самостоятельно создавать промышленные проекты ПЛК или он останется только помощником инженера? Пишите своё мнение в комментариях.
🤖 Этот пост создан с помощью ИИ. Причём тему мы разбирали не в формате «подтверди моё мнение», а специально искали аргументы и за, и против.

🔌 «Выключи и включи питание ПЛК» — хороший совет или инженерное шаманство?

Наверняка многие инженеры АСУ ТП сталкивались с ситуацией:

ПЛК работал.
Что-то изменили.
И внезапно начинается какая-то чертовщина.

Модуль не выходит на связь.
Modbus перестал отвечать.
Вход показывает непонятное состояние.
Конфигурация вроде правильная.
Ошибок в программе не видно.

И тут появляется универсальный совет:

«А питание передёргивал?»

Звучит примерно как совет системного администратора:

«А компьютер перезагружать пробовали?» 😄

Самое интересное — иногда это действительно помогает.

Но почему?

🟢 Аргументы ЗА перезапуск по питанию

ПЛК и современные модули ввода-вывода — это вычислительные устройства: процессор, память, firmware, коммуникационные интерфейсы, внутренние состояния.

При включении питания оборудование проходит процедуру инициализации.

Условно:

POWER ON → загрузка firmware → самодиагностика → инициализация I/O → запуск интерфейсов → загрузка конфигурации → RUN

Полное снятие питания заставляет оборудование пройти эту последовательность заново.

Поэтому перезапуск действительно может помочь, если:

⚡ завис коммуникационный модуль;

⚡ после помехи некорректно работает RS-485;

⚡ модуль I/O оказался в состоянии Fault;

⚡ после изменения hardware-конфигурации оборудование нормально не переинициализировалось;

⚡ ПЛК потерял связь с модулем и не смог её восстановить;

⚡ после кратковременной просадки питания устройство осталось в некорректном состоянии;

⚡ внешний Modbus Slave завис и перестал отвечать.

И это не просто народная магия наладчиков.

В документации промышленного оборудования действительно можно встретить рекомендацию:

Cycle power to the module.

То есть иногда старое доброе:

«Выключи и включи»

— вполне нормальный инженерный инструмент.

Но здесь возникает гораздо более интересный вопрос.

Допустим:

Modbus не работал → передёрнули питание → заработал.

Означает ли это, что мы действительно устранили неисправность?

Или мы просто временно убрали её проявление?

Об этом — во второй части.
🔌 Сброс питания ПЛК. Часть 2

В первой части мы выяснили, почему старое доброе:

«Выключи и включи»

иногда действительно работает.

Теперь посмотрим на другую сторону.

Представим:

Modbus перестал работать → передёрнули питание → заработало.

Можно сказать:

«Проблема решена!»

А можно задать другой вопрос:

«Почему она вообще возникла?»

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

— плохое питание 24 В;
— помехи на RS-485;
— неправильное заземление;
— ошибки termination/bias;
— конфликт адресов;
— ошибка firmware;
— переполнение внутреннего буфера;
— ошибка программы;
— неправильная последовательность запуска устройств;
— аппаратная неисправность модуля.

Перезапуск мог просто устранить следствие, не устранив причину.

Через неделю проблема появится снова.

⚠️ Более того, перезапуск может уничтожить улики

До отключения питания у нас могли оставаться:

код ошибки → состояние LED → диагностические регистры → состояние коммуникации → значения переменных → журналы событий.

Передёрнули питание —

и часть информации исчезла.

Получается парадокс:

установку восстановили, а информацию, которая могла помочь найти причину остановки, потеряли.

Поэтому при повторяющейся неисправности правильнее:

сначала зафиксировать диагностику → потом перезапускать.

❌ Иногда питание вообще лучше не трогать

Очевидный пример — обновление firmware.

Но есть и более важный момент.

На реальном технологическом объекте после power cycle нужно понимать:

Что произойдёт с выходами?
Что произойдёт с приводами?
Сохранятся ли RETAIN-переменные?
Запустится ли программа автоматически?
В каком состоянии окажутся исполнительные механизмы?

Поэтому:

«Давайте просто передёрнем питание»

на работающей установке — не всегда безобидное действие.

🟡 Так когда всё-таки перезапускать?

Если произошёл единичный непонятный сбой, диагностика зафиксирована, перезапуск технологически безопасен и производитель оборудования его допускает — почему бы и нет?

Но если получается:

понедельник — зависло → перезапустили;
среда — зависло → перезапустили;
пятница — зависло → перезапустили...

то это уже не устранение неисправности.

Это ритуал обслуживания неисправности. 😄

Поэтому правило я бы сформулировал так:

Сначала диагностика. Потом перезапуск.

А если после перезапуска всё заработало, не считать вопрос закрытым, а спросить:

«Почему снятие питания вообще помогло?»

Потому что именно ответ на этот вопрос иногда и приводит к настоящей причине неисправности.

А как поступаете вы?

Сначала передёргиваете питание или сначала пытаетесь докопаться до причины?
🤖 Вышло новое видео: создаём проект CODESYS 3.5 с помощью ИИ
Друзья, опубликовал новое большое практическое видео о том, как использовать искусственный интеллект при программировании ПЛК в CODESYS 3.5.
На этот раз мы не ограничиваемся генерацией нескольких строк ST-кода. Я показываю процесс создания проекта практически с нуля и постепенно усложняю его.
━━━━━━━━━━━━━━━━━━━━
⚙️ Что делаем в видео:
🔹 создаём функциональный блок обработки дискретных сигналов DI;
🔹 создаём несколько экземпляров ФБ и вызываем их в программе;
🔹 добавляем обработку аналоговых сигналов AI;
🔹 выполняем преобразование RAW → инженерные единицы;
🔹 добавляем тестовый режим, диагностику и аварийные состояния;
🔹 переносим данные DI и AI в структуры и массивы;
🔹 обрабатываем несколько каналов через циклы;
🔹 создаём функциональный блок управления электродвигателем;
🔹 генерируем с помощью ИИ файлы для последующего импорта в CODESYS.
━━━━━━━━━━━━━━━━━━━━
🎓 И самое интересное — показываю, как таким способом можно изучать CODESYS вместе с ИИ.
Можно попросить ИИ создать функциональный блок, затем разобрать каждую переменную и строку программы, изменить алгоритм, добавить новую функцию, найти ошибку и сразу проверить всё непосредственно в CODESYS.
То есть ИИ становится не просто генератором кода, а своеобразным персональным помощником при изучении программирования ПЛК.
━━━━━━━━━━━━━━━━━━━━
🎥 Смотреть видео:
https://www.youtube.com/watch?v=h8OLwQy5PqU
━━━━━━━━━━━━━━━━━━━━
📚 Мои курсы для тех, кто хочет изучить тему подробнее:
💻 Программирование в среде CODESYS 3.5. Основы
https://codesys3-5.skillspace.ru/l/programmirovanie-v-srede-codesys-3-5
📊 Обработка аналоговых сигналов ПЛК в CODESYS 3.5
https://codesys3-5.skillspace.ru/l/obrabotka-analogovyh-signalov-plk-0b9b92
⚡️ Основы чтения принципиальных электрических схем
https://codesys.skillspace.ru/l/osnovy-ctenia-principial-nyh-elektriceskih-shem-fb9316
👍2
👋 Новым подписчикам и участникам чата — добро пожаловать!
Меня зовут Андрей, я автор курсов «Школы АСУ ТП». Для тех, кто хочет разобраться в программировании ПЛК и применять знания на практике, расскажу о двух моих курсах.
📘 Основы программирования ПЛК в CODESYS 3.5
Открыли CODESYS, а дальше непонятно: с чего начать проект, где писать код и как проверить, что программа работает?
Этот курс — для знакомства со средой и освоения основ. Разбираем структуру проекта, переменные, программы и функциональные блоки, запуск на виртуальном контроллере и проверку работы в онлайн-режиме.
Цель — не просто повторить пример, а понять, как устроена и выполняется программа ПЛК.
👉 Программа курса и запись: https://codesys3-5.skillspace.ru/l/programmirovanie-v-srede-codesys-3-5⁠�
🤝4
📊 Обработка аналоговых сигналов ПЛК в CODESYS 3.5
Датчик подключён. Но как превратить его сигнал в понятные значения температуры, давления или уровня? Как задать уставки и обработать ошибки?
В этом курсе разбираем сигналы 0–10 В и 4–20 мА, преобразование исходных значений в инженерные единицы, масштабирование, пороги и уставки, сигнализацию, ручной режим и визуализацию.
Практическая часть — разработка функционального блока в CODESYS 3.5 на языке ST.
От сигнала датчика — к его обработке и использованию в программе.
👉 Программа курса и запись: https://codesys3-5.skillspace.ru/l/obrabotka-analogovyh-signalov-plk-0b9b92⁠�
💡 Только начинаете? Начните с основ CODESYS. Уже знакомы со средой и хотите разобраться в работе с датчиками — переходите к курсу по аналоговым сигналам.
CODESYS 3.5: от первых программ ПЛК до обработки сигналов датчиков

Работаете с автоматикой или начинаете изучать программирование контроллеров? В «Школе АСУ ТП» есть два курса под разные задачи.

📘 Основы программирования ПЛК в CODESYS 3.5

Начните с основ: разберитесь в программировании контроллеров и освойте работу в среде CODESYS 3.5. Курс подойдёт для первого знакомства с программированием ПЛК и систематизации базовых знаний.

👉 "Посмотреть программу курса и записаться" (https://codesys3-5.skillspace.ru/l/programmirovanie-v-srede-codesys-3-5)

📊 Обработка аналоговых сигналов ПЛК в CODESYS 3.5

Разберитесь с сигналами 4–20 мА и 0–10 В, масштабированием и обработкой показаний датчиков. Для тех, кто хочет понимать, как входной сигнал превращается в значение давления, температуры или уровня в программе контроллера.

👉 "Посмотреть программу курса и записаться" (https://codesys3-5.skillspace.ru/l/obrabotka-analogovyh-signalov-plk-0b9b92)

Знакомьтесь с материалами и присоединяйтесь к сообществу:

📣 "Telegram-канал о CODESYS — материалы по программированию ПЛК" (https://t.me/codesys4)

💬 "Telegram-чат CODESYS 3.5 — вопросы, обсуждения и обмен опытом" (https://t.me/codesys35)
​⚡ Почему IF срабатывает много раз, хотя кнопку нажали только один раз?

Разберём простую, но очень важную особенность работы ПЛК.

Нужно увеличивать счётчик на 1 при каждом нажатии кнопки.

Пишем:

IF xButton THEN
iCounter := iCounter + 1;
END_IF


На первый взгляд всё логично:

🔘 нажали кнопку
➕ счётчик увеличился на 1

Но после одного нажатия вдруг получаем:

iCounter = 73


😳 Почему не 1?

━━━━━━━━━━━━━━

🔄 Всё дело в цикле ПЛК

ПЛК выполняет программу не один раз.

Он повторяет её циклически — снова и снова.

Допустим, время цикла задачи:

10 мс

А кнопку оператор удерживал примерно:

1 секунду

За это время программа выполнится примерно:

1000 мс / 10 мс = 100 циклов


И всё это время:

xButton = TRUE

Значит, в каждом цикле снова выполняется:

iCounter := iCounter + 1;


📈 Поэтому одно физическое нажатие может привести к десяткам или даже сотням выполнений одной и той же команды.

━━━━━━━━━━━━━━

🎯 Нужно ловить не состояние, а событие

Нас интересует не то, сколько времени xButton находится в состоянии TRUE.

Нам нужен только момент перехода:

FALSE → TRUE

Это называется передним фронтом сигнала.

В CODESYS для его обнаружения есть стандартный функциональный блок:

R_TRIG

━━━━━━━━━━━━━━

✅ Правильный вариант

VAR
xButton : BOOL;
fbTrig : R_TRIG;
iCounter : INT;
END_VAR

fbTrig(CLK := xButton);

IF fbTrig.Q THEN
iCounter := iCounter + 1;
END_IF


Теперь выход fbTrig.Q становится TRUE только на один цикл ПЛК — в момент появления переднего фронта.

Получаем:

🔘 нажали → +1
⏳ держим кнопку → ничего
🔘 отпустили → ничего
🔘 нажали снова → +1

━━━━━━━━━━━━━━

🧠 Главное различие

Когда мы пишем:

IF xButton THEN

мы спрашиваем:

«Сигнал сейчас активен?»

А R_TRIG отвечает на другой вопрос:

«Сигнал появился именно в этом цикле?»

Это две совершенно разные задачи.

━━━━━━━━━━━━━━

🏭 Где это используется на практике?

Обработка фронта постоянно встречается в программах ПЛК:

• команды с HMI
• квитирование аварий
• переключение режимов
• изменение уставок
• подсчёт событий
• запуск последовательностей
• обработка кнопок оператора

То есть везде, где действие должно выполниться один раз по событию, а не каждый цикл ПЛК.

━━━━━━━━━━━━━━

💡 Запомните

IF проверяет состояние.

R_TRIG ловит момент появления сигнала.

Небольшая разница в коде — огромная разница в поведении программы.

━━━━━━━━━━━━━━

💬 А как вы обрабатываете фронты в своих проектах?

Используете стандартные R_TRIG / F_TRIG или пишете свою логику через запоминание предыдущего состояния?

#CODESYS #ПЛК #АСУТП #StructuredText #ПрограммированиеПЛК
👍3
🧠 РАЗБОР КОДА

На картинке — простая ситуация из программы ПЛК.

xButton = TRUE в течение 5 циклов подряд.

Начальное значение:

iCounter = 0

❓ Какое значение будет у iCounter после пятого цикла?

Сначала попробуйте ответить самостоятельно.

👇 Разбор и правильный ответ — в следующем посте.

#CODESYS #ПЛК #StructuredText #ПрограммированиеПЛК
🧠 РАЗБОР КОДА

Исходный код:

IF xButton THEN
iCounter := iCounter + 1;
END_IF


Начальное значение:

iCounter = 0

Сигнал:

xButton = TRUE

в течение 5 циклов ПЛК подряд.

❓ Что будет в iCounter после пятого цикла?

А) 1
Б) 5
В) 0
Г) Зависит от времени цикла

Сначала выберите вариант, потом откройте ответ 👇

🔎 Открыть правильный ответ

✅ Правильный ответ — Б: iCounter = 5.

Почему?

Условие xButton = TRUE выполняется во всех пяти циклах.

Поэтому команда:

iCounter := iCounter + 1;

тоже выполняется пять раз.

Получаем:

0 → 1 → 2 → 3 → 4 → 5

Время цикла здесь не влияет на результат, потому что в условии уже сказано: xButton оставался TRUE ровно 5 циклов.


💡 Главная мысль

IF проверяет состояние сигнала в каждом цикле.

Если действие нужно выполнить только один раз при переходе:

FALSE → TRUE

нужно использовать определение переднего фронта, например R_TRIG.

💬 Получилось ответить правильно до открытия спойлера?

#CODESYS #ПЛК #StructuredText #ПрограммированиеПЛК
⏱ TON в CODESYS

Почему таймер иногда «не срабатывает»?

Разбираем принцип работы TON, сброс при IN = FALSE и типичные ошибки в программе.

👇 Подробный разбор — в следующем посте.
⏱ TON в CODESYS: как работает таймер задержки включения

TON — один из самых используемых таймеров в программах ПЛК.

Задержка включения двигателя, подтверждение аварии, фильтрация кратковременных сигналов, контроль превышения температуры — во всех этих задачах часто используется именно TON.

Но иногда возникает ситуация:

«На входе уже был TRUE, а таймер почему-то не сработал».

Разберём, как TON работает на самом деле.

━━━━━━━━━━━━━━━━━━

🔹 Что делает TON?

TON — это таймер задержки включения.

Объявим экземпляр таймера:

VAR
fbTimer : TON;
xSignal : BOOL;
xAlarm : BOOL;
END_VAR


Вызовем его:

fbTimer(
IN := xSignal,
PT := T#5s
);


Основные параметры:

IN — вход запуска таймера

PT — заданное время задержки

Q — выход таймера

ET — прошедшее время

В нашем примере:

PT := T#5s


Это означает, что IN должен непрерывно оставаться в состоянии TRUE в течение 5 секунд.

━━━━━━━━━━━━━━━━━━

🔄 Что происходит после IN = TRUE?

Пока:

IN = FALSE

таймер находится в сброшенном состоянии:

Q  = FALSE
ET = T#0s


Как только:

IN = TRUE

начинается отсчёт времени.

Условно процесс выглядит так:

0 сек → ET = 0 сек
1 сек → ET = 1 сек
2 сек → ET = 2 сек
3 сек → ET = 3 сек
4 сек → ET = 4 сек
5 сек → ET = 5 сек


Пока:

ET < PT


выход:

Q = FALSE


Когда заданное время достигнуто:

ET ≥ PT


получаем:

Q = TRUE


Если IN продолжает оставаться TRUE, выход Q тоже остаётся активным.

━━━━━━━━━━━━━━━━━━

⚠️ Самая важная особенность TON

Теперь представим такую ситуацию:

xSignal = TRUE   → 4.8 сек
xSignal = FALSE → 0.1 сек
xSignal = TRUE → снова


До заданных 5 секунд не хватило всего 0.2 секунды.

Что произойдёт?

Как только:

IN = FALSE

обычный TON сбрасывается:

ET → T#0s
Q → FALSE


Когда IN снова станет TRUE, отсчёт начнётся заново.

Предыдущие 4.8 секунды таймер не запоминает.

━━━━━━━━━━━━━━━━━━

🧠 TON считает непрерывное время

Это ключевой момент.

TON не отвечает на вопрос:

«Сколько всего времени сигнал был TRUE?»

Он отвечает:

«Как долго сигнал непрерывно находится в TRUE?»

Например:

TRUE  → 3 сек
FALSE → 1 сек
TRUE → 3 сек


Суммарно сигнал был активен:

3 + 3 = 6 секунд


Но при:

PT := T#5s


выход Q не станет TRUE.

Потому что ни один непрерывный участок TRUE не длился 5 секунд.

━━━━━━━━━━━━━━━━━━

🏭 Практический пример: задержка аварии

Допустим, есть температура:

rTemperature

Нужно сформировать аварию только в том случае, если температура выше 90 °C непрерывно держится 5 секунд.

Сначала получаем условие превышения:

xHighTemp := rTemperature > 90.0;


Затем запускаем таймер:

fbHighTemp(
IN := xHighTemp,
PT := T#5s
);

xAlarm := fbHighTemp.Q;


Что произойдёт?

Если температура кратковременно поднимется выше 90 °C, например на 300 мс:

xHighTemp = TRUE


таймер начнёт отсчёт.

Но как только температура снова опустится ниже 90 °C:

xHighTemp = FALSE


таймер сбросится.

Авария не появится.

Если же температура остаётся выше 90 °C непрерывно 5 секунд:

fbHighTemp.Q = TRUE


и сформируется аварийный сигнал.

Так TON позволяет отфильтровать кратковременные выбросы.

━━━━━━━━━━━━━━━━━━

⚠️ Частая ошибка: вызывать таймер только внутри IF

Иногда встречается такой код:

IF xSignal THEN
fbTimer(
IN := TRUE,
PT := T#5s
);
END_IF


Проблема в том, что когда xSignal = FALSE, функциональный блок вообще не вызывается.

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

fbTimer(
IN := xSignal,
PT := T#5s
);


А затем использовать его выход:

IF fbTimer.Q THEN
xAlarm := TRUE;
END_IF


Так алгоритм легко читать:

xSignal определяет состояние входа таймера на каждом цикле ПЛК.

━━━━━━━━━━━━━━━━━━

🔎 Для чего нужен ET?

ET показывает текущее прошедшее время.

Например:

fbTimer.ET


может иметь значения:

T#500ms
T#2s
T#4s
T#5s


Это удобно использовать для:

• диагностики программы
• отображения времени на HMI
• индикации процесса задержки
• анализа работы алгоритма
• отладки

Например, оператору можно показать:

«Авария будет подтверждена через 2.3 секунды».

Для основной логики обычно используют Q, а ET — как дополнительную информацию.

━━━━━━━━━━━━━━━━━━

📌 Коротко: алгоритм TON

Если:

IN = FALSE

получаем:

ET = T#0s
Q = FALSE


Если:

IN = TRUE

начинается отсчёт.

Пока:

ET < PT


получаем:

Q = FALSE

Когда:

ET ≥ PT


получаем:

Q = TRUE

Если после этого:

IN = FALSE

таймер снова сбрасывается.

━━━━━━━━━━━━━━━━━━

💡 Где TON используется на практике?

Очень часто:

• задержка формирования аварии
• фильтрация кратковременных сигналов
• задержка включения оборудования
• контроль устойчивого состояния датчика
• контроль длительного превышения параметра
• ожидание перед переходом на следующий шаг алгоритма
• антидребезг дискретных сигналов
• задержка разрешения операции

Главный вопрос при выборе TON:

«Нужно ли мне убедиться, что условие непрерывно выполняется заданное время?»

Если да — TON обычно подходит.

━━━━━━━━━━━━━━━━━━

🧠 Запомните

TON — это не просто команда:

«подождать 5 секунд».

Это проверка:

«Оставался ли вход IN непрерывно в TRUE в течение заданного времени PT?»

Даже кратковременный переход IN в FALSE приводит к сбросу отсчёта.

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

━━━━━━━━━━━━━━━━━━

❓ Проверим себя

Пусть задано:

PT := T#5s


Сигнал ведёт себя так:

TRUE  → 4.9 сек
FALSE → 0.1 сек
TRUE → 4.9 сек


Станет ли Q = TRUE хотя бы на одном цикле?

💬 Напишите свой ответ в комментариях 👇

#CODESYS #ПЛК #АСУТП #StructuredText #ST #ПрограммированиеПЛК #Автоматизация
🧠 РАЗБОР КОДА: TON

Сигнал xSignal был:

TRUE  → 4.9 сек
FALSE → 0.1 сек
TRUE → 4.9 сек


Таймер:

fbTimer(
IN := xSignal,
PT := T#5s
);


❓ Станет ли Q = TRUE?

Попробуйте ответить до того, как откроете разбор.

👇 Правильный ответ — в следующем посте.

#CODESYS #ПЛК #TON #StructuredText
🧠 РАЗБОР КОДА: TON

Разберём задачу.

Есть таймер:

fbTimer(
IN := xSignal,
PT := T#5s
);


Сигнал на входе меняется так:

TRUE  → 4.9 сек
FALSE → 0.1 сек
TRUE → 4.9 сек


Начальное состояние:

Q  = FALSE
ET = T#0s


❓ Что произойдёт с выходом Q?

А) Q станет TRUE, потому что суммарно сигнал был TRUE больше 5 секунд

Б) Q станет TRUE во втором интервале TRUE

В) Q ни разу не станет TRUE

Г) Q кратковременно станет TRUE в момент сброса

Сначала выберите вариант, потом откройте ответ 👇

🔎 Открыть правильный ответ

✅ Правильный ответ — В.

Q ни разу не станет TRUE.

Почему?

В первом интервале:

xSignal = TRUE → 4.9 сек

До PT = 5 сек не хватает 0.1 секунды, поэтому Q остаётся FALSE.

Затем сигнал становится FALSE.

Для TON это означает сброс:

ET → T#0s
Q → FALSE

После этого, когда xSignal снова становится TRUE, таймер начинает отсчёт заново.

Во втором интервале сигнал снова активен только 4.9 секунды, а этого опять недостаточно.

Поэтому Q ни разу не станет TRUE.


💡 Главная мысль

TON считает не суммарное время активности сигнала, а время, в течение которого вход IN находится в TRUE непрерывно.

Как только:

IN = FALSE

таймер сбрасывается.

💬 Получилось ответить правильно до открытия спойлера?

#CODESYS #ПЛК #TON #StructuredText #ПрограммированиеПЛК
👍3
⚡ R_TRIG и F_TRIG в CODESYS

Сигнал может оставаться TRUE или FALSE сотни циклов.

Но иногда нам нужен только один конкретный момент:

⬆️ сигнал появился
⬇️ сигнал исчез

Для этого в CODESYS используются R_TRIG и F_TRIG.

👇 В следующем посте подробно разберём, как они работают и где применяются.

#CODESYS #ПЛК #StructuredText #R_TRIG #F_TRIG
⚡ R_TRIG и F_TRIG в CODESYS: как поймать момент изменения сигнала?

В программах ПЛК постоянно приходится работать с дискретными сигналами:

• кнопка нажата
• двигатель работает
• датчик сработал
• авария появилась
• команда исчезла

Но очень важно различать:

состояние сигнала

и

момент изменения сигнала.

Именно для второго случая в CODESYS используются функциональные блоки R_TRIG и F_TRIG.

━━━━━━━━━━━━━━━━━━

🔹 Состояние и событие — не одно и то же

Допустим:

xButton = TRUE


Если написать:

IF xButton THEN
iCounter := iCounter + 1;
END_IF


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

Например, если цикл программы составляет 10 мс, а кнопку держат одну секунду, код может выполниться около 100 раз.

Но иногда нам нужно выполнить действие только один раз:

именно в момент нажатия.

Для этого необходимо определить переход:

FALSE → TRUE


Это называется передним фронтом.

━━━━━━━━━━━━━━━━━━

⬆️ R_TRIG — передний фронт

R_TRIG отслеживает переход:

FALSE → TRUE


Объявим функциональный блок:

VAR
xButton : BOOL;
fbRise : R_TRIG;
END_VAR


Вызываем его каждый цикл:

fbRise(CLK := xButton);


Когда xButton изменится:

FALSE → TRUE


выход:

fbRise.Q


станет TRUE только на один цикл программы.

После этого, даже если xButton продолжает оставаться TRUE:

fbRise.Q = FALSE


до следующего нового фронта.

━━━━━━━━━━━━━━━━━━

🧠 Пример

Пусть сигнал выглядит так:

цикл 1 → FALSE
цикл 2 → FALSE
цикл 3 → TRUE
цикл 4 → TRUE
цикл 5 → TRUE


Выход R_TRIG:

цикл 1 → FALSE
цикл 2 → FALSE
цикл 3 → TRUE
цикл 4 → FALSE
цикл 5 → FALSE


То есть импульс появляется только в момент изменения сигнала.

━━━━━━━━━━━━━━━━━━

✅ Практический пример с кнопкой

Нужно увеличивать счётчик один раз при каждом нажатии:

VAR
xButton : BOOL;
fbButton : R_TRIG;
iCounter : INT;
END_VAR

fbButton(CLK := xButton);

IF fbButton.Q THEN
iCounter := iCounter + 1;
END_IF


Теперь:

🔘 нажали → +1

⏳ держим → ничего

🔘 отпустили → ничего

🔘 нажали снова → ещё +1

━━━━━━━━━━━━━━━━━━

⬇️ А что делает F_TRIG?

F_TRIG работает наоборот.

Он определяет переход:

TRUE → FALSE


То есть задний фронт сигнала.

Объявление:

VAR
xSignal : BOOL;
fbFall : F_TRIG;
END_VAR


Вызов:

fbFall(CLK := xSignal);


Когда сигнал изменится:

TRUE → FALSE


получим:

fbFall.Q = TRUE


на один цикл ПЛК.

━━━━━━━━━━━━━━━━━━

🔄 R_TRIG и F_TRIG рядом

Для одного сигнала можно использовать оба блока:

fbRise(CLK := xSignal);
fbFall(CLK := xSignal);


Получаем:

FALSE → TRUE
↑
R_TRIG.Q

TRUE → FALSE
↓
F_TRIG.Q


Таким образом можно отдельно обработать появление и исчезновение одного и того же сигнала.

━━━━━━━━━━━━━━━━━━

🏭 Где применяется R_TRIG?

Передний фронт очень часто нужен для:

• обработки нажатия кнопки
• запуска последовательности
• подсчёта событий
• регистрации появления аварии
• формирования однократной команды
• переключения режима
• увеличения или уменьшения значения
• запуска операции с HMI

Например:

IF fbStart.Q THEN
eState := STATE_STARTING;
END_IF


Переход выполняется один раз — именно при появлении команды.

━━━━━━━━━━━━━━━━━━

🏭 Где применяется F_TRIG?

Задний фронт полезен, когда действие должно происходить при исчезновении сигнала.

Например:

• оператор отпустил кнопку
• механизм остановился
• датчик перестал быть активным
• команда была снята
• аварийное условие исчезло

Пример:

fbFall(CLK := xMotorRun);

IF fbFall.Q THEN
iStopCounter := iStopCounter + 1;
END_IF


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

TRUE → FALSE


━━━━━━━━━━━━━━━━━━

⚠️ Важный момент
R_TRIG и F_TRIG должны помнить состояние входа на предыдущем вызове.

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

Например:

fbRise(CLK := xSignal);


на каждом выполнении задачи.

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

━━━━━━━━━━━━━━━━━━

⚠️ Ещё одна частая ошибка

Не нужно использовать один экземпляр R_TRIG для нескольких независимых сигналов.

Плохо:

fbTrig(CLK := xStart);
...
fbTrig(CLK := xReset);


У блока есть внутреннее состояние.

Для разных сигналов лучше создавать разные экземпляры:

fbStart : R_TRIG;
fbReset : R_TRIG;


и вызывать их отдельно:

fbStart(CLK := xStart);
fbReset(CLK := xReset);


Так программа будет понятнее и предсказуемее.

━━━━━━━━━━━━━━━━━━

💡 Главное различие

Обычный:

IF xSignal THEN


отвечает на вопрос:

«Сигнал сейчас TRUE?»

R_TRIG отвечает:

«Сигнал только что изменился с FALSE на TRUE?»

А F_TRIG:

«Сигнал только что изменился с TRUE на FALSE?»

━━━━━━━━━━━━━━━━━━

📌 Запомните

⬆️ R_TRIG

FALSE → TRUE


Передний фронт — сигнал появился.

⬇️ F_TRIG

TRUE → FALSE


Задний фронт — сигнал исчез.

Выход Q активируется только на один цикл программы при обнаружении соответствующего перехода.

━━━━━━━━━━━━━━━━━━

❓ Проверим себя

Сигнал изменяется так:

FALSE
FALSE
TRUE
TRUE
FALSE
FALSE
TRUE


Сколько раз за это время сработает R_TRIG, а сколько — F_TRIG?

💬 Напишите ответ в комментариях, не подглядывая в документацию 👇

#CODESYS #ПЛК #АСУТП #StructuredText #ST #R_TRIG #F_TRIG #ПрограммированиеПЛК