PID算法笔记(初学者对位置式,增量式,双环pid的认识)含代码


PID算法是一种很常用的算法,对于PID算法最关键的是调参,关于调参的文章会在后续去发表,这次想简要的阐述下PID算法的应用

P:Proportion(比例),就是输入偏差乘以一个常数。
I :Integral(积分),就是对输入偏差进行积分运算。
D:Derivative(微分),对输入偏差进行微分运算。
(输入偏差=读出的被控制对象的值-设定值。比如说我要把温度控制在26度,但是现在我从温度传感器上读出温度为28度。则这个26度就是”设定值“,28度就是“读出的被控制对象的值”。)

1稳定性(P和I降低系统稳定性,D提高系统稳定性):在平衡状态下,系统受到某个干扰后,经过一段时间其被控量可以达到某一稳定状态;
2 准确性(P和I提高稳态精度,D无作用):系统处于稳态时,其稳态误差;
3快速性(P和D提高响应速度,I降低响应速度):系统对动态响应的要求。一般由过渡时间的长短来衡量。

对于P项,表述的是当前偏差值,就是e(t)=期望值-当前值,期望值就是你最后想达到的值,例如步进电机,你想让它转90度,那么这个就是期望值,当前值就不多说了。如果使用pid算法只用P项的话,如上图公式Kp*e(t)在系统稳点的时候会达到零,这会发生什么情况呢,比如说你在做一个四轴飞行器,你用pid算法控制电机转速,当达到某一高度的时候你想让四轴停止,如果你只用P项的话,当四轴飞行器到达目标位置时,u(t)=0就代表着电机不转了,你好容易搞的四轴直接GG,显然只有P项肯定是不行的。

所以我们就引入了I项,I项是累加误差,也很简单,就是从开始计时起到当前时刻误差的累加和,代码实现上也很简单,就是a+=e(t)(a代表误差累加和),有了积分项,四轴飞行器就不会出现到达目标位置u(t)=0这种问题了,但是又有新的问题出现了,虽然这两项帮助我们去调节电机的目标位置,但是这两项加起来的d(u(t))实在是太大了,四轴飞行器可能在电机惯性的作用下直接飞过了目标位置,虽然可以慢慢等去让算法自己去调节,但是问题在于调节的时间很长,根本满足不了要求,就比如说电赛2011年赛题,出题者让你在15s内调节到目标位置,但你这pid要2分钟,这肯定得完蛋;。

所以我们引入了D项,D即求微分,在模拟信号中是求误差的微分,数字信号中是e(t)-e(t-1)大家学过高数都明白微分的含义,用微分项可以去对e(t)进行负反馈调节(高中生物),当我的积分项和比例项过大时,即u(t)增长过快时,利用微分项可以抑制这种快速的增长。

这就是pid的基本概念下面时pid的常用几种代码和思路

位置式PID

位置式PID是最简单的PID形式,利用位置式PID可以做出不少形式的应用了,上面图的公式便是位置式PID,位置式PID相较于增量式PID由于积分项的存在,对于时间积累的误差较大。

增量式PID

增量式PID的公式表现形式为

P=Kp*(current_error﹣last_error);

D=Kd*(current_error﹣2*last_error﹢prev_error);

I=Ki*current_error;

这是数字信号的增量式PID,模拟信号换成微分就好。如上述公式所示,增量式PID对于信号实时性比较高,用的数据都是这一段时间前后的数据,没有积分项的误差。

双环PID控制

双环PID控制

双环PID控制相较于单环PID有明显的优势,它的存在能让系统达到目标状态更快更稳定,双环PID的代码实现也非常简单,以直流电机为例

//外环控制(用的是增量式pid)

float PIDwaihuan_output ()
{
    float PIDOUT;
    pid.Ek=pid.Sv-pid.Pv;//微分项(离散形式)
    PIDOUT=pid.Kp*pid.Ek+pid.Ki*(pid.Ek+pid.Ek_1+pid.Ek_2)+pid.Kd*(pid.Ek-pid.Ek_1)+pid.OUT0;//PID公式
    pid.Ek_2=pid.Ek_1;
    pid.Ek_1=pid.Ek;
    pid.PIDOUT=PIDOUT;
    pid.PIDOUT=(pid.PIDOUT<pid.lowlimit) ? pid.lowlimit:(pid.PIDOUT>pid.uplimit) ? pid.uplimit : pid.PIDOUT;//输出限幅
    return pid.PIDOUT;返回位置信息
}
 

//内环控制(同样是增量式PID,若想改成位置式,稍加修改代码就可以)

float PID1_speedoutput ()
{
    float PIDOUT;
    pid1.Ek=pid1.Sv-pid1.Pv;
    PIDOUT=pid1.Kp*(pid1.Ek-pid1.Ek_1)+pid1.Ki*pid1.Ek+pid1.Kd*(pid1.Ek_2*pid1.Ek_1+pid1.Ek_2)+pid1.OUT0;
    pid1.Ek_2=pid1.Ek_1;
    pid1.Ek_1=pid1.Ek;
    pid1.PIDOUT+=PIDOUT;
    pid1.PIDOUT=(pid1.PIDOUT<pid1.lowlimit) ? pid1.lowlimit:(pid1.PIDOUT>pid1.uplimit) ? pid1.uplimit : pid1.PIDOUT;//输出限幅
    return pid1.PIDOUT;
}

上述代码两个环毫无联系,接下来要做的就是将内外环联系在一起做到内外环控制

 我们可以对这两个函数定义参数

对于第一个函数作为外环我们可以让入口参数为

float PIDwaihuan_output (Position,Target_position)//当前位置信息,目标位置信息

让该函数返回值为目标速度;

第二个函数作为内环控制我们可以使入口参数为

float PID1_speedoutput (Speed,target_speed)

返回值为电机pwm,

这就是简单的双环PID控制。

  • 7
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值