TGViewer
Channel Public Channel
Codesys 3.5 Обучение программированию.

Codesys 3.5 Обучение программированию.

@codesys4

Subscribers
267
Photos
38
Videos
13
Links
63
Recent Posts 20 shown
Post #162 466
При следующем выполнении этого CASE значение eState будет прочитано снова, и тогда будет выбрана ветка:

WORKING:


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

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

✅ Почему ENUM лучше набора чисел?

Можно было бы написать:

iState := 0;
iState := 10;
iState := 20;
iState := 30;


Но что означает:

iState = 20?

Без дополнительного описания — непонятно.

А:

eState = WORKING


читается сразу.

Именно поэтому для состояний удобно использовать ENUM.

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

🔧 Диагностика тоже становится проще

Если механизм остановился и оператор сообщает:

«Почему он не продолжает работу?»

в онлайн-режиме можно посмотреть:

eState = STARTING


После этого понятно:

алгоритм ждёт условия перехода из STARTING.

В нашем случае первым делом стоит проверить:

xSensor

Это значительно удобнее, чем искать комбинацию из нескольких:

xStep1, xStep2, xStep3...

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

🏗 Где такой подход особенно полезен?

ENUM + CASE хорошо подходит для:

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

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

⚠️ Но CASE — не замена каждому IF

Не нужно превращать вообще всю программу в одну гигантскую машину состояний.

Если необходимо просто проверить условие:

IF rTemperature > 90.0 THEN
xHighTemp := TRUE;
END_IF;


обычный IF прекрасно подходит.

CASE особенно полезен тогда, когда есть:

состояния → условия перехода → следующее состояние.

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

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

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

«Выполняется ли условие?»

А связка:

ENUM + CASE


помогает описать:

«В каком состоянии находится алгоритм и куда он должен перейти дальше?»

Для небольшого кода разница может быть незаметна.

Но в большом промышленном проекте понятная структура программы сильно упрощает:

• разработку
• ПНР
• диагностику
• сопровождение
• последующую доработку

Хороший код должен быть понятен не только ПЛК, но и инженеру, который откроет проект через год.

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

💬 А как вы строите пошаговые алгоритмы?

Используете CASE, отдельные BOOL для каждого шага или свой шаблон машины состояний?

📤 Если статья оказалась полезной — отправьте её другу или коллеге, который работает с CODESYS и ПЛК.

🔁 Можно также репостнуть материал в профильный чат или канал — так о наших технических разборах узнает больше инженеров.

#CODESYS #ПЛК #АСУТП #StructuredText #ST #CASE #ENUM #ПрограммированиеПЛК
  • 👍 5
Post #161 389
🔀 CASE в CODESYS: как строить понятные пошаговые алгоритмы

По мере роста программы ПЛК часто появляется что-то похожее:

IF xStart AND NOT xStep1 THEN
...
END_IF;

IF xStep1 AND xSensor THEN
...
END_IF;

IF xStep2 AND fbTimer.Q THEN
...
END_IF;


Сначала всё выглядит нормально.

Но потом появляются:

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

И через некоторое время становится трудно ответить на простой вопрос:

«На каком этапе сейчас находится алгоритм?»

Для последовательных процессов часто удобнее использовать CASE и явно хранить текущее состояние.

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

🏭 Пример задачи

Пусть после команды «Пуск» механизм должен:

1️⃣ включить двигатель

2️⃣ дождаться срабатывания датчика

3️⃣ работать ещё 5 секунд

4️⃣ остановиться

У процесса можно выделить четыре состояния:

IDLE
STARTING
WORKING
STOPPING


Создадим перечисление:

TYPE E_State :
(
IDLE,
STARTING,
WORKING,
STOPPING
);
END_TYPE


И переменную текущего состояния:

VAR
eState : E_State := IDLE;
END_VAR


Теперь вместо нескольких BOOL-переменных вида:

xStep1
xStep2
xStep3
xStep4


мы имеем одну:

eState

которая однозначно показывает текущий этап.

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

⏱ Сначала подготовим таймер

Пусть в состоянии WORKING механизм должен работать 5 секунд.

Объявим:

VAR
eState : E_State := IDLE;
fbWorkTimer : TON;

xStart : BOOL;
xSensor : BOOL;
xMotor : BOOL;
END_VAR


Таймер удобно вызывать циклически:

fbWorkTimer(
IN := eState = WORKING,
PT := T#5s
);


