剑指工控微信技术群,很多人都在问PID的复杂的微积分算法如何形成程序的?我在这里把STEP7里FB41源代码和注释给大家贴出来,让大家学习一下,FB41是积分PID。另外如果大家习惯了STEP7的PID也可以通过这个源代码移植到别的控制器上。
FUNCTION_BLOCK"CONT_C"
TITLE='continuousPIDcontroller'
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:=T1620S;//积分复位时间
TD:TIME:=T2S;//微分作用时间延时
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;//干扰变量
_VARVAR_OUTPUT
LMN:REAL:=0.0;//调节值
LMN_PER:WORD:=W0;//外设调节值
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;//误差信号
_VARVAR
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;//备用-本程序没有使用该变量
_VARVAR_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;//RealHilfsvariable
_VARIFCOM_RSTTHEN//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:=W0;
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;//外设输入转换为浮点数值
IFNOTPVPER_ONTHEN//过程变量选择
Istwert:=PV_IN;
_IF;PV:=Istwert;
ErKp:=SP_INT-PV;//计算偏差
IFErKp-DEADB_WTHEN
ER:=ErKp+DEADB_W;
ELSIFErKpDEADB_WTHEN
ER:=ErKp-DEADB_W;
ELSE
ER:=0.0;
_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;
IFrTirCycle*0.5THEN//积分时间必须=采样时间的0.5倍
rTi:=rCycle*0.5;
_IF;IFrTdrCycleTHEN//微分时间必须=采样时间
rTd:=rCycle;
_IF;IFrTmLagrCycle*0.5THEN//微分作用延时时间必须=采样时间的0.5倍
rTmLag:=rCycle*0.5;
_IF;IFP_SELTHEN//比例作用投入
Panteil:=ErKp;
ELSE
Panteil:=0.0;
_IF;IFI_SELTHEN//积分作用投入
IFI_ITL_ONTHEN//积分初始化
Ianteil:=I_ITLVAL;
sRestInt:=0.0;
ELSIFMAN_ONTHEN//手动值输入时的积分量计算,用于用于手动切换自动无扰切换
Ianteil:=sLmn-Panteil-DISV;
sRestInt:=0.0;
ELSE//积分计算
Iant:=(rCycle/rTi)*(ErKp+sInvAlt)*0.5+sRestInt;
IF(()ORINT_HOLD)OR()THEN//抗积分饱和
Iant:=0.0;
_IF;Ianteil:=sIanteilAlt+Iant;//当前积分值:=上时刻积分值+本次积分量
sRestInt:=sIanteilAlt-Ianteil+Iant;
_IF;ELSE
Ianteil:=0.0;
sRestInt:=0.0;
_IF;Diff:=ErKp;
IFNOTMAN_ONANDD_SELTHEN//微分作用投入
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;
_IF;dLmn:=Panteil+Ianteil+Danteil+DISV;//PID输出
IFMAN_ONTHEN//PID手动之打开
dLmn:=MAN;
ELSE
IFNOTI_ITL_ONANDI_SELTHEN//干扰量处理
IFIanteilLMN_HLM-DISVANDdLmnLMN_HLMANDdLmn-LMN_DLMN_HLMTHEN
rVal:=LMN_HLM-DISV;
gf:=dLmn-LMN_HLM;
rVal:=Ianteil-rVal;
IFrValgfTHEN
rVal:=gf;
_IF;Ianteil:=Ianteil-rVal;
ELSIFIanteilLMN_LLM-DISVANDdLmnLMN_LLMANDdLmn-LMN_DLMN_LLMTHEN
rVal:=LMN_LLM-DISV;
gf:=dLmn-LMN_LLM;
rVal:=Ianteil-rVal;
IFrValgfTHEN
rVal:=gf;
_IF;Ianteil:=Ianteil-rVal;
_IF;_IF;_IF;LMN_P:=Panteil;
LMN_I:=Ianteil;
LMN_D:=Danteil;
sInvAlt:=Erkp;
sIanteilAlt:=Ianteil;
sbArwHLmOn:=FALSE;
sbArwLLmOn:=FALSE;
IFdlmn=LMN_HLMTHEN//调节辆限幅(上限)
QLMN_HLM:=TRUE;
QLMN_LLM:=FALSE;
dlmn:=LMN_HLM;
sbArwHLmOn:=TRUE;
ELSE
QLMN_HLM:=FALSE;
IFdLmn=LMN_LLMTHEN//调节辆限幅(下限)
QLMN_LLM:=TRUE;
dlmn:=LMN_LLM;
sbArwLLmOn:=TRUE;
ELSE
QLMN_LLM:=FALSE;
_IF;_IF;sLmn:=dLmn;
dLmn:=dLmn*LMN_FAC+LMN_OFF;
LMN:=dLmn;
dLmn:=dLmn*276.48;
IFdLmn=32512.0THEN
dLmn:=32512.0;
ELSIFdLmn=-32512.0THEN
dLmn:=-32512.0;
_IF;LMN_PER:=INT_TO_WORD(DINT_TO_INT(REAL_TO_DINT(dLmn)));
_IF;_FUNCTION_BLOCK





