PID介绍
PID介绍此算法是由P(比例)、I(积分)和D(微分)通过线性组合构成控制器,由于PID控制器结构较为简单,参数整定也较为容易,所以应用非常广泛。
P(比例):==通俗的讲就是放大误差,==计算出实际测量值和期望值差值,然后和比例系数Kp相乘,这种控制器输出的变化与输入控制器的偏差成比例关系。一个简单的比例控制会使系统震荡,使测量值在期望值周围来回变换,而P较大时,对误差放大就会更大,虽然到达期望值所需要的时间变短,但是震荡时间变长,还会产生超调,P过大时会使系统不稳定;P较小时又会使达到期望值所需的时间变长,但是震荡时间变短,但是容易造成四旋翼无人机反应不灵敏。
I(积分):来控制过去,积分项是将误差对采样时间进行积分,然后乘以一个积分系数Ki,然后不断的累加,也就是过去一段时间的误差和,他的作用就是在测量值在趋近于期望值的时候给一个反作用的量,依次来消除稳态误差,提高系统的控制精度。
D(微分):将误差进行导数,再乘以一个Kd,微分系数较大时,超调会变大,但是调节时间变短。当微分系数较小时超调也会变大,调节时间也会较长,只有微分系数合适,才会使超调量较小,调节时间也会变短。
PID仿真分析
调节PID多了就会有经验,什么现象会合适,先调什么再调什么。调节PID需要一个调试架,也可以自己做,千万不要调PID的时候直接飞,在调试架调试的时候也要小心,不要被桨叶打着手。
在四旋翼中,有两个输入量,这样我们就可以写一个二阶的PID控制器,也就是常说的串级PID,当然可以使用单级PID,但是调节效果不如串级PID,输入量为角度和角速度,那么可以设置一个内外环,先进行外环控制,将角度先传入一个PID控制器,由于我们想要四旋翼飞行平稳,则横滚和俯仰的期望值为0,所以期望值赋值为0,此时控制器的输出为期望的角速度,那么我们就可以进入到另一个单级PID中,将外环的输出值作为角速度环(内环)的期望值,将实时测量的角速度值设为内环的测量值,那么内环的输出作为给电机的控制量。
在调节时需要把P、I、D三个系数归零,开始调节Kp,先设置Kp小一点的值,增大油门临界到将要起飞的状态,然后晃动杆子,让四旋翼晃动,观察飞机能否调节到平衡位置,如果感觉没有力气或者调节不回去或者比较慢就表明Kp值小了,就需要慢慢往上调,那么什么时候合适呢?当四旋翼开始在水平位置震荡时,就说明Kp值已经快要接近合适值了,再调大一点时,四旋翼会大幅度震荡,有时可能会呈现发散现象,就是调节的幅度会越来越大,最终达到不可控的状态,此时就要减小一些Kp值,这样的比例系数就算是合适。
接下来我们就要消除P值带来的震荡,调节Ki值,当Ki值较小时,对于消除震荡气的作用不大,则依然在震荡,可能会有些作用,但也是在轻微震荡。当Ki值合适时,就可以消除震荡,并且反应时间在我们的接收范围之内。
当Ki值过大时就会使整个系统的反应时间拉长。
当Ki值合适的时候,一般的控制系统当Kp和Ki值调好了其实就可以了,Kd值可以不用调,Kd作用就是起一些抗干扰的作用,就像是一辆汽车从路边驶到路中间,可能在行驶过程中路上会有一些坑,那么就会影响到路中间的时间和效果,那么Kd的作用就是这样。
那么就需要根据这些系数的特性去写控制器了。
void UpdatePID(PID_t* pid, const float dT)
{
pid->Err = pid->desired - pid->measured;
if(pid->Err < pid->DeathArea && pid->Err > -pid->DeathArea)
{pid->Err = 0;}
//做误差限幅
if(pid->Err_LimitHigh != 0 && pid->Err_LimitLow != 0)
{pid->Err=LIMIT(pid->Err,pid->Err_LimitLow,pid->Err_LimitHigh);}
pid->integ += pid->Err * dt; //积分项
//积分限幅
if(pid->IntegLimitHigh != 0 && pid->IntegLimitLow != 0)
{pid->integ=LIMIT(pid->integ,pid->IntegLimitLow,pid->IntegLimitHigh);}
deriv = -(pid->measured - pid->prevError)/dt; // 微分项
pid->out=pid->kp*pid->Err+pid->ki*pid->integ+pid->kd * deriv;//PID的输出结果
//PID输出限幅
if(pid->OutLimitHigh != 0 && pid->OutLimitLow != 0)
{pid->out=LIMIT(pid->out,pid->OutLimitLow,pid->OutLimitHigh);}
pid->prevError = pid->measured;//微分先行(变式)用法
那么串级PID需要将输出值当做下一个PID的期望值,角速度作为观测值。