搜索
bottom↓
回复: 15

发一个我改的PID(硬件问题还没调试过),有用拿去··

[复制链接]

出0入0汤圆

发表于 2012-5-30 19:11:00 | 显示全部楼层 |阅读模式
本人小白一个,如果有错误的地方请大侠更正下。由于我电机板子还没搞好,以前一块别人的板子上 脉冲管脚是接中断的,没接在计数器上,所以一直没能调试好。 我是用2个码盘电机做小车的。个人觉得最好上UCOS2,因为2个电机那实时性能要保证。加上我是2电机+4舵机的控制 所以。。。。我是上UCOS2的。

typedef struct PID            
{
//    signed int vi_Ref;                        //    设置的速度                这两个参数由于是动态变化的所以。。。
//    signed int vi_FeedBack;                   //   传感器读回来的速度         用形式参数
    long int vi_PreError;                  //  E-1 error
    long int vi_PreDerror;                 //  E-2 error
   
    unsigned int v_Kp;                       // P
    unsigned int v_Ki;                       // I     three parameter
    unsigned int v_Kd;                       // D
               
    long int vl_PreU;                     //所得电压
        
}PID;


PID     sPID1[2];
PID *pp1 =&sPID1[0];
PID *pp2 =&sPID1[1];                                  //  PID Control Structure


long int v_PIDCalc1( signed short set_point,signed short next_point)
{
    signed long  error,d_error,dd_error;   
            
        error = (signed long)(set_point - next_point);            
        d_error = error - pp1->vi_PreError;
        dd_error = d_error - pp1->vi_PreDerror;
        
    pp1->vi_PreError = error;            pp1->vi_PreDerror = d_error;
   
    if( ( error < VV_DEADLINE ) && ( error > -VV_DEADLINE ) );   
    else                                
    {
      pp1->vl_PreU +=(signed long)(  pp1 -> v_Kp * d_error + pp1 -> v_Ki * error  + pp1->v_Kd*dd_error);

    }
   
    if( pp1->vl_PreU >= VV_MAX )         
    {
      pp1->vl_PreU = VV_MAX;
    }
    else if( pp1->vl_PreU <= VV_MIN )   
    {
      pp1->vl_PreU = 0;        

    }                     
     else   if(error>20)
    {
      pp1->vl_PreU=VV_MAX;   
    }
    return (pp1->vl_PreU);            
}

long int v_PIDCalc2( signed short set_point,signed short next_point)
{
    signed long  error,d_error,dd_error;   
            
        error = (signed long)(set_point - next_point);            
        d_error = error - pp2->vi_PreError;
        dd_error = d_error - pp2->vi_PreDerror;
        
    pp2->vi_PreError = error;            pp2->vi_PreDerror = d_error;
   
    if( ( error < VV_DEADLINE ) && ( error > -VV_DEADLINE ) );   
    else                                
    {
      pp2->vl_PreU +=(signed long)(  pp2 -> v_Kp * d_error + pp2 -> v_Ki * error  + pp2->v_Kd*dd_error);

    }
   
    if( pp2->vl_PreU >= VV_MAX )         
    {
      pp2->vl_PreU = VV_MAX;
    }
    else if( pp2->vl_PreU <= VV_MIN )   
    {
      pp2->vl_PreU = 0;        

    }                     
     else   if(error>20)
    {
      pp2->vl_PreU=VV_MAX;   
    }
    return (pp2->vl_PreU);            
}

void PIDInit ()
{   
//    sPID1.vi_Ref = 0 ;         
//    sPID1.vi_FeedBack = 0 ;   
        
    pp1->vi_PreError = 0 ;      
    pp1->vi_PreDerror = 0 ;      
   
    pp1->v_Kp = VV_KPVALUE;
        pp1->v_Ki = VV_KIVALUE;
        pp1->v_Kd = VV_KDVALUE;
                                                       
               
        pp1->vl_PreU = 0;
   
   
   
   
    pp2->vi_PreError = 0 ;      
    pp2->vi_PreDerror = 0 ;      
   
    pp2->v_Kp = VV_KPVALUE;
        pp2->v_Ki = VV_KIVALUE;
        pp2->v_Kd = VV_KDVALUE;
                                                       
               
        pp2->vl_PreU = 0;
    }


起初我调试PID时 思路是这么想的,用定数器采集码盘脉冲的数量,实现测速的功能。同时开启定时器的中断设定周期,每隔一定的周期产生一次中断去读取脉冲数,然后将此脉冲数清零。此时测出的速度值与你设定的速度值想减,经过PID算法。然后输出速度值,输出的速度一路用于反馈,一路用于输出相应的PWM值。。。。。。

出0入0汤圆

发表于 2012-6-6 09:20:47 | 显示全部楼层
我顶

出0入0汤圆

发表于 2012-6-13 13:06:02 | 显示全部楼层
接外部中断是可以做测速的。我现在就是这么做的

