Сообщение от
des_na_laes@mail.ru
И так. Выяснил, что требуется. Библиотека OSCATbasic. Но она не поддерживается в в codesys 17 p3. Как быть коллеги, подскажите пожалуйста. Требуется pid регулятор с дискретными выходами. Может кто подскажет как заставить стандартный pid из util доработать до дискретного. Есть у кого нибудь такой опыт?
Выход с регулятора PID/UTIL перевожу на вход блока управления клапаном с виртуальным позиционером. Ниже код
Код:
FUNCTION_BLOCK VALVE1
VAR_INPUT
Setpoint:REAL;(*Физическая уставка клапану*)
PV:REAL;
SP:REAL;
END_VAR
VAR_OUTPUT
Q_Open :BOOL;
Q_Close :BOOL;
Position:REAL;
State:INT;
TimeTRUE:TIME:=T#600ms;
TimeFALSE:TIME:=T#600MS;
END_VAR
VAR_IN_OUT
END_VAR
VAR
Delta:REAL;
BLINK:BLINK1;
BLINK1:BLINK;(*Для дожатия*)
TON:TON;(*Для сброса команд*)
U_var_open:REAL;
U_var_close:REAL;
koeff_o:REAL;(*Коэффициент масштабирования позиционера клапана*)
koeff_c:REAL;(*Коэффициент масштабирования позиционера клапана*)
State1:INT;(*Dlya shim*)
STBL:STBL;
INC,DEC,STB:BOOL;
TON1:TON;(*Для сброса команд*)
Count:INT;
R_TRIG:R_TRIG;
LAG:LAG;
SP1:REAL;
LAG1:LAG;
Position1:REAL;
END_VAR
*********
LAG(IN:=SP , k:=0.001, OUT=>SP1 );
Delta := ABS(SP1-PV);
CASE State1 OF
0:
TimeTRUE := T#200MS;
TimeFALSE := T#20S;
IF Delta>=1 THEN State1:=1; END_IF;
1:
TimeTRUE := T#300MS;
TimeFALSE := T#15S;
IF Delta<1 THEN State1:=0; END_IF;
IF Delta>=1.2 THEN State1:=2; END_IF;
2:
TimeTRUE := T#400MS;
TimeFALSE := T#10S;
IF Delta<1.2 THEN State1:=1; END_IF;
IF Delta>=1.4 THEN State1:=3; END_IF;
3:
TimeTRUE := T#500MS;
TimeFALSE := T#8S;
IF Delta<1.4 THEN State1:=2; END_IF;
IF Delta>=1.6 THEN State1:=4; END_IF;
4:
TimeTRUE := T#600MS;
TimeFALSE := T#7S;
IF Delta<1.6 THEN State1:=3; END_IF;
IF Delta>=1.8 THEN State1:=5; END_IF;
5:
TimeTRUE := T#700MS;
TimeFALSE := T#6S;
IF Delta<1.8 THEN State1:=4; END_IF;
IF Delta>=2 THEN State1:=6; END_IF;
6:
TimeTRUE := T#800MS;
TimeFALSE := T#5S;
IF Delta<2 THEN State1:=5; END_IF;
IF Delta>=2.2 THEN State1:=7; END_IF;
7:
TimeTRUE := T#900MS;
TimeFALSE := T#4S;
IF Delta<2.2 THEN State1:=6; END_IF;
IF Delta>=2.4 THEN State1:=8; END_IF;
8:
TimeTRUE := T#1000MS;
TimeFALSE := T#3S;
IF Delta<2.4 THEN State1:=7; END_IF;
IF Delta>=2.7 THEN State1:=9; END_IF;
9:
TimeTRUE := T#1100MS;
TimeFALSE := T#2S;
IF Delta<2.7 THEN State1:=8; END_IF;
IF Delta>=3 THEN State1:=10; END_IF;
10:
TimeTRUE := T#1200MS;
TimeFALSE := T#1s;
IF Delta<3 THEN State1:=9; END_IF;
END_CASE;
BLINK(ENABLE:=(State=2) OR (State=3), TIMELOW:=TimeFALSE , TIMEHIGH:=TimeTRUE );
BLINK1(ENABLE:=(State=4) OR (State=5) , TIMELOW:=T#30s , TIMEHIGH:=T#100ms , OUT=> );
CASE State OF
0:(*Инициализация*)
TON1(IN:=FALSE);
State := 1;
1:(*Ситуация покоя*)
State := State;
Q_Open := FALSE;
Q_Close := FALSE;
Position := Position;
Setpoint := Setpoint;
Delta := Delta;
TON1(IN:=TRUE, PT:=T#5s);
//IF PV>SP1 AND Delta>0.1 AND TON1.Q THEN State:= 3; END_IF;(*Закрывается*)
//IF PV<SP1 AND Delta>0.4 AND TON1.Q THEN State:= 2; END_IF;(*Открывается*)
IF Position>Setpoint AND TON1.Q THEN State:= 3; END_IF;(*Закрывается*)
IF Delta>1 AND PV>SP1 THEN State := 3; END_IF;(*Закрывается*)
IF Position<Setpoint AND TON1.Q THEN State:= 2; END_IF;(*Открывается*)
//IF Position <= 1 AND (SP1<PV) AND Delta>0.5 AND TON1.Q THEN State := 5; END_IF;(*Закрыт*)
//IF Position >= 99 AND (SP1>PV) AND Delta>0.5 AND TON1.Q THEN State := 4; END_IF;(*Открыт*)
2:(*Открывается*)
State := State;
TON1(IN:=FALSE);
Q_Close := FALSE;
Q_Open := BLINK.OUT;
R_TRIG(CLK:=BLINK.OUT);
//IF R_TRIG.Q THEN END_IF;
IF INC THEN Count:=Count+1; END_IF;
IF Position>=Setpoint THEN Count:=0; State := 1; END_IF;(*Ситуация покоя*)
IF PV>=SP1+0.6 THEN Count:=0; State := 1; END_IF;(*Ситуация покоя*)
IF Count>300 THEN Count:=0; State := 1; END_IF;(*Ситуация покоя*)
IF INC AND Delta<=1.3 THEN Count:=0; State := 1; END_IF;
IF Delta<=0.3 AND PV<SP1 THEN Count:=0; State := 1; END_IF;
3:(*Закрывается*)
State := State;
TON1(IN:=FALSE);
Q_Open := FALSE;
Q_Close := BLINK.OUT;
R_TRIG(CLK:=BLINK.OUT);
IF R_TRIG.Q THEN Count:=Count+1; END_IF;
IF Position<=Setpoint THEN Count:=0; State := 1; END_IF;(*Ситуация покоя*)
4:(*Открыт*)
State := State;
TON1(IN:=FALSE);
Position:=100;
Q_Open := BLINK1.OUT;
Q_Close := FALSE;
IF Setpoint<=99.8 OR DEC THEN State := 3; END_IF;(*Закрывается*)
IF Delta<=0.5 THEN State := 1; END_IF;(*Ситуация покоя*)
5:(*Закрыт*)
State := State;
TON1(IN:=FALSE);
Position:=0;
Q_Open := FALSE;
Q_Close := BLINK1.OUT;
IF Setpoint>0.3 AND INC THEN State := 2; END_IF;(*Открывается*)
IF Delta<=0.5 THEN State := 1; END_IF;(*Ситуация покоя*)
END_CASE;
IF Q_Open THEN Position1:=Position1+0.04; END_IF;
IF Q_Close THEN Position1:=Position1-0.04; END_IF;
IF Position > 100 THEN Position:=100; END_IF;
IF Position < 0 THEN Position:=0; END_IF;
IF Position1 > 100 THEN Position1:=100; END_IF;
IF Position1 < 0 THEN Position1:=0; END_IF;
LAG1(IN:=Position1 , k:=0.00005, OUT=>Position );
IF Setpoint > 100 THEN Setpoint:=100; END_IF;
IF Setpoint < 0 THEN Setpoint:=0; END_IF;
//IF DEC AND (PV<SP1+0.3) THEN Q_Close := FALSE; END_IF;
STBL(PV:=PV , INC=>INC , DEC=>DEC , STBL=>STB );
IF PV>SP THEN Q_Open := FALSE; END_IF;
IF PV<SP THEN Q_Close:= FALSE; END_IF;