【RM】串级PID学习笔记
在调试英雄机器人的过程中,云台出现了疯转,观察云台的运动规律,我们发现云台会先进行左右振荡,接着才进行快速的单向旋转。问题的重点在于同样的调参方式在步兵机器人上能够正常运行,但到了英雄机器人上却出现了问题。
于是我们开始利用Debug抓取当前的实时参数,并且对代码进行更细致的分析。
float PID(float now,float target)
{
static int err=0;
float out_put;
if(target<0) {target+=8192;}//不加的话电机会乱转
err=target-now; //计算偏差
if( err>(max_angle/2)){ err= err-max_angle;}//解决360度问题让电机走最优路径
else if( err<-(max_angle/2)){ err= err+max_angle;}
out_put=Xp/100*err-Xd/100*(Motor_measure[4].speed); //PI控制器
if(out_put>max_output){out_put=max_output;}
else if(out_put<-max_output){out_put=-max_output;}//限制输出,加上后改max_output可调节电机回弹的力气
return out_put; //输出
}
上部分为内环PID代码,目标值为6020电机的角度值,当前值为陀螺仪Yaw轴返回值。
{
PID->error[2] = PID->error[1]; //误差值传递,1为上一次,2为上上次
PID->error[1] = PID->error[0]; //误差值传递,0为最新误差,1为上一次
PID->measure = measure; //参数传递,下同
PID->target = target;
PID->error[0] =target - measure;
if(PID->error[0]>4096) PID->error[0]=PID->error[0]-8191; //角度环误差处理,限制在-4096 ~~ +4096
else if(PID->error[0]<-4096) PID->error[0]=PID->error[0]+8191;
//}
PID->Pout = PID->Kp * PID->error[0]; //p输出
PID->Iout += PID->Ki * PID->error[0]; //i输出,累加 //前后误差差值传递,0为最新差值
PID->D_item = (PID->error[0] - PID->error[1]); //微分项计算
PID->Dout = PID->Kd * PID->D_item; //d输出,通过微分项
LimitMax(PID->Iout,PID->Max_iout); //i输出限制
PID->OUT = PID->Pout + PID->Iout + PID->Dout; //总输出
LimitMax(PID->OUT,PID->Max_out);
return PID->OUT
}
上部分为外环PID代码,目标值为外环的输出值,当前值为6020电机速度值。
流程国如下图所示:
那么结合该两部分代码,串级PID的总体思路就是,先利用外环计算出目标值与当前值位置上的差值,再去通过内环根据这个差值计算电机该以多少的速度去进行运动,从而到达指定角度。很明显,若内环的值给的不恰当,即使外环的P、D非常小,也很容易导致PID输出过大,从而导致电机疯转。
电机疯转的原因,也与结构上的设计有关,步兵机器人的云台长度与质量都要小于英雄机器人的,从而导致英雄机器人云台的转动惯量要比步兵机器人大得多,这时如果使用一样的调参方法,会导致即使云台已经达到目标位置了,但由于惯性仍然会继续运动,此时电机的角度值与陀螺仪的Yaw轴返回值又产生了差值,导致外环PID的输出值变大,进而导致内环的目标速度值变大,这会是一个不会停止的反复计算,因为速度越大,只会导致云台角度值和陀螺仪Yaw轴返回值的差值越大,进而导致整个云台的速度越来越快,最后云台开始朝同一个方向快速旋转。
发现这些规律之后,问题就很好解决了。
转变一下思路,从外环开始出发,协调外环的P与D,加大电机抵抗惯性运动的转矩电流,减小内环的P值,同时在利用Vofa+上位机打印出波形图,就可以得到理想的控制效果了。
若各路高手有不同的看法与见解,还请多多指教!