/****************************************************************************** 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" #include "myprintf.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 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] < Ai_CTRL.CTEMP) { if(((Ai_CTRL.Error[0]*Ai_CTRL.dErr[0]) > 0) || ((Ai_CTRL.Error[0] == 0) && ( Ai_CTRL.dErr[0] != 0))) //误差变大的情况 { Ai_CTRL.SumErrLimit += Ai_CTRL.Error[0]; //误差变大的时候,求积分 if(Ai_CTRL.SumErrLimit < MAXNEGINTERG) //限幅,如果超过负的最大值, 保持为负的最大值 Ai_CTRL.SumErrLimit = MAXNEGINTERG; //////////////////////////////////////////////////////////// Ai_CTRL.du = Ai_CTRL.Error[0] * Kp + Ai_CTRL.SumErrLimit * Ki / KI * Kp; //增益抑制模式 // } else //开环保持模式 { if(((Ai_CTRL.Error[0]*Ai_CTRL.dErr[0]) < 0) || (Ai_CTRL.dErr[0] == 0)) //误差变小的情况 { Ai_CTRL.du = Ai_CTRL.SumErrLimit * Ki / KI * Kp; } else { Ai_CTRL.du = Ai_CTRL.PreviewOut; } } } else Ai_CTRL.du = PWM_PERIOD; //升温 if(Ai_CTRL.du < 0) Ai_CTRL.du = 0; if(Ai_CTRL.du > PWM_PERIOD) Ai_CTRL.du = PWM_PERIOD; Ai_CTRL.PreviewOut = Ai_CTRL.du; Ai_CTRL.temp_out = (unsigned int)Ai_CTRL.du; #ifdef _DEBUG printf("%ld,",Ai_CTRL.CTEMP); printf("%ld,%ld,",Ai_CTRL.Error[0],Ai_CTRL.dErr[0] ); printf("%ld,%ld,%d\n",Ai_CTRL.ECSUM,Ai_CTRL.SumErrLimit,(int)Ai_CTRL.du); #endif //积分值在输出稳定的情况下保存 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; } } //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; //将 目标 温度值 转换 为 Ai_CTRL.lRate = cRate*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 调节控温范围 if(Ai_CTRL.CTEMP < INTEGRALSWITCH) Ai_CTRL.CTEMP = INTEGRALSWITCH; 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; } } 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); }