(* @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