发一个我改的PID(硬件问题还没调试过),有用拿去··
本人小白一个,如果有错误的地方请大侠更正下。由于我电机板子还没搞好,以前一块别人的板子上 脉冲管脚是接中断的,没接在计数器上,所以一直没能调试好。 我是用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;
PID *pp1 =&sPID1;
PID *pp2 =&sPID1; //PID Control Structure
long int v_PIDCalc1( signed short set_point,signed short next_point)
{
signed longerror,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 longerror,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值。。。。。。 我顶{:lol:}{:lol:}{:lol:}{:lol:}{:lol:}{:lol:}{:lol:}{:lol:} 接外部中断是可以做测速的。我现在就是这么做的 lgupen 发表于 2012-6-13 13:06 static/image/common/back.gif
接外部中断是可以做测速的。我现在就是这么做的
``````我当时是用外部中断的·····但是没跑系统的情况下,出现了 轮子抽筋现象····我估计是外部中断引起的,也就是说当输出PWM时,突然一个外部中断打断了,那么此时PWM就不再是完整的了。会出现抽筋现象,当然频率高点的MCU令当处理。跑系统我就没试过用外部中断来控制电机转速了。···· 后来我去问了一些人 他们大多用定时器中断做处理。定时器做处理可以不用时时中断,保证了PWM的连贯性。 如果是单纯测速的话另当别论······ 单纯测速用外部中断是可以的 轮子抽筋现象?你说的现象是轮子一直在抖吗?我用PI去控制速度,效果还不错。 lgupen 发表于 2012-6-14 12:14 static/image/common/back.gif
轮子抽筋现象?你说的现象是轮子一直在抖吗?我用PI去控制速度,效果还不错。 ...
你上系统没? 还是只是用一个MCU控制一个电机? 我所谓i的抽筋现象 就是 电机转着转着突然一瞬间没电 然后又有电······那一瞬间很渺小 但是对车的行走很不稳定···· 我上操作系统,用的是前后台的工作方式,我没出现这个现象。。。。会不会是电机对你的控制芯片有干扰呢。你加光耦或什么芯片隔离了没
····可能我没上操作系统的原因吧···· 我到时还是去测试下···· 毕竟当时是用一块ATMEGA88控制2个闭环电机····有些力不从心。。。。加上各种课程设计搞得我那珍贵的时间就从手中消逝了····等我暑假有空再去上个UC/OS2 看看效果怎么样 如果行的胡再发我全部代码过来 mark……嘎嘎嘎噶 继续学习啊啊啊啊啊 我先在在做小车,思路和你差不多,只是在pid参数设置上感觉没法下手,要设置的大概范围是多少? Lucky_Lucky 发表于 2012-7-9 18:36 static/image/common/back.gif
我先在在做小车,思路和你差不多,只是在pid参数设置上感觉没法下手,要设置的大概范围是多少? ...
范围设置大概是按照PID顺序来设置的。也就是说先设置P参数,也就是比例参数。P的设置基本上把你的车的速度定下来了。接下来再设置I参数,也就是积分参数。这里主要是控制响应时间的。当然如果你有示波器的话,可以看出参数不同,PID所映射出来的曲线基本是有点差异的。一个是很快比较平稳,但是很陡。这个参数要保持到既平稳,又在范围内的陡峭。保持系统的稳定性。不发生突变。一般要求不高的就只要PI设置行了。D也就是微分设置的控制作用很微小。一般是不作设置的。 我现在做的 这个平衡车角度 和加速度 还有电机的PWM 都已经跳出来了但是 编码器 怎么获得脉冲数呢?还有就是PID的这个部分还是个新手 忘您赐教 - - 我也是新手啊,大家一起探讨就行了。 你一般是用光电编码器的吧,如果是用这个的话一般有4条线,其中2条是电源和地线。还有2条是对应2个光栅的。这2条接单片机的IO口。我记得被遮住的时候光栅不导通,那么输出那端一般是高电平吧。与此同时另外一个光栅是低电平。要2个光栅就是为了判断轮子的正反转,如果A光栅为搞定平,B光栅输出为低电平为正转。那么与他相反的输出就是反转了。读取脉冲数就是靠读取光栅的一定时间内有几个高电平就行了。当然这种貌似是增量式的。还有种位置式的码盘,那个可以读取此时的坐标为多少。我也不懂,因为没做过那东西。
页:
[1]