Когда состояние становится WORKING, таймер начинает отсчёт.

При выходе из этого состояния:

IN = FALSE


и TON сбрасывается.

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

🔧 Теперь сам CASE

CASE eState OF

IDLE:
xMotor := FALSE;

IF xStart THEN
eState := STARTING;
END_IF;


STARTING:
xMotor := TRUE;

IF xSensor THEN
eState := WORKING;
END_IF;


WORKING:
xMotor := TRUE;

IF fbWorkTimer.Q THEN
eState := STOPPING;
END_IF;


STOPPING:
xMotor := FALSE;
eState := IDLE;

END_CASE


Теперь структура алгоритма читается почти как описание технологического процесса.

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

🔎 Разберём по шагам

1. IDLE

Механизм находится в ожидании:

xMotor := FALSE;


При появлении команды:

xStart = TRUE


выполняется:

eState := STARTING;


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

2. STARTING

Включаем двигатель:

xMotor := TRUE;


И ждём подтверждающий сигнал от датчика:

IF xSensor THEN
eState := WORKING;
END_IF;


Пока датчик не сработал, алгоритм остаётся в STARTING.

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

3. WORKING

Двигатель продолжает работать:

xMotor := TRUE;


А таймер:

fbWorkTimer.Q


станет TRUE после пяти секунд пребывания в состоянии WORKING.

После этого:

eState := STOPPING;


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

4. STOPPING

Останавливаем двигатель:

xMotor := FALSE;


и возвращаем автомат в исходное состояние:

eState := IDLE;


Цикл завершён.

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

🧠 Что здесь даёт CASE?

Представим:

eState = STARTING


Тогда выполняется только логика ветки:

STARTING:


Код IDLE, WORKING и STOPPING в этом выполнении CASE не выполняется.

Поэтому состояния процесса хорошо отделены друг от друга.

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

⚠️ Важная особенность переходов

Допустим, внутри STARTING выполняется:

eState := WORKING;


Это не означает, что ветка WORKING немедленно начнёт выполняться ниже в том же CASE.

Текущая ветка уже была выбрана.
Post #160 264
🔀 CASE в CODESYS: когда алгоритм начинает тонуть в IF

Небольшой проект легко написать на нескольких IF.

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

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

ENUM + CASE

Например:

IDLE → STARTING → WORKING → STOPPING → IDLE


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

👇 В следующем посте — подробный пример на Structured Text.

📤 Если тема актуальна — перешлите пост коллеге, который программирует ПЛК.

#CODESYS #ПЛК #StructuredText #CASE #ПрограммированиеПЛК
Post #150 290
📘 Новая книга по CODESYS 3.5

Подготовил практическую книгу по программированию ПЛК в CODESYS.

Внутри — понятные объяснения, примеры на Structured Text и разборы типовых задач.

📎 Книгу прикрепляю к этому посту.

Если материал окажется полезным — поделитесь постом с друзьями и коллегами, которым интересны ПЛК, CODESYS и промышленная автоматизация.

🔁 Репосты очень помогают развивать канал и делать больше полезных материалов.

#CODESYS #ПЛК #АСУТП #StructuredText #ПрограммированиеПЛК
  • 👍 1
  • 🤝 1
Post #149 258
✅ РАЗБОР ЗАДАЧИ: R_TRIG и F_TRIG

Исходный сигнал:

Цикл:    1      2      3      4      5      6      7
Signal: FALSE FALSE TRUE TRUE FALSE FALSE TRUE


❓ Сколько раз сработают R_TRIG и F_TRIG?

А) R_TRIG — 1, F_TRIG — 1
Б) R_TRIG — 2, F_TRIG — 1
В) R_TRIG — 2, F_TRIG — 2
Г) R_TRIG — 3, F_TRIG — 2

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

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

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

R_TRIG сработает 2 раза.
F_TRIG сработает 1 раз.

Разберём по шагам.

⬆️ Между циклами 2 и 3:

FALSE → TRUE

Это передний фронт.

Значит:

R_TRIG.Q = TRUE

только на один цикл.

На следующем цикле сигнал всё ещё TRUE, но нового фронта уже нет.

⬇️ Между циклами 4 и 5:

TRUE → FALSE

Это задний фронт.

Значит:

F_TRIG.Q = TRUE

только на один цикл.

⬆️ Между циклами 6 и 7 снова происходит:

FALSE → TRUE