出0入0汤圆

 楼主| 发表于 2012-6-13 13:14:02 | 显示全部楼层
lgupen 发表于 2012-6-13 13:06
接外部中断是可以做测速的。我现在就是这么做的

``````我当时是用外部中断的·····但是没跑系统的情况下,出现了 轮子抽筋现象····我估计是外部中断引起的,也就是说当输出PWM时,突然一个外部中断打断了,那么此时PWM就不再是完整的了。会出现抽筋现象,当然频率高点的MCU令当处理。跑系统我就没试过用外部中断来控制电机转速了。····   后来我去问了一些人 他们大多用定时器中断做处理。定时器做处理可以不用时时中断,保证了PWM的连贯性。

出0入0汤圆

 楼主| 发表于 2012-6-13 13:15:35 | 显示全部楼层
如果是单纯测速的话另当别论······    单纯测速用外部中断是可以的

出0入0汤圆

发表于 2012-6-14 12:14:39 | 显示全部楼层
轮子抽筋现象?你说的现象是轮子一直在抖吗?我用PI去控制速度,效果还不错。

出0入0汤圆

 楼主| 发表于 2012-6-14 13:16:55 | 显示全部楼层
lgupen 发表于 2012-6-14 12:14
轮子抽筋现象?你说的现象是轮子一直在抖吗?我用PI去控制速度,效果还不错。 ...

你上系统没? 还是只是用一个MCU控制一个电机?

出0入0汤圆

 楼主| 发表于 2012-6-14 13:20:27 | 显示全部楼层
我所谓i的抽筋现象 就是 电机转着转着突然一瞬间没电 然后又有电······那一瞬间很渺小 但是对车的行走很不稳定····

出0入0汤圆

发表于 2012-6-14 15:23:01 | 显示全部楼层
我上操作系统,用的是前后台的工作方式,我没出现这个现象。。。。会不会是电机对你的控制芯片有干扰呢。你加光耦或什么芯片隔离了没

出0入0汤圆

 楼主| 发表于 2012-6-14 21:44:24 | 显示全部楼层
····可能我没上操作系统的原因吧····   我到时还是去测试下···· 毕竟当时是用一块ATMEGA88控制2个闭环电机····有些力不从心。。。。加上各种课程设计搞得我那珍贵的时间就从手中消逝了····等我暑假有空再去上个UC/OS2 看看效果怎么样 如果行的胡再发我全部代码过来

出0入0汤圆

发表于 2012-7-9 11:01:08 | 显示全部楼层
mark……嘎嘎嘎噶

出0入0汤圆

发表于 2012-7-9 11:13:09 | 显示全部楼层
继续学习啊啊啊啊啊

出0入0汤圆

发表于 2012-7-9 18:36:22 | 显示全部楼层
我先在在做小车,思路和你差不多,只是在pid参数设置上感觉没法下手,要设置的大概范围是多少?

出0入0汤圆

 楼主| 发表于 2012-8-12 01:28:25 | 显示全部楼层
Lucky_Lucky 发表于 2012-7-9 18:36
我先在在做小车,思路和你差不多,只是在pid参数设置上感觉没法下手,要设置的大概范围是多少? ...

范围设置大概是按照PID顺序来设置的。也就是说先设置P参数,也就是比例参数。P的设置基本上把你的车的速度定下来了。接下来再设置I参数,也就是积分参数。这里主要是控制响应时间的。当然如果你有示波器的话,可以看出参数不同,PID所映射出来的曲线基本是有点差异的。一个是很快比较平稳,但是很陡。这个参数要保持到既平稳,又在范围内的陡峭。保持系统的稳定性。不发生突变。一般要求不高的就只要PI设置行了。D也就是微分设置的控制作用很微小。一般是不作设置的。

出0入0汤圆

发表于 2012-8-21 17:03:11 | 显示全部楼层
我现在做的 这个平衡车  角度 和加速度 还有电机的PWM 都已经跳出来了  但是 编码器 怎么获得脉冲数呢?  还有就是PID的这个部分  还是个新手 忘您赐教

出0入0汤圆

 楼主| 发表于 2012-8-21 20:01:35 | 显示全部楼层
- - 我也是新手啊,大家一起探讨就行了。 你一般是用光电编码器的吧,如果是用这个的话一般有4条线,其中2条是电源和地线。还有2条是对应2个光栅的。这2条接单片机的IO口。我记得被遮住的时候光栅不导通,那么输出那端一般是高电平吧。与此同时另外一个光栅是低电平。要2个光栅就是为了判断轮子的正反转,如果A光栅为搞定平,B光栅输出为低电平为正转。那么与他相反的输出就是反转了。读取脉冲数就是靠读取光栅的一定时间内有几个高电平就行了。当然这种貌似是增量式的。还有种位置式的码盘,那个可以读取此时的坐标为多少。我也不懂,因为没做过那东西。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-30 05:37

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表