程序为模糊控制程序,基于8位单片机,为模糊控制算法程序,实现简单的模糊控制,经实践总结得出,当调整幅度较大时,会出现振荡,系统难以达到稳定,这就需要更高一级的算法控制调整,当调整幅度较小时,系统可以很快达到稳定。
以下为模糊算法源程序:
#include "reg52.h"//------------------------------------------------------------------------------------// 定义差距输入常量#define GAP_ZERO 0x00#define GAP_VSMALL 0x01#define GAP_SMALL 0x02#define GAP_MEDIUM 0x03#define GAP_BIG 0x04// 定义控制输出常量#define TURN_ZERO 0x80#define TURN_VSMALL 0x81#define TURN_SMALL 0x82#define TURN_MEDIUM 0x83#define TURN_BIG 0x84//-------------定义常量----------------------------------------------------------------#define MU_MAX 0XFF //模糊度的最大值为0XFF代表面1#define RULE_TOT 10 //规则数个数#define MF_TOT 5 //成员函数的个数#define IO_NUM 0x07#define LABEL_NUM 0x70#define DEFAULT_VALUE 0x00//----------------定义数据库-----------------------------------------------------------unsigned char code output_memf[MF_TOT]={0, 15, 35, 60, 102};// OUTPUT TURNING NUMBER: //ZERO, VSMALL, SMALL, MEDIUM, BIGunsigned char code input_memf[MF_TOT][4]={// 输入功能函数以点斜式方式存储. 第一维成员函数标号第二维是点斜式数据//距离功能函数{ 0x00, 0x00, 0x00, 0x0d }, // VSLOW{ 0x00, 0x0d, 0x14, 0x0d }, // SLOW{ 0x1e, 0x0d, 0x32, 0x0d }, // MEDIUM{ 0x3C, 0x0d, 0x50, 0x0d }, // FAST{ 0x50, 0x09, 0x6e, 0x00 } // VFAST };//-----------定义模糊系统规则-----------------------------------------------------------unsigned char code rules[RULE_TOT]={ // if... then...GAP_ZERO,TURN_ZERO,GAP_VSMALL,TURN_VSMALL,GAP_SMALL,TURN_SMALL,GAP_MEDIUM,TURN_MEDIUM,GAP_BIG,TURN_BIG };//-----------定义各变量-----------------------------------------------------------------unsigned char outputs[MF_TOT],fuzzy_out; //模糊输出mu值//-----------子程序函数头申明-----------------------------------------------------------void fuzzy_engine(uchar);uchar compute_memval(uchar,uchar);void defuzzify(void);uchar compute_memval(uchar input,uchar label) { int data temp; if (input < input_memf[label][0]) { // 如果输入不在曲线下u值为0 return 0; } else { if (input < input_memf[label][2]) { temp=input; // 用点斜式计算mu temp-=input_memf[label][0]; if (!input_memf[label][1]) { temp=MU_MAX; } else { temp*=input_memf[label][1]; } if (temp < 0x100) { // 如果结果不超过1 return temp; // 返回计算结果 } else { return MU_MAX; // 确保mu值在范围内 } } else { // 输入落在第二条斜线上 temp=input; // 用点斜式方法计算 mu temp-=input_memf[label][2]; temp*=input_memf[label][3]; temp=MU_MAX-temp; if (temp < 0) { // 确保结果不小于0 return 0; } else { return temp; // mu为正 – 返回结果 } } } return 0; }void defuzzify(void) { unsigned long numerator, denominator; unsigned char j; numerator=0; // 恢复总数值 denominator=0; for (j=0; j { // 计算总和值 numerator+=(outputs[j]*output_memf[j]); denominator+=outputs[j]; outputs[j]=0; // 清零输出作为参考使用 } if (denominator) { // 确保分母是0的情况不发生 fuzzy_out=numerator/denominator; // 确定 COG } else { fuzzy_out=DEFAULT_VALUE; // 没有规则被触发 } } }unsigned char bdata clause_val; // 保存当前的分支进行快速访问sbit clause_type = clause_val^7; // 表示分支是否是条件分支或者是结果分支void fuzzy_engine(uchar input) { bit then; // 当正在分析结果时置位 unsigned char if_val, // 保存当前规则中条件分支中的值 clause, // 规则基中当前的分支 mu, // 保存当前分支中的值 label=0; // 被条件使用的成员函数 then=0; // 设第一个分支是条件分支 if_val=MU_MAX; // max out mu for the first rule for (clause=0; clause { // 遍历每条规则 clause_val=rules[clause]; // 读入当前的分支 if (!clause_type) { // 当前的分支是不是条件分支 if (then) { // 是否正在分析结果... then=0; if_val=MU_MAX; // 复位mu } mu=compute_memval(input, label); // 得到条件分支的值 if_val=mu; label++; } else { // 当前分支是结果 then=1; // 置位标志位,如果当前规则的mu比参考的值要大,保存这个值作为新的模糊输出 if (outputs[clause_val&0x07] < if_val) { outputs[clause_val&0x07]=if_val; } } } defuzzify(); // 用COG方法计算模糊输出和反模糊输出 }//------------------------------------------------------------------------------