西门子 PID之 FB41

西门子 PID之 FB41,第1张

剑指工控微信技术群,很多人都在问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

你的是PID控制,当MAN_ON为0时为自动控制,当SP大于PV时,控制器通过积分作用将输出最大值100。所以不管你的SP是100还是80,由于PV为0,所以输出为100。当MAN_ON为1 时为手动控制,LMN输出为MAN的值。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12199892.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-21
下一篇 2023-05-21

发表评论

登录后才能评论

评论列表(0条)

保存