luozhongchao 发表于 2011-10-24 11:53:26

研究 模糊控制+电机伺服控制 的进来看看!!

最近做点电机的伺服控制,先使用积分分离的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)

lcmdw 发表于 2011-10-24 11:57:24

mark

luozhongchao 发表于 2011-10-24 12:38:40

说说意见吧! 模糊自适应的PID算法谁做过啊?能给点资料吗?

luozhongchao 发表于 2011-10-24 12:42:51

大家都不怎么喜欢说话?

luozhongchao 发表于 2011-10-24 21:11:08

都不研究电机的算法啊?

qwerttt 发表于 2011-10-24 22:10:46

终于大侠研究模糊控制了

zouyf12 发表于 2011-10-24 22:34:27

玩过一两天,感觉模糊控制到最后就是查表,通过输入的变量在数组里找到对应的输出, 当时玩到后面都省去了前面那些模糊化、推理和解模糊, 直接按照感觉改表里的数据了。。。。。

luozhongchao 发表于 2011-10-24 22:47:38

有没有比较好的参考资料和代码啊?
感觉模糊控制经验要求较多!!

kinsno 发表于 2011-10-25 00:14:54

你的做法是对的,直线加速到某个速度,再PID。这个速度稍微选一个,要注意惯性,因为惯性和负载有关系。根据负载和精度的不一样,反复调好的,就和我们调程序一样。

PS:我的BLDC,最高1000转,我可以控制在10转以内,再高精度也没时间去调了,没准这个算法不合适。

sleet1986 发表于 2011-10-25 08:20:34

进来学习学习--对模糊控制不是很懂-

ccmj4708 发表于 2011-10-25 08:27:40

mark

shotstar 发表于 2011-10-25 08:31:53

算法这个东西只能是学习,特别是模糊算法。PID还能用用,模糊没用过。

zouyf12 发表于 2011-10-25 12:47:16

主要是存在很大的主观性,里面的很多东西都是按照人的主观意愿来设定的,其实到后面也就是查表了,虽然我只懂点皮毛。

luozhongchao 发表于 2011-10-25 12:59:59

回复【8楼】kinsno
-----------------------------------------------------------------------

但是在两种控制的 切换的时候怎么处理啊? 如果控制量就在PID和模糊控制的零界点波动,那就会出现一会进行模糊控制,以后进入PID控制区域,这样的话不是很难稳定??我在实际中也遇到了这样的问题,还没找打解决的办法呢
??

chy.du 发表于 2011-10-25 13:24:44

查表控制起来比较好。

司马朝阳 发表于 2013-9-7 00:00:51

学习了

xingyw112 发表于 2013-9-7 06:28:36

学习了,我也用的是这个程序,为我提供了新的思路,谢谢了呀!!!能加QQ交流吗???447230995

windancerhxw 发表于 2013-9-8 22:16:02

{:victory:}mark一下,感觉很有用的

robocon2014 发表于 2014-3-2 22:38:10

是不是要调节积分微分项

Pao_fu 发表于 2014-3-31 14:41:59

正研究着,碰到个量化因子,和隶属的计算问题

Pao_fu 发表于 2014-3-31 15:27:06

正研究着,碰到个量化因子,和隶属的计算问题

EysTech 发表于 2014-7-13 09:48:31

MARK            

linlonghuazbdx 发表于 2016-1-20 12:21:55

兄弟 现在这个研究的怎么样了
页: [1]
查看完整版本: 研究 模糊控制+电机伺服控制 的进来看看!!