搜索

PID仿人控制孰优孰劣? [有代码]

[复制链接]
1585|0
 楼主 | 2009-11-19 13:00 | 显示全部楼层
/******************************************************************************

FILE:       FUZZY.C

POPURSE:

WRITER:     Xukaiming

DATE:       2007.03.08

******************************************************************************/


#include "main.h"

#include "task.h"

#include "fuzzy.h"

#include "ied_ctrl.h"

#include "math.h"

#include "x5043.h"

#include "manctrl.h"





#define ERRORCNT  9                        //误差记录

#define DERRORCNT 10                //误差变化率记录

//#define DOOROPENSPEED  -15L        //开门时的升温速度,如果低于此温度,认为电阻丝的热量完全散发出来或者开门升温

xdata long DOOROPENSPEED =  - 15L;

#define MAXNEGINTERG   (-200L*KI/Ki)

extern code unsigned int K_Temp_Tab[];

typedef struct AI_CONTROL

{

  long gDest; //目标温度的AD值

  long CTEMP; //开始控制温度



  long Error[ERRORCNT]; //偏差

  long dErr[DERRORCNT]; //偏差变化率       

  long ECSUM; //10S内的偏差变化率之和               

  long SumErrLimit; //加热初值                       



  long PreviewOut;

  long du;

  long DoorOpenValue; //保存炉子门状态         

  char LowSpeedCnt;

  unsigned int iDestTemp; //目标温度值

};



#define Kp                15                           //输出变量u比例因子

#define Ki                1/10                                 //衰减系数;               

#define KI                15



//Kp 变小的时候 ki要变大       

xdata struct AI_CONTROL Ai_CTRL;

void TaskFuzzy(void)

{

  char cnt;

  _nop_();



  if (IED.lADTemp > MAX_TEMP)

  //超温保护

  {

    SetPWM(PWM_PITCED);

    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 - IED.lADTemp) / KC));

  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;



  #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

  SetPWM((unsigned char)Ai_CTRL.du);

  //保存上次输出

  Ai_CTRL.PreviewOut = Ai_CTRL.du;



}



//functions prototype

/************************************************************************

仿人智能控制器//Humanoid Intelligent Controller

************************************************************************/



/*******************************************************************

模糊控制数据变量

********************************************************************/

void InitFuzzy(void)

{

  Ai_CTRL.DoorOpenValue = 0; //  重新统计升温速度       

  Ai_CTRL.LowSpeedCnt = 0;

  SetPWM(PWM_PITCED);

}



/*********************************************************************

启动高温炉

**********************************************************************/

void CtrlStove(UCHAR cOpen, long lDefTemp, UCHAR cRate)

{

  xdata StableTempTab psTmpTab;

  //停止                               

  SuspendTask(TASK_FUZZY);

  InitFuzzy();

  if (cOpen)

  //启动

  {

    Ai_CTRL.gDest = (((double)(0xFFFFFFUL << 2)) / 5000000UL)

      *K_Temp_Tab[lDefTemp] + 20; //将 目标 温度值 转换 为 AD值

    Ai_CTRL.CTEMP = (1010L - lDefTemp); //控温范围

    ActiveTask(TASK_FUZZY, PWM_SCAN);

  }

}



/**********************************************************************

设置PWM,PWM0控制高温炉

16MHz时,T=2*512/16=64uS,F=42.666KHz,计数周期=256,占空比=0%--99.61%

***********************************************************************/

sbit POUT = P1 ^ 3;

char gcPoutTimer =  - 1;



void StopPOut()

{

  POUT = 1;

}







void SetPWM(UCHAR cPeriod)

{

  /*

  CMOD  = 0x00;                                         // Setup PCA timer

  // Configure PCA0 Counter operating mode

  CCAP0L=CCAP0H=cPeriod;                        // Set duty for TCM0

  CCON  =0x40;                       

  CCAPM0=0x42;                                        // Set TCM0 operationg mode                        

   */

  long period;

  StopTimer(&gcPoutTimer);

  POUT = 1;

  period = PWM_SCAN * cPeriod / 255 / 10;

  if (period > 0)

  {

    POUT = 0;

    gcPoutTimer = StartTimer(TIMER_MODE_ONCEROUTINE, period, StopPOut, 0);

  }



}

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 我要提问 投诉建议 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

关闭

热门推荐上一条 /5 下一条

在线客服 快速回复 返回顶部 返回列表