FUNCTION FC1 : VOID
VAR_INPUT
Run:BOOL //True-运行,False-停止
Auto:BOOL //True-自动,False-手动
ISW:BOOL //True-积分有效,False-积分无效
DSW:BOOL //True-微分有效,False-微分无效
SetMV:REAL //手动时的开度设定值
SVSW:REAL //当设定值低于SVSW时,开度为零
PV:REAL //测量值
SV:REAL //设定值
DeadBand:REAL //死区大小
PBW:REAL //比例带大小
IW:REAL //积分带大小
DW:REAL //微分带大小
dErr_IN:REAL //误差累积
LastPV_IN:REAL //上一控制周期的测量值
END_VAR
VAR_OUTPUT
MV:REAL //输出开度
dErr_OUT:REAL //误差累积
LastPV_OUT:REAL//上一控制周期的测量值
END_VAR
VAR
Err:REAL //误差
dErr:REAL //误差累积
PBH:REAL //比例带上限
PBL:REAL //比例带下限
PVC:REAL //测量值在一个控制周期内的变化率,即测量值变化速率
P:REAL //比例项
I:REAL //积分项
D:REAL //微分项
END_VAR
IF Run=1 THEN
IF Auto=1 THEN
IF SV>=SVSW THEN
Err:=SV-PV
PBH:=SV+PBW
PBL:=SV-PW
IF PV<PBL THEN
MV:=1
ELSIF PV>PBH THEN
MV:=0
ELSE
P=(PBH-PV)/(PBH-PBL) //计算比例项
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////以下为积分项的计算//////////////////////////////////////////////////////////////
IF ISW=1 THEN
dErr:=dErr_IN
IF (PV<(SV-DeadBand)) OR (PV>(SV+DeadBand)) THEN
IF (dErr+Err)<(0-IW) THEN
dErr:=0-IW
ELSIF (dErr+Err)>IW THEN
dErr:=IW
ELSE
dErr:=dErr+Err
END_IF
END_IF
I:=dErr/IW
dErr_OUT:=dErr
ELSE
I:=0
END_IF
/////////////////////////////////////////////以上为积分项的计算//////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////以下为微分项的计算//////////////////////////////////////////////////////////////
IF DSW=1 THEN
PVC:=LastPV_IN-PV
D:=PVC/DW
LastPV_OUT:=PV
ELSE
D:=0
END_IF
/////////////////////////////////////////////以上为微分项的计算//////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
IF (P+I+D)>1 THEN
MV:=1
ELSIF (P+I+D)<0 THEN
MV:=0
ELSE
MV:=P+I+D
END_IF
END_IF
ELSE
MV:=0
END_IF
ELSE
MV:=SetMV
END_IF
ELSE
MV:=0
END_IF
END_FUNCTION
剑指工控微信技术群,很多人都在问PID的复杂的微积分算法如何形成程序的?我在这里把STEP7 里FB41源代码和注释给大家贴出来,让大家学习一下,FB41是积分PID。另外如果大家习惯了STEP7的PID也可以通过这个源代码移植到别的控制器上。FUNCTION_BLOCK "CONT_C"
TITLE ='continuous PID controller'
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
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)