Код:
(* Интерфейс трехточечного управления исполнительным механизмом
без датчика положения.*)
(*ПКК Ладья, 2015 г. www.pkk-ladya.ru*)
FUNCTION_BLOCK Valve_Interface_No_Pos
VAR_INPUT
IN_VAL: REAL; (*К выходу регулятора*)
Y_MIN: REAL :=-100; (*Нижний предел выходного сигнала регулятора *)
Y_MAX: REAL :=100; (*Верхний предел выходного сигнала регулятора *)
LIMIT_Y: BOOL :=0; (*Постоянное открытие при IN_VAL >= Y_MAX или закрытие при IN_VAL <= Y_MIN*)
RUN: BOOL; (*Включение*)
FULL_MOTION_TIME :REAL :=45; (*Время хода ИМ, сек *)
MIN_WORK:REAL :=0.5; (*Минимальное время импульса*)
REVERS_TIME :REAL :=1; (*Время реверса ИМ, сек*)
LUFT_TIME: REAL :=0; (*Время люфта в соединениях ИМ, сек *)
END_VAR
VAR_OUTPUT
MORE:BOOL; (*Выход БОЛЬШЕ*)
LESS: BOOL; (*Выход МЕНЬШЕ*)
END_VAR
VAR
L_skaly: REAL;
TOF_1: TOF;
TOF_2: TOF;
Y1: REAL;
X: BOOL;
dY: REAL;
T_imp: REAL;
Pusk: BOOL;
Rass: REAL;
Znak: BOOL;
TP_1: TP;
Q_TP_1: BOOL;
TP_2: TP;
Q_TP_2: BOOL;
PT_1: REAL;
T_PWM : REAL;
Y_old : REAL;
Rev: BOOL;
TP_Rev: TP;
RS_1: RS;
UP_Old: BOOL;
END_VAR
(*Расчетная формула Тимп = dY/(Ymax-Ymin)* время полного хода ИМ *)
TOF_1(IN:=NOT X AND RUN, PT:=REAL_TO_TIME(1000*MIN_WORK), Q=>X , ET=>); //Цикл измерения
IF X=0 THEN dY:=IN_VAL-Y_old; Y_old:=IN_VAL; END_IF; //Определение изменения вых сигнала за мин время импульса
L_skaly:=Y_MAX-Y_MIN; //Диапазон сигнала регулятора
IF L_skaly=0 THEN L_skaly:=200; END_IF; //Защита от деления на ноль при неподсоединении входов или отсутствии значений
Rass:=MIN_WORK*dY/L_skaly; //Рассогласование
IF ABS(T_Imp) >= MIN_WORK AND NOT Pusk THEN //Как только величина накопленного импульса превышает мин время импульса и импульс при этом не выдается на выход
T_PWM:=T_Imp; //время управления выходом становится равным длит накопл импульса
T_Imp:= 0; //Время накопленного импульса сбрасывается
ELSE T_imp := T_Imp + Rass; //иначе накопленный импульс накапливается дальше
END_IF;
Znak S= T_PWM>0 AND Up_old OR T_PWM<0 AND NOT Up_old; //Любое изменение направления знака импульса вызывает "взвод" переменной Znak
IF Znak THEN PT_1:= ABS(T_PWM) + LUFT_TIME; ELSE PT_1:= ABS(T_PWM); END_IF; //При изменении направления к времени мпульса добавляется время люфта,
TP_Rev (IN:= Znak AND NOT Pusk , PT:=REAL_TO_TIME(1000*REVERS_TIME), Q=>Rev , ET=>); // а также задержка пуска на время реверса
TOF_2(IN:= (ABS(T_PWM)>0 AND NOT Pusk AND NOT Rev), PT:=REAL_TO_TIME(1000*PT_1) , Q=> Pusk, ET=>); //Запуск импульса
IF NOT Pusk AND NOT Rev THEN T_PWM:=0; Znak R=TRUE; END_IF; //По его окончании сброс времени управления выходом и переменной Znak
IF RUN THEN //Если включено...
IF IN_VAL<=Y_MIN AND LIMIT_Y AND NOT LESS THEN MORE:=1;
ELSIF IN_VAL>=Y_MAX AND LIMIT_Y AND NOT MORE THEN LESS:=1; //Если регулятор уперся в ограничение, то соотв. выход открывается постоянно.
ELSE
IF Pusk AND T_PWM<0 AND NOT LESS THEN MORE:=Pusk; //Если пер UP вверх, не открыто вниз и сигнал Пуск, то запускается открытие
ELSIF Pusk AND T_PWM>0 AND NOT MORE THEN LESS:=Pusk; //Аналогично закрытие
ELSE LESS:=0; MORE:=0; //Иначе отключается
END_IF;
END_IF;
RS_1(SET:= MORE, RESET1:=LESS , Q1=> UP_Old); //Триггер запоминает знак предыдущего импульса
ELSE T_Imp:=0; T_PWM:=0; Pusk:=0; MORE:=0; LESS :=0; PT_1 :=0; Znak:=FALSE; //Если выкючено - то все обнуляется
END_IF;