Поэтому R_TRIG срабатывает второй раз.

Итого:

R_TRIG — 2 срабатывания
F_TRIG — 1 срабатывание


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

R_TRIG реагирует только на:

FALSE → TRUE

F_TRIG — только на:

TRUE → FALSE

Само длительное состояние TRUE или FALSE новых импульсов не создаёт.

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

#CODESYS #ПЛК #R_TRIG #F_TRIG #StructuredText #ПрограммированиеПЛК
Post #148 213
🧠 РАЗБОР КОДА: R_TRIG и F_TRIG

Посмотрите на изменение сигнала по циклам ПЛК:

Цикл:    1      2      3      4      5      6      7
Signal: FALSE FALSE TRUE TRUE FALSE FALSE TRUE


Для этого сигнала работают два блока:

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


где:

⬆️ fbRise — R_TRIG
⬇️ fbFall — F_TRIG

❓ Сколько раз за эти 7 циклов сработают R_TRIG и F_TRIG?

А) R_TRIG — 1, F_TRIG — 1
Б) R_TRIG — 2, F_TRIG — 1
В) R_TRIG — 2, F_TRIG — 2
Г) R_TRIG — 3, F_TRIG — 2

Выберите вариант до того, как посмотрите разбор 👇

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

#CODESYS #ПЛК #R_TRIG #F_TRIG #StructuredText
Post #147 191
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 #ПрограммированиеПЛК
Post #146 159
⚡ 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


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

⚠️ Важный момент
Post #145 154
⚡ R_TRIG и F_TRIG в CODESYS

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

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

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

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

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

#CODESYS #ПЛК #StructuredText #R_TRIG #F_TRIG
  • 🤝 1
Post #144 208
🧠 РАЗБОР КОДА: 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 #ПрограммированиеПЛК
  • 👍 4
Post #143 214
🧠 РАЗБОР КОДА: TON

Сигнал xSignal был:

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


Таймер:

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


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

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

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

#CODESYS #ПЛК #TON #StructuredText
Post #142 234
Гораздо понятнее и надёжнее вызывать экземпляр таймера каждый цикл:

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 #ПрограммированиеПЛК #Автоматизация
Post #141 205
⏱ 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, функциональный блок вообще не вызывается.

Его входы и внутреннее состояние в этом цикле не обновляются обычным способом.
Post #140 229
⏱ TON в CODESYS

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

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

👇 Подробный разбор — в следующем посте.
Post #139 234
🧠 РАЗБОР КОДА

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

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 #ПрограммированиеПЛК
Post #138 232
🧠 РАЗБОР КОДА

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

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

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

iCounter = 0

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

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

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

#CODESYS #ПЛК #StructuredText #ПрограммированиеПЛК
Post #137
Channel photo updated
Post #136 254
​⚡ Почему 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 #ПрограммированиеПЛК
  • 👍 5
Post #133 428
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)
Post #132 1.01K
📊 Обработка аналоговых сигналов ПЛК в CODESYS 3.5
Датчик подключён. Но как превратить его сигнал в понятные значения температуры, давления или уровня? Как задать уставки и обработать ошибки?
В этом курсе разбираем сигналы 0–10 В и 4–20 мА, преобразование исходных значений в инженерные единицы, масштабирование, пороги и уставки, сигнализацию, ручной режим и визуализацию.
Практическая часть — разработка функционального блока в CODESYS 3.5 на языке ST.
От сигнала датчика — к его обработке и использованию в программе.
👉 Программа курса и запись: https://codesys3-5.skillspace.ru/l/obrabotka-analogovyh-signalov-plk-0b9b92⁠�
💡 Только начинаете? Начните с основ CODESYS. Уже знакомы со средой и хотите разобраться в работе с датчиками — переходите к курсу по аналоговым сигналам.
Older posts →

About this channel

How can I read @codesys4 without a Telegram account?
TGViewer shows the public web preview Telegram publishes for Codesys 3.5 Обучение программированию.: recent posts, photos, videos and the subscriber count, with no app, login or account.
How many subscribers does Codesys 3.5 Обучение программированию. have?
Codesys 3.5 Обучение программированию. (@codesys4) has 267 subscribers on Telegram, refreshed roughly every 30 minutes.
Does Codesys 3.5 Обучение программированию. know I viewed it here?
No. Public channel previews carry no viewer identity, and TGViewer has no accounts or tracking of what you look up.
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →