研究 模糊控制+电机伺服控制 的进来看看!!
最近做点电机的伺服控制,先使用积分分离的PID算法,感觉控制效果很差,参数及其不好调试,所以就放弃了!现在正研究模糊PID的控制算法,希望做过的朋友,提供点意见和资料!不胜感激啊!在网上找了一片模糊控制的代码,控制效果好,控制精度不行,后来在此代码的基础上加上PID控制,控制效果还可以,大概思路是先用模糊控制将误差整定到一个小的区间,然后在使用PID!但是在两种模式切换的时候,容易震荡,希望大家帮忙想想办法!!
下面是控制代码:
/**********************************************************/
/*输入量P语言值特征点*/
const s16 PFF={0,30,60,90}; //偏差输入值范围
/*输入量D语言值特征点*/
const s16 DFF={0,15,30,45}; //偏差微分输入范围
/*输出量U语言值特征点*/
const s16 UFF={0,15,30,45,60,75,90}; //输出范围
/*采用了调整因子的规则表,大误差时偏重误差,小误差时偏重误差变化*/
/*a0=0.3,a1=0.55,a2=0.74,a3=0.89 */
const s16 rule={
//误差变化率 -3,-2,-1, 0, 1, 2, 3 // 误差
{-6,-6,-6,-5,-5,-5,-4,}, // -3
{-5,-4,-4,-3,-2,-2,-1,}, // -2
{-4,-3,-2,-1, 0, 1, 2,}, // -1
{-4,-3,-1, 0, 1, 3, 4,}, // 0
{-2,-1, 0, 1, 2, 3, 4,}, // 1
{ 1, 2, 2, 3, 4, 4, 5,}, // 2
{ 4, 5, 5, 5, 6, 6, 6}}; // 3
/**********************************************************/
s16 FuzzyCale(s16 P,s16 D) /*模糊运算引擎,输入偏差和偏差微分*/
{
#define PMAX 100 //偏差正最大值
#define PMIN -100 //偏差负最大值
#define DMAX 100 //偏差微分正最大值
#define DMIN -100 //偏差微分负最大值
#define FMAX 100 /*输出语言值的满幅值*/
s16 U; /*偏差,偏差微分以及输出值的精确量*/
u16 PF,DF,UF; /*偏差,偏差微分以及输出值的隶属度*/
s16 Pn,Dn,Un; //分区参数
s32 temp1,temp2;
/*隶属度的确定*/
/*根据P,D的指定语言值获得有效隶属度*/
if(P>-PFF && P<PFF)
{
if(P<=-PFF) {Pn=-2;PF=FMAX*((float)(-PFF-P)/(PFF-PFF));} // 将误差分区域,同事求出相应的
else if(P<=-PFF) {Pn=-1;PF=FMAX*((float)(-PFF-P)/(PFF-PFF));}
else if(P<=PFF) {Pn=0; PF=FMAX*((float)(-PFF-P)/(PFF-PFF));}
else if(P<=PFF) {Pn=1; PF=FMAX*((float)(PFF-P)/(PFF-PFF));}
else if(P<=PFF) {Pn=2; PF=FMAX*((float)(PFF-P)/(PFF-PFF));}
else if(P<=PFF) {Pn=3; PF=FMAX*((float)(PFF-P)/(PFF-PFF));}
}
else if(P<=-PFF) {Pn=-2; PF=FMAX;}
else if(P>=PFF) {Pn=3; PF=0;}
PF=FMAX-PF; //这个为低一级隶属度
if(D>-DFF && D<DFF)
{
if(D<=-DFF) {Dn=-2;DF=FMAX*((float)(-DFF-D)/(DFF-DFF));}
else if(D<=-DFF) {Dn=-1;DF=FMAX*((float)(-DFF-D)/(DFF-DFF));}
else if(D<=DFF) {Dn=0; DF=FMAX*((float)(-DFF-D)/(DFF-DFF));}
else if(D<=DFF) {Dn=1; DF=FMAX*((float)(DFF-D)/(DFF-DFF));}
else if(D<=DFF) {Dn=2; DF=FMAX*((float)(DFF-D)/(DFF-DFF));}
else if(D<=DFF) {Dn=3; DF=FMAX*((float)(DFF-D)/(DFF-DFF));}
}
else if(D<=-DFF) {Dn=-2; DF=FMAX;}
else if(D>=DFF) {Dn=3; DF=0;}
DF=FMAX-DF; //这个为低一级隶属度
/*使用误差范围优化后的规则表rule*/
/*输出值使用13个隶属函数,中心值由UFF指定*/
/*一般都是四个规则有效*/
Un=rule;
Un=rule;
Un=rule;
Un=rule;
if(PF<=DF)UF=PF; else UF=DF;
if(PF<=DF)UF=PF; else UF=DF;
if(PF<=DF)UF=PF; else UF=DF;
if(PF<=DF)UF=PF; else UF=DF;
/*同隶属函数 输出语言值求大*/
{
if(Un==Un)
{
if(UF>UF)UF=0;
else UF=0;
}
if(Un==Un)
{
if(UF>UF)UF=0;
else UF=0;
}
if(Un==Un)
{
if(UF>UF)UF=0;
else UF=0;
}
if(Un==Un)
{
if(UF>UF)UF=0;
else UF=0;
}
if(Un==Un)
{
if(UF>UF)UF=0;
else UF=0;
}
if(Un==Un)
{
if(UF>UF)UF=0;
else UF=0;
}
}
/*重心法反模糊*/ //加权平均算法
{/*Un[]原值为输出隶属函数标号,转换为隶属函数值*/
if(Un>=0)Un=UFF];else Un=-UFF[-Un];
if(Un>=0)Un=UFF];else Un=-UFF[-Un];
if(Un>=0)Un=UFF];else Un=-UFF[-Un];
if(Un>=0)Un=UFF];else Un=-UFF[-Un];
}
temp1=UF*Un+UF*Un+UF*Un+UF*Un;
temp2=UF+UF+UF+UF;
U=temp1/temp2;
return U;
}
s16 FuzzyControl(Fuzzy *Fuzzy,s16 NextPoint)
{
s16 ek,eck;
s16 temp1;
ek = SetPoint - NextPoint; //得到误差值
eck = ek - Fuzzy->ek_1; //得到误差变化值
temp1 = FuzzyCale(ek,eck);
//Fuzzy->ek_2 =Fuzzy->ek_1;
Fuzzy->ek_1 =ek; //更新两次误差值,备下次计算误差变化使用;
return temp1 ;
}
s16 Fuzzy_Pid(PID* pid,Fuzzy *Fuzzy,s16 NextPoint)
{
s16dError1,dError2, Error;
s16 ek;
s16 temp1;
s16 dU;
ek = SetPoint -NextPoint;
if( ek>=-40 && ek<=40 ) //小误差使用PID 控制 ,位置式控制
{
mark = 1;
Error = SetPoint -NextPoint; // 偏差
pid->SumError += Error; // 积分
dError1 = pid->ek_1 - pid->ek_2; // 当前微分
pid->ek_2 = pid->ek_1;
pid->ek_1 = Error;
temp1 = pid->Kp * Error // 比例项
+ pid->Ki * (pid->SumError/2) // 积分项
+ pid->Kd * dError1 ; // 微分项
if ( temp1 >=200)temp1= 190 ; //限幅输出
if ( temp1 <= -200)temp1= -190;
temp1 /=2;
// mark = 1;
// Error = SetPoint -NextPoint; //求偏差
//
// dError1 = Error - pid->ek_1; //偏差变化值
// dError2 = pid->ek_1 - pid->ek_2;
//
// if((pid->LastValue >= 300 && Error > 0)||(pid->LastValue <= -300 && Error < 0)) //积分分离
// {
// dU =((s16)( pid->Kp * (Error -pid->ek_1) +pid->Kd * (dError1 - dError2)))>>2;
// }
//
// dU =( (s16)(pid->Kp * (Error -pid->ek_1) + pid->Ki * Error +pid->Kd * (dError1 - dError2)) )>>2;
//
// pid->ek_2 = pid->ek_1; //更新误差
// pid->ek_1 = Error;
//
// temp1 =dU+ pid->LastValue;
// pid->LastValue = temp1;
//
// if ( temp1 >=200)temp1= 190 ; //限幅输出
// if ( temp1 <= -200)temp1= -190;
//
// temp1 /=2;
}
else //大误差使用模糊控制
{
mark= 2;
temp1 =FuzzyControl(Fuzzy,NextPoint);
}
return temp1;
}
为了方便查看 上传源码
ourdev_688086TEYCVO.txt(文件大小:37K) (原文件名:main.txt) mark 说说意见吧! 模糊自适应的PID算法谁做过啊?能给点资料吗? 大家都不怎么喜欢说话? 都不研究电机的算法啊? 终于大侠研究模糊控制了 玩过一两天,感觉模糊控制到最后就是查表,通过输入的变量在数组里找到对应的输出, 当时玩到后面都省去了前面那些模糊化、推理和解模糊, 直接按照感觉改表里的数据了。。。。。 有没有比较好的参考资料和代码啊?
感觉模糊控制经验要求较多!! 你的做法是对的,直线加速到某个速度,再PID。这个速度稍微选一个,要注意惯性,因为惯性和负载有关系。根据负载和精度的不一样,反复调好的,就和我们调程序一样。
PS:我的BLDC,最高1000转,我可以控制在10转以内,再高精度也没时间去调了,没准这个算法不合适。 进来学习学习--对模糊控制不是很懂- mark 算法这个东西只能是学习,特别是模糊算法。PID还能用用,模糊没用过。 主要是存在很大的主观性,里面的很多东西都是按照人的主观意愿来设定的,其实到后面也就是查表了,虽然我只懂点皮毛。 回复【8楼】kinsno
-----------------------------------------------------------------------
但是在两种控制的 切换的时候怎么处理啊? 如果控制量就在PID和模糊控制的零界点波动,那就会出现一会进行模糊控制,以后进入PID控制区域,这样的话不是很难稳定??我在实际中也遇到了这样的问题,还没找打解决的办法呢
?? 查表控制起来比较好。 学习了
学习了,我也用的是这个程序,为我提供了新的思路,谢谢了呀!!!能加QQ交流吗???447230995
{:victory:}mark一下,感觉很有用的 是不是要调节积分微分项 正研究着,碰到个量化因子,和隶属的计算问题 正研究着,碰到个量化因子,和隶属的计算问题 MARK 兄弟 现在这个研究的怎么样了
页:
[1]