Тупо (и глупо
) и надежно.
Надёжно? Когда таймер вызывают три раза подряд, эпитет "надёжно" должен быть последним в списке, потому что это явный признак неуверенности и bug driven development. От такого кода жди удар в спину в любой момент.
С таймерами и вообще любыми ФБ в ST всё очень просто: надо не вызывать блок в условиях, а условия передавать блоку. t1(IN := ACTIV AND P16 и т.д.). Вот из одного нашего проекта код:
Код:
RegenTimer(IN := RegenEnabled AND NOT RegenTimer.Q AND NOT RegenFilling AND NOT lvl1);
RegenTrig(clk := RegenEnabled);
RegenFilling := RegenEnabled AND (RegenFilling (*already*) OR NOT (*even*) lvl2 OR RegenTrig.Q OR RegenTimer.Q OR dtt1 >= 30) AND NOT lvl1 (*yet*);
FillEnd(clk := RegenFilling);
IF RegenFilling THEN (* Держать конфигурацию заполнения *)
k5 := TRUE;
k6 := ik5;
npp1 := ik6;
k10 := FALSE;
ELSIF FillEnd.Q THEN (* Отменить конфигурацию заполнения *)
k5 := k6 := npp1 := FALSE;
END_IF
Все таймеры и триггеры вызываются по одному разу, вне IF'ов, а сами IF'ы имеют единственный уровень вложенности. Условия реализованы через AND/OR/NOT. И это _весь_ код, который управляет заполнением испарителя не самой простой установки по множеству условий - периодически, по достижении уровня, по температуре, при активации. Причём код запуска это одновременно и код остановки. А IF'ами оно бы на целую страницу растянулось как минимум.
А тут...
Код:
t1;
...
IF KH_IN AND NOT t1.IN THEN
t1(IN := FALSE);
Зачем t1(IN := FALSE)? Он уже остановлен к этому моменту. Приходите на пересдачу.
Как я понял у меня лишние вызовы "t1;", которые по-хорошему можно все убрать. Я прав?
У вас общий стратегический просчёт. Всё вывернуто наизнанку. Под ПЛК так не пишут.