AUTHOR : Jiansiting
FAMILY : JZGK
NAME : CONT_C
VERSION : '2.0'
KNOW_HOW_PROTECT
VAR_INPUT
COM_RST : BOOL := FALSE; //完全重啟動
MAN_ON : BOOL := TRUE; //手動值打開
PVPER_ON : BOOL := FALSE; //外設過程變量打開
P_SEL : BOOL := TRUE; //比例作用打開
I_SEL : BOOL := TRUE; //積分作用打開
INT_HOLD : BOOL := FALSE; //積分作用保持
I_ITL_ON : BOOL := FALSE; //積分作用初始化
D_SEL : BOOL := FALSE; //微分作用打開
CYCLE : TIME := T#1S; //采樣時間
SP_INT : REAL := 0.0; //內部設定值
PV_IN : REAL := 0.0; //過程變量輸入
PV_PER : WORD := W#16#0; //外設過程變量
MAN : REAL := 0.0; //手動值
GAIN : REAL := 2.0; //比例增益
TI : TIME := T#20S; //積分復位時間
TD : TIME := T#10S; //微分時間
TM_LAG : TIME := T#2S; //微分作用時間延時
DEADB_W : REAL := 0.0; //死區帶寬
LMN_HLM : REAL := 100.0; //積分值上限
LMN_LLM : REAL := 0.0; //積分值下限
PV_FAC : REAL := 1.0; //過程變量因子
PV_OFF : REAL := 0.0; //過程變量偏移量
LMN_FAC : REAL := 1.0; //調節值因子
LMN_OFF : REAL := 0.0; //調節值偏移量
I_ITLVAL : REAL := 0.0; //積分作用的初始化值
DISV : REAL := 0.0; //幹擾變量
END_VAR
VAR_OUTPUT
LMN : REAL := 0.0; //調節值
LMN_PER : WORD := W#16#0; //外設調節值
QLMN_HLM : BOOL := FALSE; //達到調節值上限
QLMN_LLM : BOOL := FALSE; //達到調節值下限
LMN_P : REAL := 0.0; //比例分量
LMN_I : REAL := 0.0; //積分分量
LMN_D : REAL := 0.0; //微分分量
PV : REAL := 0.0; //
ER : REAL := 0.0; //誤差信號
END_VAR
VAR
sInvAlt : REAL := 0.0; //上周期比例偏差值
sIanteilAlt : REAL := 0.0; //上周期積分值
sRestInt : REAL := 0.0; //上周期積分偏差量(浮點數計算偏差)
sRestDif : REAL := 0.0; //上周期微分偏差量(浮點數計算偏差)
sRueck : REAL := 0.0; //
sLmn : REAL := 0.0; //上周期調節值
sbArwHLmOn : BOOL := FALSE; //上周期達到調節值上限
sbArwLLmOn : BOOL := FALSE; //上周期達到調節值下限
sbILimOn : BOOL := TRUE; //備用-本程序沒有使用該變量
END_VAR
VAR_TEMP
rCycle : REAL ; //采樣時間浮點值
Iant : REAL ; //積分增量
Diff : REAL ; //積分量
Istwert : REAL ; //過程變量浮點值
ErKp : REAL ; //偏差比例值
rTi : REAL ; //積分時間浮點值
rTd : REAL ; //微分時間浮點值
rTmLag : REAL ; //微分作用時間延時浮點值
Panteil : REAL ; //比例值
Ianteil : REAL ; //積分值
Danteil : REAL ; //微分值
Verstaerk : REAL ; //
RueckDiff : REAL ; //
RueckAlt : REAL ; //上周期積分量
dLmn : REAL ; //調節量
gf : REAL ; //Hilfwert
rVal : REAL ; //Real Hilfsvariable
END_VAR
IF COM_RST THEN //PID初始化
sIanteilAlt := I_ITLVAL ;
LMN := 0.0 ;
QLMN_HLM := FALSE ;
QLMN_LLM := FALSE ;
LMN_P := 0.0 ;
LMN_I := 0.0 ;
LMN_D := 0.0 ;
LMN_PER := W#16#0 ;
PV := 0.0 ;
ER := 0.0 ;
sInvAlt := 0.0 ;
sRestInt := 0.0 ;
SRestDif := 0.0 ;
sRueck := 0.0 ;
sLmn := 0.0 ;
sbArwHLmOn := FALSE ;
sbArwLLmOn := FALSE ;
ELSE
rCycle := DINT_TO_REAL( TIME_TO_DINT( CYCLE ) ) / 1000.0 ; //采樣時間轉換為浮點數值
Istwert := DINT_TO_REAL( INT_TO_DINT( WORD_TO_INT ( PV_PER ) ) ) * 0.003616898 ;
Istwert := Istwert * PV_FAC + PV_OFF ; //外設輸入轉換為浮點數值
IF NOT PVPER_ON THEN //過程變量選擇
Istwert := PV_IN ;
END_IF;
PV := Istwert ;
ErKp := SP_INT - PV ; //計算偏差
IF ErKp < -DEADB_W THEN
ER := ErKp + DEADB_W ;
ELSIF ErKp > DEADB_W THEN
ER := ErKp - DEADB_W ;
ELSE
ER := 0.0 ;
END_IF;
ErKp := ER * GAIN ; //偏差比例增益
rTi := DINT_TO_REAL( TIME_TO_DINT( TI ) ) / 1000.0 ;
rTd := DINT_TO_REAL( TIME_TO_DINT( TD ) ) / 1000.0 ;
rTmLag := DINT_TO_REAL( TIME_TO_DINT( TM_LAG ) ) / 1000.0 ;
IF rTi rCycle * 0.5 THEN //積分時間必須 >= 采樣時間的0.5倍
rTi := rCycle * 0.5 ;
END_IF;
IF rTd rCycle THEN //微分時間必須 >= 采樣時間
rTd := rCycle ;
END_IF;
IF rTmLag rCycle * 0.5 THEN //微分作用延時時間必須 >= 采樣時間的0.5倍
rTmLag := rCycle * 0.5 ;
END_IF;
IF P_SEL THEN //比例作用投入
Panteil := ErKp ;
ELSE
Panteil := 0.0 ;
END_IF;
IF I_SEL THEN //積分作用投入
IF I_ITL_ON THEN //積分初始化
Ianteil := I_ITLVAL ;
sRestInt := 0.0 ;
ELSIF MAN_ON THEN //手動值輸入時的積分量計算,用於用於手動切換自動無擾切換
Ianteil := sLmn - Panteil - DISV ;
sRestInt := 0.0 ;
ELSE //積分計算
Iant := ( rCycle / rTi ) * ( ErKp + sInvAlt ) * 0.5 + sRestInt ;
IF ( ( Iant > 0.0 AND sbArwHLmOn ) OR INT_HOLD ) OR ( Iant < 0.0 AND sbArwLLmOn )THEN //抗積分飽和
Iant := 0.0 ;
END_IF;
Ianteil := sIanteilAlt + Iant ; //當前積分值 := 上時刻積分值 + 本次積分量
sRestInt := sIanteilAlt - Ianteil + Iant ;
END_IF;
ELSE
Ianteil := 0.0 ;
sRestInt := 0.0 ;
END_IF;
Diff := ErKp ;
IF NOT MAN_ON AND D_SEL THEN //微分作用投入
Verstaerk := rTd / ( rCycle * 0.5 + rTmLag ) ;
Danteil := ( Diff - sRueck ) * Verstaerk ;
RueckAlt := sRueck ;
RueckDiff := rCycle / rTd * Danteil + sRestDif ;
sRueck := RueckDiff + RueckAlt ;
sRestDif := RueckAlt - sRueck + RueckDiff ; //同積分壹樣計算微分誤差量
ELSE //
Danteil := 0.0 ;
sRestDif := 0.0 ;
sRueck := Diff ;
END_IF;
dLmn := Panteil + Ianteil + Danteil + DISV ; //PID輸出
IF MAN_ON THEN //PID手動之打開
dLmn := MAN ;
ELSE
IF NOT I_ITL_ON AND I_SEL THEN //幹擾量處理
IF Ianteil > LMN_HLM - DISV AND dLmn > LMN_HLM AND dLmn - LMN_D > LMN_HLM THEN
rVal := LMN_HLM - DISV ;
gf := dLmn - LMN_HLM ;
rVal := Ianteil - rVal ;
IF rVal > gf THEN
rVal := gf ;
END_IF;
Ianteil := Ianteil - rVal ;
ELSIF Ianteil < LMN_LLM - DISV AND dLmn < LMN_LLM AND dLmn - LMN_D < LMN_LLM THEN
rVal := LMN_LLM - DISV ;
gf := dLmn - LMN_LLM ;
rVal := Ianteil - rVal ;
IF rVal < gf THEN
rVal := gf ;
END_IF;
Ianteil := Ianteil - rVal ;
END_IF;
END_IF;
END_IF;
LMN_P := Panteil ;
LMN_I := Ianteil ;
LMN_D := Danteil ;
sInvAlt := Erkp ;
sIanteilAlt := Ianteil ;
sbArwHLmOn := FALSE ;
sbArwLLmOn := FALSE ;
IF dlmn >= LMN_HLM THEN //調節輛限幅(上限)
QLMN_HLM := TRUE ;
QLMN_LLM := FALSE ;
dlmn := LMN_HLM ;
sbArwHLmOn := TRUE ;
ELSE
QLMN_HLM := FALSE ;
IF dLmn = 32512.0 THEN
dLmn := 32512.0 ;
ELSIF dLmn