Сообщение от
Мурат Ахриев
Библиотека Util распространяется компанией 3S в компилированном виде, соответственно внутренняя структура функциональных блоков скрыта.
А почему у меня - в открытом?
Код:
(* PD controller *)
FUNCTION_BLOCK PID
VAR_INPUT
ACTUAL :REAL; (* actual value, process variable *)
SET_POINT:REAL; (* desired value, set point *)
KP:REAL; (* proportionality const. (P)*)
TN:REAL; (* reset time (I) in sec *)
TV:REAL; (* rate time, derivative time (D) in sec*)
Y_MANUAL:REAL; (* Y is set to this value as long as MANUAL=TRUE *)
Y_OFFSET:REAL; (* offset for manipulated variable *)
Y_MIN:REAL; (* minimum value for manipulated variable *)
Y_MAX:REAL; (* maximum value for manipulated variable *)
MANUAL:BOOL; (* TRUE: manual: Y is not influenced by controller,
FALSE: controller determines Y *)
RESET:BOOL; (* reset: set Y output to Y_OFFSET and reset integral part *)
END_VAR
VAR_OUTPUT
Y:REAL; (* manipulated variable, set value*)
LIMITS_ACTIVE:BOOL:=FALSE; (* true set value would exceed limits Y_MIN, Y_MAX *)
OVERFLOW:BOOL:=FALSE; (* overflow in integral part *)
END_VAR
VAR
CLOCK:TON;
I: INTEGRAL;
D: DERIVATIVE;
TMDIFF: DWORD;
ERROR: REAL;
INIT: BOOL:=TRUE;
Y_ADDOFFSET: REAL;
KPcopy:REAL;
TNcopy:REAL;
TVcopy:REAL;
END_VAR
IF TN>0 AND KP<> 0 AND (NOT OVERFLOW OR RESET OR MANUAL) THEN
ERROR := SET_POINT-ACTUAL; (* Regeldifferenz *)
IF RESET OR MANUAL OR INIT OR (KP<>KPcopy OR TN<>TNcopy OR TV<>TVcopy) THEN (* Reset oder Handbetrieb *)
I(RESET:=TRUE);
D(RESET:=TRUE);
OVERFLOW:=FALSE;
LIMITS_ACTIVE:=FALSE;
IF RESET OR INIT THEN
Y := Y_OFFSET;
INIT:=FALSE;
Y_ADDOFFSET := 0;
ELSIF MANUAL THEN
Y := Y_MANUAL;
Y_ADDOFFSET := Y_MANUAL-(Y_OFFSET+KP*(ERROR+I.OUT/TN+D.OUT*TV));
ELSE
Y_ADDOFFSET := Y - Y_OFFSET - KP*ERROR;
END_IF
TMDIFF:=0;
CLOCK(IN:=FALSE); (* Timer neu starten *)
CLOCK(PT:=t#1h, IN:=TRUE);
TNcopy := TN;
TVcopy := TV;
KPcopy := KP;
ELSE
CLOCK; (* Timer abfragen *)
TMDIFF:=TIME_TO_DWORD(CLOCK.ET); (* Zeitdifferenz seit letztem Aufruf *)
END_IF;
IF TMDIFF>0 THEN
CLOCK(IN:=FALSE); (* Timer neu starten *)
CLOCK(PT:=t#1h, IN:=TRUE);
D(IN:=ERROR, TM:=TMDIFF, RESET:=FALSE); (* Differential abschätzen *)
I(IN:=ERROR, TM:=TMDIFF, RESET:=FALSE); (* Integral abschätzen *)
OVERFLOW := I.OVERFLOW;
IF NOT OVERFLOW THEN
Y:=Y_OFFSET+KP*(ERROR+I.OUT/TN+D.OUT*TV) + Y_ADDOFFSET;
IF Y>1E30 OR Y<-1E30 THEN (* Overflow steht bevor, darf aber eigentlich nicht passieren *)
OVERFLOW:=TRUE;
END_IF;
LIMITS_ACTIVE:=FALSE;
IF Y_MAX>Y_MIN AND Y>Y_MAX THEN (* Stellwert-Obergrenze überschritten *)
LIMITS_ACTIVE:=TRUE;
IF KP<>0 THEN
I(IN:=(Y_MAX-Y)*TN/KP,TM:=1000,RESET:=FALSE); (* Integral korrigieren *)
END_IF
Y:=Y_MAX;
END_IF;
IF Y_MAX>Y_MIN AND Y<Y_MIN THEN (* Stellwert-Untergrenze unterschritten *)
LIMITS_ACTIVE:=TRUE;
IF KP<>0 THEN
I(IN:=(Y_MIN-Y)*TN/KP,TM:=1000,RESET:=FALSE); (* Integral korrigieren *)
END_IF
Y:=Y_MIN;
END_IF;
END_IF;
ELSE
CLOCK(PT:=t#1h,IN:=TRUE);
END_IF;
END_IF;