//######################################################################### //该块为自适应模糊PID的比例积分微分计算块 //该块分7个模糊语言 //PB 正大 亦可用PL表示 //PM 正中 //PS 正小 //ZO 零 亦可用ZE表示 //NS 负小 //NM 负中 //NB 负大 亦可用NL表示 //该块配合PID块使用,便于不同控制器的移植。 //EBC LW 20180913 //########################################################################## FUNCTION_BLOCK FB1 TITLE = 'Fuzzy_C' // // 用于计算模糊PID的比例积分微分参数... // VERSION: '0.1' AUTHOR: EBC_LW NAME: Fuzzy FAMILY: EBC KNOW_HOW_PROTECT VAR_INPUT PV:REAL;//过程值 SP:REAL;//设定值 Fuzzy_EN:BOOL:=TRUE;//自适应模糊PID使能1:为启用、0:为取消 //Auto_Tuning_STAUS:BOOL;//是否整定状态 1:是、0:否 Kp_MAX:REAL:=5.0;//比例参数输出的上限 Kp_MIN:REAL:=1.0;//比例参数输出的下限 Ki_MAX:REAL:=30.0;//积分参数输出的上限 Ki_MIN:REAL:=5.0;//积分参数输出的下限 Kd_MAX:REAL:=30.0;//微分参数输出的上限 Kd_MIN:REAL:=5.0;//微分参数输出的下限 Deadb_W:REAL:=0.0;//死区 Cycle:TIME:=T#1S;//采样时间与循环中断块一致 Cycle_Parameter:DINT:=1;//采样时间参数,多长时间执行计算(单位:秒) END_VAR VAR_IN_OUT Kp_MAN:REAL:=2.0;//手动设定比例参数初始值(上一周期的值) Ki_MAN:REAL:=20.0;//手动设定积分参数初始值(上一周期的值) Kd_MAN:REAL:=10.0;//手动设定微分参数初始值(上一周期的值) END_VAR VAR_OUTPUT // Output Parameters PV_OUT:REAL;//过程值输出 SP_OUT:REAL;//设定值输出 Kp_OUT:REAL;//比例参数输出 Ki_OUT:REAL;//积分参数输出 Kd_OUT:REAL;//微分参数输出 END_VAR VAR_TEMP // Temporary Variables I:INT;//循环变量1 J:INT;//循环变量2 E_TEMP:REAL;//量化后的偏差 EC_TEMP:REAL;//量化后的偏差变化率 U_Kp_TEMP1:REAL; U_Kp_TEMP2:REAL; U_Ki_TEMP1:REAL; U_Ki_TEMP2:REAL; U_Kd_TEMP1:REAL; U_Kd_TEMP2:REAL; rCycle:REAL;//采样时间浮点值 Cycle_Timer_PN:BOOL;//采样时间上升沿 END_VAR CONST //基本论域 PL:=3.0; PM:=2.0; PS:=1.0; ZE:=0.0; NS:=-1.0; NM:=-2.0; NL:=-3.0; END_CONST VAR E:REAL;//偏差 E_OLD:REAL;//上一次的偏差 E_OLD_OLD:REAL;//上上次的偏差 EC:REAL;//偏差变化率 K_E:REAL;//偏差的量化因子 K_EC:REAL;//偏差变化率的量化因子 K_Kp:REAL;//比例参数的量化因子 K_Ki:REAL;//积分参数的量化因子 K_Kd:REAL;//微分参的量化因子 U_E_INDEX:ARRAY[0..2] OF INT;//偏差模糊子集的下标 U_EC_INDEX:ARRAY[0..2] OF INT;//偏差变化率模糊子集的下标 Cycle_Timer_OLD:BOOL;//采样周期上一次的状态 Cycle_Timer_TEMP:BOOL;//采样周期经过采样周期参数计算后得出的状态 Cycle_Timer_Count:DINT;//采样周期计数 //定义规则表 //比例参数的规则表 FuzzyRuleKp_Table:ARRAY[0..6,0..6] OF REAL:= PL, PL, PM, PM, PS, PS, ZE, PL, PL, PM, PM, PS, ZE, ZE, PM, PM, PM, PS, ZE, NS, NM, PM, PS, PS, ZE, NS, NM, NM, PS, PS, ZE, NS, NS, NM, NM, ZE, ZE, NS, NM, NM, NM, NL, ZE, NS, NS, NM, NM, NL, NL; //积分参数的规则表 FuzzyRuleKi_Table:ARRAY[0..6,0..6] OF REAL:= NL, NL, NL, NM, NM, ZE, ZE, NL, NL, NM, NM, NS, ZE, ZE, NM, NM, NS, NS, ZE, PS, PS, NM, NS, NS, ZE, PS, PS, PM, NS, NS, ZE, PS, PS, PM, PM, ZE, ZE, PS, PM, PM, PL, PL, ZE, ZE, PS, PM, PL, PL, PL; //微分参数的规则表 FuzzyRuleKd_Table:ARRAY[0..6,0..6] OF REAL:= PS, PS, ZE, ZE, ZE, PL, PL, NS, NS, NS, NS, ZE, NS, PM, NL, NL, NM, NS, ZE, PS, PM, NL, NM, NM, NS, ZE, PS, PM, NL, NM, NS, NS, ZE, PS, PS, NM, NS, NS, NS, ZE, PS, PS, PS, ZE, ZE, ZE, ZE, PL, PL; //论域表格背景数据块当中可设置调整 //偏差的论域 E_mf_paras:ARRAY[0..12] OF REAL := -1.2,-1.0,-0.8,-0.6,-0.4,-0.2,0.0,0.2,0.4,0.6,0.8,1.0,1.2; //偏差变化率的论域 EC_mf_paras:ARRAY[0..12] OF REAL := -0.6,-0.5,-0.4,-0.3,-0.2,-0.1,0.0,0.1,0.2,0.3,0.4,0.5,0.6; //比例参数的增量论域 Kp_mf_paras:ARRAY[0..12] OF REAL := -0.6,-0.5,-0.4,-0.3,-0.2,-0.1,0,0.1,0.2,0.3,0.4,0.5,0.6; //积分参数的增量论域 Ki_mf_paras:ARRAY[0..12] OF REAL := -0.12,-0.10,-0.08,-0.06,-0.04,-0.02,0,0.02,0.04,0.06,0.08,0.10,0.12; //微分参数的增量论域 Kd_mf_paras:ARRAY[0..12] OF REAL := -6.0,-5.0,-4.0,-3.0,-2.0,-1.0,0.0,1.0,2.0,3.0,4.0,5.0,6.0; Paras:ARRAY[0..6]OF REAL:= NL,NM,NS,ZE,PS,PM,PL; U_E:ARRAY[0..6]OF REAL;//偏差隶属度值 U_EC:ARRAY[0..6]OF REAL;//偏差变化率隶属度值 U_Kp:ARRAY[0..6]OF REAL;//比例参数隶属度值 U_Ki:ARRAY[0..6]OF REAL;//积分参数隶属度值 U_Kd:ARRAY[0..6]OF REAL;//微分参数隶属度值 END_VAR //---------------------------程序执行周期处理------------------------------------------ //将采样时间转换为浮点数秒 rCycle:=DINT_TO_REAL(TIME_TO_DINT(CYCLE))/1000.0;//采样时间转换为浮点数值 Cycle_Timer_Count:=Cycle_Timer_Count+1;//采样周期计数 IF Cycle_Timer_Count> REAL_TO_DINT(DINT_TO_REAL(Cycle_Parameter)/rCycle) THEN//判断是否到达设定的时间 Cycle_Timer_Count:=0; Cycle_Timer_TEMP:=TRUE; END_IF; //计数产生上升沿信号 Cycle_Timer_PN:=Cycle_Timer_TEMP&(NOT Cycle_Timer_OLD); Cycle_Timer_OLD:=Cycle_Timer_TEMP; IF Cycle_Timer_TEMP THEN //自复位 Cycle_Timer_TEMP:=FALSE; END_IF; //判断是否使能自适应PID参数计算 IF Fuzzy_EN & Cycle_Timer_PN THEN//再使能模糊控制算法时按周期进行计算 //-----------------------------------------计算量化因子------------------------------------------ //计算输入E及EC的量化因子 如 K_E:=E_mf_paras[12]/3; K_EC:=EC_mf_paras[12]/3; //计算输出Kp/Ki/Kd的量化因子 K_Kp:=3/Kp_mf_paras[12]; K_Ki:=3/Ki_mf_paras[12]; K_Kd:=3/Kd_mf_paras[12]; //----------------------------------------计算偏差----------------------------------------------- E:=SP-PV;//计算过程值和设定值之间的偏差(负偏差) IF E>Deadb_W THEN//死区,该死区应该和PID死区相一致 E:=E-Deadb_W; ELSE IF E<-Deadb_W THEN E:=E+Deadb_W; ELSE E:=0.0; END_IF; END_IF; EC:=E-E_OLD;//计算上一次和当次的偏差的变化 E_OLD_OLD:=E_OLD;//将上一次的值存储与上上次 E_OLD:=E;//将当此的偏差进行存储用于下一次的计算 //----------------------------------隶属度数组及规则表下标清零操作---------------------------------- I:=0;//循环变量清零 FOR I:=0 TO 6 BY 1 DO U_E[I]:=0.0;//偏差隶属度值清零 U_EC[I]:=0.0;//偏差变化率隶属度值清零 U_Kp[I]:=0.0;//比例参数隶属度值清零 U_Ki[I]:=0.0;//积分参数隶属度值清零 U_Kd[I]:=0.0;//微分参数隶属度值清零 END_FOR; J:=0;//循环变量清零 FOR J:=0 TO 2 BY 1 DO//实际只使用了两个元素,因为三角隶属在两个隶属度之间只能最多属于两个隶属度都占有,要么完全属于其中的一个隶属 U_E_INDEX[J]:=0;//偏差下标清零 U_EC_INDEX[J]:=0;//偏差变化率下标清零 END_FOR; //---------------------------------------计算输入E/EC的隶属度----------------------------------- //三角隶属度函数-------------------------------------------------------------------- (*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*) (* 三角隶属度函数 |-- 0, X<=A1 | |-- (X-A1)/(A2-A1), A1A3 如图 A(X) 1| /|\ | / | \ | / | \ | / | \ |______________X 0 A1 A2 A3 *) (*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@2*) //----------------------------------判断E/EC是否超出范围并处理------------------------- IF E>E_mf_paras[12] THEN E:=E_mf_paras[12]; END_IF; IF EEC_mf_paras[12] THEN EC:=EC_mf_paras[12]; END_IF; IF EC0.0 THEN //将规则表Y轴方向的地址存入数组 U_E_INDEX[J]:=I; J:=J+1; // U_E_INDEX[J]:=I+1; END_IF; END_FOR; //-----------------------------将EC进行模糊化处理(计算隶属度)--------------------------- I:=0;//循环变量清零 J:=0; FOR I:=0 TO 6 BY 1 DO IF (Paras[I] <= EC_TEMP) & (EC_TEMP<= Paras[I+1]) THEN U_EC[I]:=(Paras[I+1]-EC_TEMP)/(Paras[I+1]-Paras[I]) ; U_EC[I+1]:=(EC_TEMP-Paras[I])/(Paras[I+1]-Paras[I]) ; END_IF; IF U_EC[I]<>0.0 THEN //将规则表X轴方向的地址存入数组 U_EC_INDEX[J]:=I; J:=J+1; // U_EC_INDEX[J]:=I+1; END_IF; END_FOR; //-----------------------------加权平均反模糊化处理-------------------------------------- // ============Kp反模糊化=============== I:=0; U_Kp_TEMP1:=0; U_Kp_TEMP2:=0; FOR I:=0 TO 2 BY 1 DO U_Kp_TEMP1:=U_E[(U_E_INDEX[I])]*U_EC[U_EC_INDEX[I]]*FuzzyRuleKp_Table[U_EC_INDEX[I],U_E_INDEX[I]]+U_Kp_TEMP1; U_Kp_TEMP2:=U_E[U_E_INDEX[I]]*U_EC[U_EC_INDEX[I]]+U_Kp_TEMP2; END_FOR; Kp_OUT:=U_Kp_TEMP1/U_Kp_TEMP2/K_Kp+Kp_MAN; IF Kp_OUT>Kp_MAX THEN Kp_OUT:=Kp_MAX; END_IF; IF Kp_OUTKi_MAX THEN Ki_OUT:=Ki_MAX; END_IF; IF Ki_OUTKd_MAX THEN Kd_OUT:=Kd_MAX; END_IF; IF Kd_OUT