⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fuzzy.c

📁 s12温度控制程序,包括模糊控制和LCD程序
💻 C
字号:

#include <hidef.h>      /* common defines and macros */
#include "all_head.h"
#include <mc9s12dg128.h>     /* derivative information */
#pragma LINK_INFO DERIVATIVE "mc9s12dg128b"


extern uchar FreqSetValue;
extern uchar value;
extern int E;
extern int EC;
extern int E1;
extern uchar U[8];
extern int pulse;
extern char channel;
extern int DisplayValue[8];
extern int SampArray[NUM];
extern int SampNum;
extern char NowChannel;
extern int flag;                //看模糊控制输出值时用
extern int fuzzy_value[NUM];    //用于存放模糊控制器输出值
extern int k;                   //看实际输出值时用 ,实际输出值 = 上一次的值 + 当前控制器输出值 - 128
extern int control_value[NUM];  //用于存放实际给固态继电器的输出值

//extern uchar input_mfs[8][4];
uchar current_ins1;   //精确的模糊输入变量1
uchar current_ins2;   //精确的模糊输入变量2

const uchar input_mfs[8][4]={          //输入两变量的隶属函数
//E
 0,    EN2,  0,  13, //no.0 NB
 EN1,  EN3,  4,  10, //no.1 NS
 EN2,  EN4,  6,  6,  //no.2 ZE
 EN3,  EN5,  10, 4,  //no.3 PS
 EN4,  250,  13, 0,  //no.4 PB
//EC
 0,     ECN2, 0,  8,  //no.0 NS
 ECN1,  ECN3, 8,  8,  //no.1 Z
 ECN2,  250,  8,  0,  //no.2 PS
};


/***
 ----------------E------------           
          NB   NS  ZE  PS  PB
     NS   NB   NS  NS  ZE  PB
 EC  ZE   NB   NS  ZE  PS  PB
     PS   NB   ZE  PS  PS  PB   
------------------------------    
      
***/
const uchar rule_start[76]={                //模糊推理规则表
(5*0)+0,(5*1)+0,0xfe,(5*0)+0+8,0xfe, //no.1
(5*0)+0,(5*1)+1,0xfe,(5*0)+0+8,0xfe, //2
(5*0)+0,(5*1)+2,0xfe,(5*0)+0+8,0xfe, //3

(5*0)+1,(5*1)+0,0xfe,(5*0)+1+8,0xfe, //4
(5*0)+1,(5*1)+1,0xfe,(5*0)+1+8,0xfe, //5
(5*0)+1,(5*1)+2,0xfe,(5*0)+2+8,0xfe, //6

(5*0)+2,(5*1)+0,0xfe,(5*0)+1+8,0xfe, //7
(5*0)+2,(5*1)+1,0xfe,(5*0)+2+8,0xfe, //8
(5*0)+2,(5*1)+2,0xfe,(5*0)+3+8,0xfe, //9


(5*0)+3,(5*1)+0,0xfe,(5*0)+2+8,0xfe, //10
(5*0)+3,(5*1)+1,0xfe,(5*0)+3+8,0xfe, //11
(5*0)+3,(5*1)+2,0xfe,(5*0)+3+8,0xfe, //12

(5*0)+4,(5*1)+0,0xfe,(5*0)+4+8,0xfe, //13
(5*0)+4,(5*1)+1,0xfe,(5*0)+4+8,0xfe, //14
(5*0)+4,(5*1)+2,0xfe,(5*0)+4+8,0xfe, //15
0xff};

uchar fuz_ins[8];                          //用于存放两个模糊输入变量
uchar fuz_outs[5];                         //用于存放一个模糊输出变量


uchar output_mfs[5]={32,103,128,154,250};      //输出变量的隶属度函数


/********模糊控制函数*********/
char fuzzy(int e, int ec)     /* e表示偏差,ec表示偏差变化率 */
{
  uchar cog_out=0;  
  int m1,m2;

/* 限幅值,128表示0,取值范围0--255 */
    m1=e+127;
    m2=ec+127;
    if(m1<0)         
    m1=0;
    if(m1>250)
    m1=250;
    if(m2<0)
    m2=0;
    if(m2>250)
    m2=250;   
  current_ins1=m1-1;      
  current_ins2=m2-1;
  

  asm{
      fuzzyify: ldx #input_mfs
                ldy #fuz_ins
                ldaa current_ins1
                ldab #5
     grad_loop: mem
                dbne b,grad_loop
                ldaa current_ins2
                ldab #3
    grad_loop1: mem
                dbne b,grad_loop1
                ldab #5
     rule_eval: clr 1,y+
                dbne b,rule_eval
                ldx #rule_start
                ldy #fuz_ins
                ldaa #0xff
                rev
         defuz: ldy #fuz_outs
                ldx #output_mfs
                ldab #5
                wav
                ediv
                tfr y,d
                stab cog_out   // cog_out 系统输出
    }
return cog_out;
}

