工控智汇

工控智汇

西门子FB41

admin 183 129

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

_VAR

VAR_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;//误差信号

_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;//备用-本程序没有使用该变量

_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;//RealHilfsvariable

_VAR

IFCOM_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