/****************************************************************************** FILE: FUZZY.C POPURSE: WRITER: DATE: 2007.03.08 ******************************************************************************/ #include "STM32Lib\\stm32f10x.h" #include "main.h" #include "fuzzy.h" //#include //#include "temperature_table.h" #include "MENU.h" StableTempTab tabTmp; //#define DOOROPENSPEED -15L //开门时的升温速度,如果低于此温度,认为电阻丝的热量完全散发出来或者开门升温 long DOOROPENSPEED = -15L; #define MAXNEGINTERG (-200L*KI/Ki) //extern const u16 k_table[]; #define Kp 15 //输出变量u比例因子 #define Ki 1/10 //衰减系数; #define KI 15 //Kp 变小的时候 ki要变大 extern AI_CONTROL Ai_CTRL; extern MFL_PARA MFL_PARA_A; extern u8 FLASH_DATA_TEMP[528]; void TaskFuzzy(void) { char cnt; if(Ai_CTRL.cur_Temp>MAX_TEMP) //超温保护 { Ai_CTRL.temp_out=PWM_PITCED; Ai_CTRL.PreviewOut=0; return ; } //求偏差 for(cnt=ERRORCNT-1;cnt>0;cnt--) { Ai_CTRL.Error[cnt] = Ai_CTRL.Error[cnt-1]; } //保存上次偏差值 Ai_CTRL.Error[0] = (long)((Ai_CTRL.gDest-Ai_CTRL.cur_Temp)); for(cnt=DERRORCNT-1;cnt>0;cnt--) { Ai_CTRL.dErr[cnt] = Ai_CTRL.dErr[cnt-1]; } //保存上次偏差率值 Ai_CTRL.dErr[0] = Ai_CTRL.Error[0]-Ai_CTRL.Error[1]; //计算偏差变化率 Ai_CTRL.ECSUM = Ai_CTRL.dErr[0] + Ai_CTRL.dErr[1] + Ai_CTRL.dErr[2] + Ai_CTRL.dErr[3] + Ai_CTRL.dErr[4]; //10s的温升速率 =iol if(Ai_CTRL.Error[0]DOOROPENSPEED)&&(Ai_CTRL.CTEMP>INTEGRALSWITCH)&&(Ai_CTRL.ECSUM<0)&&(Ai_CTRL.LowSpeedCnt++>2)) //连续运行60S温升速度慢,误差大,减少控制范围 { //升温速度 很慢 低于 1.6/10s //升温速度慢超过2s*60次 //温度误差大于最后一次的起控范围 //不是敞开炉门 //ECSUM >0开门 if(Ai_CTRL.gDest>2500) //250度 { Ai_CTRL.CTEMP/=2; DOOROPENSPEED = -10L; } else //目标温度过低,过快改变起控点容易超调 { Ai_CTRL.CTEMP-=20; //起控点减少2度 DOOROPENSPEED = -5L; } Ai_CTRL.LowSpeedCnt = 0; if(Ai_CTRL.CTEMP0) || ((Ai_CTRL.Error[0]==0) &&( Ai_CTRL.dErr[0]!=0))) //误差变大的情况 { Ai_CTRL.SumErrLimit +=Ai_CTRL.Error[0]; //误差变大的时候,求积分 if(Ai_CTRL.SumErrLimit20)&&(Ai_CTRL.Error[0]PWM_PERIOD) Ai_CTRL.du=PWM_PERIOD; Ai_CTRL.temp_out=(unsigned int)Ai_CTRL.du; //积分值在输出稳定的情况下保存 if((Ai_CTRL.PreviewOut==Ai_CTRL.du)&&(Ai_CTRL.du!=0xFF)&&((Ai_CTRL.du!=0))) { //如果半分钟 输出都很稳定,可以 认为很稳定了 //将数据读出比较, 比较稳定次数,如果此次稳定次数 大于上次的稳定次数,给予保存 //printf("Ai_CTRL.iStableCnt = %d ,Ai_CTRL.iPreStabCnt =%d \n",Ai_CTRL.iStableCnt,Ai_CTRL.iPreStabCnt); if((Ai_CTRL.iStableCnt++>Ai_CTRL.iPreStabCnt)&&(Ai_CTRL.iStableCnt<0x7FF)) { //StableTempTab tabTmp; tabTmp.iStableCnt = Ai_CTRL.iStableCnt; tabTmp.iDestTemp = Ai_CTRL.iDestTemp/100*100;// tabTmp.integral = Ai_CTRL.SumErrLimit; SaveStable(&tabTmp); Ai_CTRL.iPreStabCnt = Ai_CTRL.iStableCnt+5; } }else { Ai_CTRL.iStableCnt = 0; } Ai_CTRL.PreviewOut=Ai_CTRL.du; } //functions prototype /************************************************************************ 仿人智能控制器//Humanoid Intelligent Controller ************************************************************************/ /******************************************************************* 模糊控制数据变量 ********************************************************************/ void InitFuzzy(void) { Ai_CTRL.DoorOpenValue = 0 ;// 重新统计升温速度 Ai_CTRL.LowSpeedCnt=0; Ai_CTRL.du=0; } /********************************************************************* 启动高温炉 **********************************************************************/ void CtrlStove(u8 cOpen, long lDefTemp, u8 cRate) { StableTempTab psTmpTab; u8 temp; //停止 InitFuzzy(); //Ai_CTRL.HFDownTemp=HUIFA_900_QIKONG*10; if(cOpen) //启动 { Ai_CTRL.gDest = lDefTemp*10; //将 目标 温度值 转换 为 LoadStable(lDefTemp,&psTmpTab); //这里是否需要乘以10 ? if((psTmpTab.iDestTemp/100)==(lDefTemp/100)) //已经保存过积分表 { Ai_CTRL.SumErrLimit = psTmpTab.integral; //加载保存的积分数据 Ai_CTRL.iPreStabCnt = psTmpTab.iStableCnt; Ai_CTRL.iDestTemp = lDefTemp; } else //未保存. { Ai_CTRL.SumErrLimit = -(1010-lDefTemp)/10*KI*2; //扣掉(1010-lDefTemp)/10的脉宽 ; Ai_CTRL.iPreStabCnt = 10; Ai_CTRL.iDestTemp = lDefTemp; } // Ai_CTRL.iStableCnt = 0; Ai_CTRL.CTEMP = (1010-lDefTemp) ; //XC20121108 调节控温范围 temp = readHFDownTemp(); if((temp==0)||(temp==0xFF)) //设置初始值 { //Ai_CTRL.HFDownTemp = 1000; //Ai_CTRL.HFDownTemp = 600; //Ai_CTRL.HFDownTemp=HUIFA_900_QIKONG*10; Ai_CTRL.HFDownTemp = 1000; saveHFDownTemp (Ai_CTRL.HFDownTemp/10); } else Ai_CTRL.HFDownTemp=(long)temp*10; //Ai_CTRL.HFDownTemp = ByteRead(EEOROM_HFTEMP_ADDR)*10; /*FlashPageRead (HFDownTemp_BASE,FLASH_DATA_TEMP); //读取Ai_CTRL.HFDownTemp,原始函数都是字节!!! Ai_CTRL.HFDownTemp=FLASH_DATA_TEMP[0]; if((Ai_CTRL.HFDownTemp==0)||(Ai_CTRL.HFDownTemp==0xFF)) //设置初始值 { Ai_CTRL.HFDownTemp = 1000; //ByteWrite(EEOROM_HFTEMP_ADDR,Ai_CTRL.HFDownTemp/10); FLASH_DATA_TEMP[0]=Ai_CTRL.HFDownTemp; FlashPageWrite (HFDownTemp_BASE,FLASH_DATA_TEMP); }*/ //控温范围 } else { Ai_CTRL.gDest = 0; Ai_CTRL.temp_out=0; } } void SaveStable(StableTempTab *psTmpTab) { u16 n,temp; u8 eeprom_data_temp[32]; //M24C64为32个字节一个page temp=psTmpTab->iDestTemp/100; if (temp>199) temp=199; temp+=TEMP_TABLE_BASE; temp<<=5; n=0; eeprom_data_temp[n++]=psTmpTab->iStableCnt>>8; eeprom_data_temp[n++]=psTmpTab->iStableCnt; eeprom_data_temp[n++]=psTmpTab->iDestTemp>>8; eeprom_data_temp[n++]=psTmpTab->iDestTemp; eeprom_data_temp[n++]=psTmpTab->integral>>24; eeprom_data_temp[n++]=psTmpTab->integral>>16; eeprom_data_temp[n++]=psTmpTab->integral>>8; eeprom_data_temp[n++]=psTmpTab->integral; eeprom_data_temp[31]=DATA_SET_FLAG; eeprom_24c64_write (temp,32,eeprom_data_temp); } void LoadStable(u16 iTemp,StableTempTab *psTmpTab) { u16 n,temp; u8 eeprom_data_temp[32]; //M24C64为32个字节一个page temp=iTemp/100; if (temp>199) temp=199; temp+=TEMP_TABLE_BASE; temp<<=5; eeprom_24c64_read (temp,32,eeprom_data_temp); n=0; psTmpTab->iStableCnt=eeprom_data_temp[n++]; psTmpTab->iStableCnt<<=8; psTmpTab->iStableCnt+=eeprom_data_temp[n++]; psTmpTab->iDestTemp=eeprom_data_temp[n++]; psTmpTab->iDestTemp<<=8; psTmpTab->iDestTemp+=eeprom_data_temp[n++]; psTmpTab->integral=eeprom_data_temp[n++]; psTmpTab->integral<<=8; psTmpTab->integral+=eeprom_data_temp[n++]; psTmpTab->integral<<=8; psTmpTab->integral+=eeprom_data_temp[n++]; psTmpTab->integral<<=8; psTmpTab->integral+=eeprom_data_temp[n++]; } // u8 readHFDownTemp (void) { u16 n; u8 eeprom_data_temp[32]; //M24C64为32个字节一个page //n=HFDownTemp_BASE; //n<<=5; n=HUIFA_TEMP_DROP_ADD; eeprom_24c64_read (n,2,eeprom_data_temp); if (eeprom_data_temp[0]==0) return eeprom_data_temp[1]; else return 100; } // void saveHFDownTemp (u8 temp) { u16 n; u8 eeprom_data_temp[32]; //M24C64为32个字节一个page /*eeprom_data_temp[0]=temp; eeprom_data_temp[31]=DATA_SET_FLAG; n=HFDownTemp_BASE; n<<=5; eeprom_24c64_write (n,32,eeprom_data_temp);*/ eeprom_data_temp[0]=0; eeprom_data_temp[1]=temp; n=HUIFA_TEMP_DROP_ADD; n<<=5; eeprom_24c64_write (n,2,eeprom_data_temp); }