MC9S12DG128模糊控制崩溃之旅<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
夜随风舞
<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />Tuesday, May 06, 2008
在BLOG上允诺要写有关模糊控制的内容很长时间了,一直未兑现。今天工作稍闲,想起了承诺,所以就开始敲起了键盘。不过,首先得声明,本人并非学自动控制相关专业的,只不过是由于“项目”需要做起了模糊控制,所以有不足或是错误之处,敬请谅解!呵呵……热烈欢迎相关的讨论。
另外,之所以将题名选为“MC9S12DG128模糊控制崩溃之旅”,是因为我前前后后调试了几近一个月才有点头绪,所以是够崩溃的。好了,言归正传。
首先,简单介绍一下模糊控制。
l 模糊控制以模糊集合理论为基础,而模糊集合靠隶属度函数来描述。至于什么是“模糊集合理论”,什么是“隶属度函数”。请网友查找相关的网页或书籍。在此不作深入的说明。
l 模糊推理方式
1. IF A THEN B
2. IF A THEN B ELSE C
3. IF A AND B THEN C
第三种表达有得最多,而且在这里我用的也是这个。通常在实际应用中
以A表示误差,用B表示误差变化率,而C则是控制量。
l 模糊控制步骤
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />
精确量输入 |
模糊化 |
规则推理 |
反模糊 |
精确量输出 |
现在稍稍介绍一下我的系统,我的系统是基于Freescale公司MC9S12DG128的一个随动系统,要求能跟随目标的变化而作相应的角度,速度的变化。D系列的产品具有模糊推理的功能,有模糊指令集,而且有模糊机例程。而我正是在该模糊机例程的基础上做的模糊控制。下面是该模糊机的例程代码。
#include "syf.h"
uchar FUZ_INS[18];
uchar FUZ_OUTS[9];
const uchar INPUT_MFS[18][4]={
//trend
0,4,0,20,
2,10,10,10,
6,14,10,10,
12,22,10,8,
15,25,8,8,
18,28,8,10,
26,34,10,10,
30,38,10,10,
36,40,20,0,
//av_line
0,5,0,8,
0,10,8,8,
5,15,8,8,
10,20,8,8,
15,25,8,8,
20,30,8,8,
25,35,8,8,
30,40,8,8,
35,40,8,0
};
const uchar OUTPUT_MFS[9]={
0,1,2,3,4,5,6,7,8
};
const uchar RULE_START[406]={
//no.1
(9*0)+0,(9*1)+0,0xfe,(9*0)+0+18,0xfe, //no.1
(9*0)+0,(9*1)+1,0xfe,(9*0)+0+18,0xfe, //no.2
(9*0)+0,(9*1)+2,0xfe,(9*0)+0+18,0xfe, //no.3
(9*0)+0,(9*1)+3,0xfe,(9*0)+1+18,0xfe, //no.4
(9*0)+0,(9*1)+4,0xfe,(9*0)+1+18,0xfe, //no.5
(9*0)+0,(9*1)+5,0xfe,(9*0)+2+18,0xfe, //no.6
(9*0)+0,(9*1)+6,0xfe,(9*0)+2+18,0xfe, //no.7
(9*0)+0,(9*1)+7,0xfe,(9*0)+3+18,0xfe, //no.8
(9*0)+0,(9*1)+8,0xfe,(9*0)+4+18,0xfe, //no.9
……
0xff };
uchar fuzzy(uchar fuzzy_in_1,uchar fuzzy_in_2){
char fuzzy_out;
fuzzy_out = 0;
__asm{
LDX #INPUT_MFS ;Point at MF definitions
LDY #FUZ_INS ;Point at fuzzy input table
LDAA fuzzy_in_1 ;Get first input value
LDAB #9 ;9 labels per input
GRAD_LOOP: MEM ;Evaluate one MF
DBNE B,GRAD_LOOP ;For 9 labels of 1 input
LDAA fuzzy_in_2 ;Get the second input value
LDAB #9 ;5 labels per input
GRAD_LOOP1: MEM ;Evaluate one MF
DBNE B,GRAD_LOOP1 ;For 5 labels of 1 input
LDAB #9 ;Loop count
RULE_EVAL: CLR 1,Y+ ;Clear a fuzzy out & inc ptr
DBNE b,RULE_EVAL ;Loop to clr all fuzzy outs
LDX #RULE_START ;Point at first rule element
LDY #FUZ_INS ;Point at fuzzy ins And outs
LDAA #$FF ;Init A (and clears V-bit)
REV
DEFUZ: LDY #FUZ_OUTS ;Point at fuzzy outputs
LDX #OUTPUT_MFS ;Point at singleton positions
LDAB #9 ;9 fuzzy outs per COG output
WAV ;Calculate sums for wtd av
EDIV ;Final divide for wtd av
TFR Y,D ;Move result to A:B
STAB fuzzy_out ;Store system output
}
return (fuzzy_out);
}
上面的粗体部分是模糊机的例程,前面的数组是精确输入,精确输出和规则库。
一开始,我花了很多时间来消化这个例程,不好懂,主要是当时对模糊控制的过程不是很理解吧。然后就看了很多资料,后来也就好像是顿悟了一样,理解了什么是模糊控制。但是,光光理解了不行阿,还要形成代码,才行阿。就又接着看资料,找S12在这一块的论述,找例程等。最后,才形成了上面的代码。下面简要的说一下代码的格式为什么是那样的。在const uchar INPUT_MFS[18][4]中一行的数据的意思是“起始点坐标,终点坐标,前沿斜率,后沿斜率”。而在规则库中, “(9*0)+2,(9*1)+0,0xfe,(9*0)+0+18,0xfe, //no.1”,“oxfe”是分割标志,第一个前面是模糊输入表的8位偏移量,其后是输出表的8位偏移量。其实具体我的理解也不是很深。而且我在规则库这里还碰到一个问题,就是,在上面大家可以看到“(9*0)+0+18”,“(9*0)”好理解,因为输出的隶属度函数是一维数组,而“+0”表示的该一维数组中的第一位数,而其后的“+18”就不知道为何物了!而且我试过,如果输入的语言值只有7个话,那么后就应该改为“+14”,而且这里是“+18”也好,还是“+14”也好,它们对应的输出都只是单值函数,不是三角函数或是梯形的。但是如果要提高系统的控制精度的话,单值函数是胜任不了的,所以我尝试换成三角函数,但是,模糊不出来正确的结果。不知道有没有高手做过类似的,有没有碰到类似的问题。
最后,上面提出来的问题也没解决,只能是用单值函数暂时顶一下。然后我就手动输入精确值,看输出是否符合规则上的,是不是我想要的。很好,出来的精确值我很满意,然后,我就满怀信心的将我的系统放到实际的环境中,让它先采集目标的特定参数,然后再利用模糊来控制系统,结果始终就是出不来正确的结果。一开始,我以为是我的模糊有问题,就再次手动输入了一次精确值,输出正确。然后再实际测试目标的特定参数,也在其论域内,而且我可以确认的是我的隶属度函数的选取还是比较合理的。但为什么两单独测试都很正常,而结合在一起就不行了。很崩溃,当时真有不想用模糊控制的冲动,但我又觉得很不甘心。就仔细检查我的代码,后来发现是两个常量的值搞反掉了。但当时也不能肯定就是这个原因,抱着试一试的态度,把它们的值修改过来,重新整合系统,嘿,成了,能根据目标的变化而随动了。而且效果还不错。呵呵……
其实,调试一个月的模糊之后,感觉这个跟调试者的经验,对系统的理解度有很大的关系。而且隶属度函数啊,规则库啊,不都是调试者根据一定的理论基础结合实际经验获得吗?虽然我的模糊现在能起到一定的作用了,但是还不是很完善。尤其是上面的问题。
〔参考文献:单片嵌入式应用在线开发方法 邵贝贝 清华大学出版社〕
注:未经允许,请勿转载,虽然写得不怎样,呵呵……
欢迎讨论,QQ:373538543,E_MAIL:shuyingfei@126.com
用户435602 2013-1-20 18:56
用户377235 2013-1-10 21:35
我也是在学这个,也不太懂。我的邮箱是757118560@qq.com,如果有好的资料共享,感激不尽
用户1378933 2009-6-11 21:30
用户1378933 2009-6-11 21:29