/*限幅函数*/
uchar Bounds(uchar data)
{
  if(data<1)   data = 0;
  if(data>250) data = 250;
  return data;

}

/*将int型变量限幅到0-250之间*/
int Boundsint(int data) {
  if(data<1)   data = 0;
  if(data>249) data = 249;
  return data;
}

/*将输入数据缩小10倍*/
int ReduceBound(int data) {         //缩小data的50倍,这个倍数可以根据需要更改, 
   int quotient;                    //主要因为采样时间太长
   int surplus;
   quotient = data/10;              //将data缩小10倍
   surplus  = data%10;              //求data除10后的余数
   if(surplus>=5)  quotient +=1;    //判断余数大小,相似于四舍五入
   return quotient;
 }

/*********主控函数********/ 
void FreqControl(void)                 //输出值在0-250之间
{
  int feedback_value;
  int temp;
  char nowchannel;
  nowchannel = channel;                //保存当前的通道值
  channel++;                         
  if(channel>7) channel = 0;           //限幅值
  pulse = Frequence_sample();          //读取当前通道采样反馈值
  ChannelChoose(channel);              //设定下一次采样为下一通道采样
  feedback_value = ReduceBound(pulse); //限幅0--255
  
  if(SampNum>=NUM)  SampNum = 0;
  SampArray[SampNum++] = feedback_value;         //保存采样数据,以备查看
  
  pulse = 0;                           //清零变量,
  E = FreqSetValue - feedback_value;   //求系统偏差
  EC = E - E1;                         //求系统偏差变化
  value = fuzzy(E,EC);                 //执行模糊控制
  E1 = E;                              //当前偏差赋值给前一偏差,用于下次求偏差变化
  value = Bounds(value);               //限幅
  
  //temp = value - 128;                  //转换结果,因为模糊控制器输出值是在0-255之间,128代表0
  /*
  temp = U + temp;                     //递加
  temp = Boundsint(temp);              //限幅
  U = temp+1;                          //消除编译警告
  //上面三行代码是为实现U =U + value - 128;  
  */
  
  temp = U[nowchannel] + value - 128; //递加,输出实际控制值,因为模糊控制器输出值128代表0,故要减去128	           
 	temp = Boundsint(temp);             //限幅0-249
 	U[nowchannel] = temp + 1;           //将限幅后的值赋给U[nowchannel], +1是为了消除编译警告
 	U[nowchannel] = Bounds(U[nowchannel]);     //限幅0-250,产生控制器输出值
 	
 	PWM_Generate(nowchannel,U[nowchannel]+128);      //产生实际PWM控制量
 	//这里不能直接将U[nowchannel]作为占空比输出,还应有一个转换过程,
 	//因为算得的取值范围与实际产生PWM占空比的取值范围一样都是0-250,同样是128代表0,故在此+128
 	
 	DisplayValue[nowchannel] = feedback_value-1; //保存当前通道的反馈值,-1是为了配合后面消除编译警告

  DisplayPicture(NowChannel);             //实时显示
  
   
  //存放控制器输出值,主要为了调试方便
  if(flag>NUM)  flag = 0;
    fuzzy_value[flag++] = value;    //fuzzy controller output
  if(k>NUM)  k = 0;
    control_value[k++] = U[nowchannel] + 128;         //the actual output pwm
  /* 
  //串口显示当前控制器输出值
  if(flag>7)  flag = 0;                             
  Sci0Write_string("the output of controller_ch");
  Sci0_Sendvalue(flag);
  Sci0Write_string(" is ");
  Sci0_Sendvalue(value);
  Sci0_Sendbyte('\n');
  flag++;
  
  //串口显示当前系统输出实际值
  if(k>7)  k = 0;                                   
  Sci0Write_string("the output of system_ch");
  Sci0_Sendvalue(k);
  Sci0Write_string(" is ");
  Sci0_Sendvalue(U[nowchannel] + 128);
  Sci0_Sendbyte('\n');
  k++;
  */
                                      
}

//如果要加入外部按键操作, 可以将nowchannel设为全局变量








⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -