前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布

FB41

作者头像
剑指工控
发布2021-11-09 14:57:33
5640
发布2021-11-09 14:57:33
举报
文章被收录于专栏:剑指工控

很多人都在问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 <= LMN_LLM THEN //调节辆限幅(下限) QLMN_LLM := TRUE ; dlmn := LMN_LLM ; sbArwLLmOn := TRUE ; ELSE QLMN_LLM := FALSE ; END_IF; END_IF; sLmn := dLmn ; dLmn := dLmn * LMN_FAC + LMN_OFF ; LMN := dLmn ; dLmn := dLmn* 276.48 ; IF dLmn >= 32512.0 THEN dLmn := 32512.0 ; ELSIF dLmn <= -32512.0 THEN dLmn := -32512.0 ; END_IF; LMN_PER := INT_TO_WORD( DINT_TO_INT( REAL_TO_DINT( dLmn) ) ) ; END_IF; END_FUNCTION_BLOCK

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-04-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 剑指工控 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档