/****************************************************************************** FILE: FUZZY.C POPURSE: WRITER: xukaiming DATE: 2009.03.08 ******************************************************************************/ #include "main.h" #include "task.h" #include "fuzzy.h" #include "CTRL.H" #include "adc.h" #include #define TEMP1000mV 9.587f //1000度时为9.587mV #define KC ((int)(TEMP1000mV/10.0f/(VREF*1000.0f/MAX_STOVE_CNT/GAIN_TEMP/0xFFFL))) #define MAX_TEMP (12500L*KC) extern unsigned int S_Temp_Tab[]; /* #define K1 40UL #define KI 60UL #define giKu 40UL */ #define K1 2L //5度偏差满输出 //255/giKu*K1 =温度范围(单位0.1度) #define KI 60L //偏差30次也要满输出 #define giKu 10L #define MAXSUM 200L //Kp 变小的时候 ki要变大 //#define RTT_PRINT #ifdef RTT_PRINT #include "SEGGER_RTT.h" #endif #ifdef RTT_PRINT void initPrintf(void) { SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL); } static char buff[64]; int __print(const char* format,...) { int ret =0; va_list args; va_start(args, format); ret = vsnprintf(buff, sizeof(buff)-1,format, args); SEGGER_RTT_WriteString(0, buff); va_end(args); return ret; } #endif void TaskFuzzy(void) { AI_CONTROL *Ai_CTRL = &IED.Ai_CTRL; if(IED.AdValue.lTemp>MAX_TEMP) //超温保护 { SetPWM(PWM_PITCED); return ; } Ai_CTRL->Error[1] = Ai_CTRL->Error[0]; //保存上次偏差值 disable(); Ai_CTRL->Error[0] = (*Ai_CTRL->gDest-IED.AdValue.lTemp)/KC+5; enable(); //保存上次偏差率值 Ai_CTRL->dErr = Ai_CTRL->Error[0]-Ai_CTRL->Error[1]; //计算偏差变化率 if(Ai_CTRL->Error[0]CTEMP) { //比例阶段 if((Ai_CTRL->Error[0]*Ai_CTRL->dErr>0) //误差变大的情况 || ((Ai_CTRL->Error[0]==0) &&( Ai_CTRL->dErr!=0))) { Ai_CTRL->SumErrLimit+= (Ai_CTRL->Error[0]*giKu ); if(Ai_CTRL->SumErrLimit >MAXSUM*KI*K1) Ai_CTRL->SumErrLimit = MAXSUM* KI*K1; Ai_CTRL->du = giKu*Ai_CTRL->Error[0]/K1; Ai_CTRL->du+= Ai_CTRL->SumErrLimit /KI/K1; //积分 } else { if(((Ai_CTRL->Error[0]*Ai_CTRL->dErr)<0)||(Ai_CTRL->dErr==0)) //误差变小的情况 { Ai_CTRL->du = Ai_CTRL->SumErrLimit/KI/K1; } else { Ai_CTRL->du = Ai_CTRL->PreviewOut; } } } else { Ai_CTRL->du=PWM_PERIOD; //升温 } if(Ai_CTRL->Error[0]CTEMP*3) //离目标3倍启动点内,压制升温速度 { //压制升温速度 if(Ai_CTRL->dErr<(*Ai_CTRL->speed)*PWM_SCAN/1000) ////13.21 { Ai_CTRL->du= 0; } } //归一化 if(Ai_CTRL->du<0) Ai_CTRL->du=0; if(Ai_CTRL->du>=PWM_PERIOD) Ai_CTRL->du=PWM_PERIOD-10; #ifdef RTT_PRINT __print("%ld,",Ai_CTRL->CTEMP); __print("%ld,%ld,",Ai_CTRL->Error[0],Ai_CTRL->dErr); __print("%ld,%ld\n",Ai_CTRL->SumErrLimit,Ai_CTRL->du); #endif SetPWM((unsigned char)Ai_CTRL->du); Ai_CTRL->PreviewOut=Ai_CTRL->du; } /************************************************************************ 仿人智能控制器//Humanoid Intelligent Controller ************************************************************************/ /******************************************************************* 模糊控制数据变量 ********************************************************************/ void InitFuzzy(void) { AI_CONTROL *pAi_CTRL = &IED.Ai_CTRL; memset(pAi_CTRL->Error,0,sizeof(pAi_CTRL->Error)); SetPWM(PWM_PITCED); } /********************************************************************* 启动高温炉 **********************************************************************/ void CtrlStove(UCHAR cOpen, long *lDefADValue,short *speed) { AI_CONTROL *Ai_CTRL = &IED.Ai_CTRL; SuspendTask(TASK_FUZZY); InitFuzzy(); Ai_CTRL->WarmFlag = cOpen; if(cOpen) //启动 { //Ai_CTRL->gDest = lDefADValue+(KC<<2); //将 目标 温度值 转换 为 AD值 Ai_CTRL->gDest = lDefADValue; Ai_CTRL->speed = speed; // Ai_CTRL->CTEMP = 1000; //预控温100度 Ai_CTRL->CTEMP = 500; //预控温50度 Ai_CTRL->SumErrLimit = 0; //Ai_CTRL->SumErrLimit = -(1010-lDefTemp)/10*KI*2; //扣掉(1010-lDefTemp)/10的脉宽 ; Ai_CTRL->SumErrLimit = 0; ActiveTask(TASK_FUZZY, PWM_SCAN); } } /********************************************************************** 设置PWM,PWM0控制高温炉 16MHz时,T=2*512/16=64uS,F=42.666KHz,计数周期=256,占空比=0%--99.61% ***********************************************************************/ signed char gcPoutTimer = -1; void StopPOut(void* p) { POUT = 1; gcPoutTimer = -1; } void SetPWM(UCHAR cPeriod) { long period; if(gcPoutTimer!=-1) StopTimer(&gcPoutTimer); period = PWM_SCAN*cPeriod/255/10; if(period>0) { POUT = 0; if(cPeriod!=0xFF) gcPoutTimer = StartTimer(TIMER_MODE_ONCEROUTINE,period,StopPOut,0); } else POUT = 1; } void SetPWM2(char * cPeriod) { SetPWM(*cPeriod) ; }