📘 Часть 2/3. Почему R_TRIG может выдавать ложные импульсы?
В первой части мы выяснили, что повторные вызовы одного экземпляра ФБ используют общую внутреннюю память.
Теперь рассмотрим ошибку, которую бывает непросто обнаружить при отладке.
━━━━━━━━━━━━━━━━━━
🧠 Один R_TRIG для двух сигналов
Объявим:
VAR
fbTrig : R_TRIG;
xA : BOOL;
xB : BOOL;
END_VAR
И вызовем один экземпляр для двух сигналов:
fbTrig(CLK := xA);
fbTrig(CLK := xB);
На первый взгляд кажется, что мы просто проверяем два сигнала.
Но
R_TRIG хранит предыдущее состояние входа CLK.Поэтому второй вызов использует память, которая уже изменилась после первого.
━━━━━━━━━━━━━━━━━━
🔍 Что произойдёт?
Пусть:
xA = TRUE
xB = FALSE
Перед первым вызовом внутренняя память триггера содержит
FALSE.Первый вызов:
fbTrig(CLK := xA);
Обнаруживается переход:
FALSE → TRUE
Поэтому:
fbTrig.Q = TRUE
Но затем выполняется второй вызов:
fbTrig(CLK := xB);
Теперь вход равен
FALSE.После этого:
fbTrig.Q = FALSE
Если проверить выход после обоих вызовов:
IF fbTrig.Q THEN
// Обработка события
END_IF;
условие не выполнится.
Импульс, сформированный первым вызовом, уже исчез!
━━━━━━━━━━━━━━━━━━
⚠️ А теперь самое интересное
Предположим, сигналы не меняются:
xA = TRUE
xB = FALSE
В каждом цикле выполняются два вызова.
1️⃣ Первый получает TRUE после предыдущего FALSE и формирует импульс.
2️⃣ Второй получает FALSE и обновляет внутреннюю память.
На следующем цикле ситуация повторяется.
В результате
R_TRIG формирует импульс при каждом первом вызове, хотя xA всё время остаётся TRUE.Это серьёзная логическая ошибка!
━━━━━━━━━━━━━━━━━━
📌 Вывод
Один экземпляр
R_TRIG нельзя использовать как два независимых триггера.Каждый вызов изменяет его внутреннее состояние.
➡️ В следующей части: как правильно обрабатывать независимые сигналы и какие правила стоит соблюдать при работе с ФБ.
#CODESYS #ПЛК #StructuredText #R_TRIG