ParamManagerScripts/backend/script_groups/TwinCat/.example/FB41_PIDCONTROLLER.EXP

138 lines
2.9 KiB
Plaintext

(* @PATH := '\/Functions_Collection' *)
(* @SYMFILEFLAGS := '4096' *)
FUNCTION_BLOCK FB41_PIDController
VAR_INPUT
in_SP : REAL; (* SP *)
in_PV : REAL; (* PV *)
MAN : REAL;
GAIN : REAL;
TI : REAL;
TD : REAL;
DEADB_W : REAL ;
LMN_HLM : REAL;
LMN_LLM : REAL;
LMN_FAC : REAL;
LMN_OFF : REAL;
CYCLE : REAL ;
I_ITLVAL : REAL;
DISV : REAL;
MAN_ON : BOOL;
I_SEL : BOOL;
P_SEL : BOOL;
D_SEL : BOOL;
INT_HOLD : BOOL;
I_ITL_ON : BOOL;
END_VAR
VAR_OUTPUT
LMN : REAL;
LMN_P : REAL;
LMN_I : REAL;
LMN_D : REAL;
High_Limit : BOOL;
Low_Limit : BOOL;
END_VAR
VAR
mIntegral : Integral ; (* FB Integral Instance *)
mIntegralOut : REAL; (* Integral Value *)
mOld_error : REAL ;
Error : REAL ;
mProportional : REAL ;
mDerivative : REAL ;
Gain_error : REAL; (*Error Value * Gain*)
Total_result : REAL; (*Total result of PID Block*)
INT_Block : BOOL;
LMN_alarm : BOOL ; (*Limit output alarm *)
mAuxONS : R_TRIG ;
mManEn : BOOL ;
mManONS : F_TRIG ;
END_VAR
(* @END_DECLARATION := '0' *)
(* SP - PV *)
Error := in_SP - in_PV ;
(* Multiply GAIN *)
IF ABS(Error) >= DEADB_W THEN (* Dead Band Implementation *)
Gain_error := Error * GAIN ;
ELSE
Gain_error := 0.0 ;
END_IF
(* Freeze Integral Calculation *)
INT_Block := INT_HOLD OR MAN_ON OR LMN_alarm ;
(* Integral calculation *)
IF I_SEL AND TI>0 THEN
IF I_ITL_ON THEN
mIntegralOut := I_ITLVAL;
ELSE
IF NOT INT_Block THEN
IF (( Gain_error>=0 ) AND NOT High_Limit) OR (( Gain_error<=0 ) AND NOT Low_Limit) THEN
(*mIntegral := mIntegral + Gain_error * CYCLE / TI;*)
mIntegral.i_NewValue := Gain_error / TI ;
mIntegral.i_IntCycle := CYCLE ;
mIntegral(Out_Integral:=mIntegralOut) ;
END_IF
END_IF
END_IF
ELSE
mIntegralOut := 0.0 ;
END_IF
LMN_I := mIntegralOut ;
(* Derivative calculation *)
IF ( D_SEL AND TD >0 ) THEN
mDerivative := ( Gain_error - mOld_error ) * TD / 10 ;
ELSE
mDerivative := 0.0 ;
END_IF
mOld_error := Gain_error ;
LMN_D := mDerivative ;
(* Proportional contribute *)
IF P_SEL THEN
mProportional := Gain_error ;
ELSE
mProportional := 0 ;
END_IF
LMN_P := mProportional ;
(* Total result P + I + D + DISV *)
Total_result := mProportional + mIntegralOut + mDerivative + DISV ;
mManONS(CLK:=MAN_ON) ;
(* Manual control *)
IF MAN_ON THEN
Total_result := MAN ;
IF NOT I_ITL_ON AND mManONS.Q THEN
mIntegralOut := LMN - LMN_P - DISV ; (* - Bumpless - Inizilize the Integral Component when the PID is setted in auto again *)
mIntegral(Out_Integral:=mIntegralOut) ;
mDerivative := 0.0 ;
END_IF
END_IF
(* High Low limit for total result *)
High_Limit := FALSE ;
Low_Limit := FALSE ;
IF Total_result > LMN_HLM THEN
High_Limit := TRUE ;
Total_result := LMN_HLM;
END_IF
IF Total_result < LMN_LLM THEN
Low_Limit := TRUE ;
Total_result := LMN_LLM;
END_IF
LMN := ( Total_result * LMN_FAC ) + LMN_OFF;
END_FUNCTION_BLOCK