FB41的SCL源码

  • 格式:docx
  • 大小:41.40 KB
  • 文档页数:16

最近在论坛看到好多网友寻找西门子PLC FB41的SCL源码,现在就将我从网上搜集(因原始出处好像不能访问了,时间久了我也忘记了,)的源码贴出来,此源程序来源于网络,不保证编译后与原版一致,仅供参考。

源码我粗略看了一遍,好象是不完全微分PID,但由于使用的是位置式PID,所以里面还做了手自动的无扰动切换,但个人感觉无扰动切换还是增量PID好,无需做任何处理就直接支持。

源码可以通过编译,内容如下:FUNCTION_BLOCK "CONT_C"TITLE ='continuous PID controller'AUTHOR : MTFAMILY : ICONTNAME : CONT_CVERSION : '1.5'KNOW_HOW_PROTECTVAR_INPUTCOM_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_VARVAR_OUTPUTLMN : 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_VARVARsInvAlt : 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_VARVAR_TEMPrCycle : 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 ; //HilfwertrVal : REAL ; //Real HilfsvariableEND_VARIF 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_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 ;ELSErCycle := 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 THENER := ErKp + DEADB_W ;ELSIF ErKp > DEADB_W THENER := ErKp - DEADB_W ;ELSEER := 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 ;ELSEEND_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 ; //感觉sRestInt一直等于0.0 ;不知为何,通过运行发现不为0.0,可能是浮点数计算误差END_IF;ELSEIanteil := 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 ;ELSEIF NOT I_ITL_ON AND I_SEL THEN //干扰量处理IF Ianteil > LMN_HLM - DISV AND dLmn > LMN_HLM AND dLmn - LMN_D > LMN_HLM THENrVal := LMN_HLM - DISV ;gf := dLmn - LMN_HLM ;rVal := Ianteil - rVal ;IF rVal > gf THENrVal := gf ;END_IF;Ianteil := Ianteil - rVal ;ELSIF Ianteil < LMN_LLM - DISV AND dLmn < LMN_LLM AND dLmn - LMN_D < LMN_LLM THENrVal := LMN_LLM - DISV ;gf := dLmn - LMN_LLM ;rVal := Ianteil - rVal ;IF rVal < gf THENrVal := 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 ;ELSEQLMN_HLM := FALSE ;IF dLmn <= LMN_LLM THEN //调节辆限幅(下限)QLMN_LLM := TRUE ;dlmn := LMN_LLM ;sbArwLLmOn := TRUE ;ELSEQLMN_LLM := FALSE ;END_IF;END_IF;sLmn := dLmn ;dLmn := dLmn * LMN_FAC + LMN_OFF ;LMN := dLmn ;dLmn := dLmn* 276.48 ;IF dLmn >= 32512.0 THENdLmn := 32512.0 ;ELSIF dLmn <= -32512.0 THENdLmn := -32512.0 ;END_IF;LMN_PER := INT_TO_WORD( DINT_TO_INT( REAL_TO_DINT( dLmn) ) ) ;END_IF;END_FUNCTION_BLOCKyanyanpid块FB41 SCL 源代码查看日志列表发表于01月26日15:08FUNCTION_BLOCK "CONT_C"TITLE ='continuous PID controller'AUTHOR : MTFAMILY : ICONTNAME : CONT_CVERSION : '1.5'KNOW_HOW_PROTECTVAR_INPUTCOM_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_VARVAR_OUTPUTLMN : 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_VARVARsInvAlt : 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_VARVAR_TEMPrCycle : 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 ; //HilfwertrVal : REAL ; //Real HilfsvariableEND_VARIF 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 ;ELSErCycle := 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 THENER := ErKp + DEADB_W ;ELSIF ErKp > DEADB_W THENER := ErKp - DEADB_W ;ELSEER := 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 ;ELSEPanteil := 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 ; //感觉sRestInt一直等于0.0 ;不知为何,通过运行发现不为0.0,可能是浮点数计算误差END_IF;ELSEIanteil := 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 ;ELSEIF NOT I_ITL_ON AND I_SEL THEN //干扰量处理IF Ianteil > LMN_HLM - DISV AND dLmn > LMN_HLM AND dLmn - LM N_D > LMN_HLM THENrVal := LMN_HLM - DISV ;gf := dLmn - LMN_HLM ;rVal := Ianteil - rVal ;IF rVal > gf THENrVal := gf ;END_IF;Ianteil := Ianteil - rVal ;ELSIF Ianteil < LMN_LLM - DISV AND dLmn < LMN_LLM AND dLmn - LMN_D < LMN_LLM THENrVal := LMN_LLM - DISV ;gf := dLmn - LMN_LLM ;rVal := Ianteil - rVal ;IF rVal < gf THENrVal := 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 ;ELSEQLMN_HLM := FALSE ;IF dLmn <= LMN_LLM THEN //调节辆限幅(下限)QLMN_LLM := TRUE ;dlmn := LMN_LLM ;sbArwLLmOn := TRUE ;ELSEQLMN_LLM := FALSE ;END_IF;END_IF;sLmn := dLmn ;dLmn := dLmn * LMN_FAC + LMN_OFF ;LMN := dLmn ;dLmn := dLmn* 276.48 ;IF dLmn >= 32512.0 THENdLmn := 32512.0 ;ELSIF dLmn <= -32512.0 THENdLmn := -32512.0 ;END_IF;LMN_PER := INT_TO_WORD( DINT_TO_INT( REAL_TO_DINT( dLmn) ) ) ;END_IF;END_FUNCTION_BLOCK查看日志列表分享转载。