本文链接:https://blog.csdn.net/weixin_42881419/article/details/86551249
PID算法 是控制算法中的经典算法,特别是在一个闭环控制系统中更为常用。自己曾是第十三届全国大学生“恩智浦”杯智能汽车竞赛的参赛选手,相信所有的选手在电机控制算法上大多都是用PID算法,本想好好使用这种算法,却无奈没有学过。而网上查阅资料却又是基本都是一些苦涩难懂数学公式和脍炙人口的一些PID语句,对于刚接触PID算法的人而言无异于天书。所以写此文章,意在用于分享自己对于PID算法的理解,希望可以帮助同样与我曾经有相同困惑的人排除困惑。注:本文是自己通过查阅书籍和观看视频学习而得,若有错误,欢迎批评指正。
控制系统有几种分类方法,其中,按控制原理的不同,自动控制系统分为开环控制系统
和闭环控制系统
。
在开环控制系统中,系统输出只受输入的控制,控制精度和抑制干扰的特性都比较差。
闭环控制系统利用输出量同期望值的偏差对系统进行控制,可获得比较好的控制性能。闭环控制系统又称反馈控制系统。
由图中可以很明显的看出,此控制系统比开环系统多了一个环节——传感器,通过传感器进行 采集和反馈 到控制算法中,形成一个 闭合的回环 这也就是闭环控制系统中的闭环。
PID算法
是将偏差
的比例( P roportion)
、积分( I ntegral)
和 微分( D ifferential)
通过线性组合构成控制量,用这一控制量对被控对象进行控制,这样的控制器称PID控制器。
简单来说,偏差
= 用户设定的期望值
— 传感器采集回来的当前值
,将偏差进行P、I、D
三个环节的计算,再进行求和、输出
。
二位式控制算法在某种程度上可谓是PID算法的前身,了解原理便可更好的理解PID算法。
二位式控制算法输出的控制量只有高 \ 低 电平
2种状态。我们以烧水为例:假设我们要求此控制系统要将水加热到100℃,当传感器采集反馈回的当前值 没有达到期望值
(100℃),便全高/低电平加热;当传感器采集反馈回的当前值达到期望值
(100℃),便停止加热。
一个简单的控制系统这么设计看似毫无问题,然而,由于我们的控制对象具有惯性
,例如我们控制加热丝烧水,当我们达到指定温度停止加热
的时候,加热丝不会马上冷却下来
,水温还会继续升高,超过指定温度;而过了一会儿,水温冷却下来低于指定温度时,给加热丝通电,加热丝也无法立刻把温度升上去
。由于我们的控制对象(加热丝、电感、电容、电机等)具有惯性
,而二位式控制算法的输出量只于当前状态有关
,故很难达到精确控制
。
eg:电机就是一个 具有惯性的对象,给他施加电压,不能马上转到对应的速度;撤去电压,电机也不能马上停下。
由于惯性环节的存在,会使控制对象超出期望值。
我们规定:用户期望值为 Expect,每隔一个固定时间对控制对象进行信息采样Xn,在此基础上,我们在三个环节中介绍三个序列。
P(比例)环节:对当前时刻的偏差进行比例放大。
u(k)=Kp * e(k)
。I(积分)环节:对过去所有时间的偏差进行积分。
u(k)=Ki * ∑ei
。(Ki:i比例系数)在控制系统刚启动时,由于I环节的 偏差累积效应,可以 更快的达到期望值。但同时也由于偏差的累积效应,使得系统第一次达到期望值时,过去所有时刻都未达标,即∑ei很大,所以曲线其实会超过期望的那条虚线并持续增长,所以,我们通常会在I环节中除以积分时间Ti,即u(k)=Ki * ∑ei/Ti
另一个解决办法 我们后面在增量式算法中再进行讨论。
D(微分)环节:通过偏差的偏差,对控制系统的输出走向进行预判,起超前调节的作用。
△ek=ek-ek-1
;u(k)=Kd * △e(k)
。位置式PID:u(k)=Kp * e(k)+Ki / T * ∫ e(k) dt+Kd*d e(k);
增量式PID:u(k)=Kp * e(k-1)+Ki *e(t) +Kd *(e(k)-2e(k-1)+e(k-2));
很显然,对位置式PID进行求导(dx = f(x) - f(x-1)),就得到了增量式PID。
对于前面谈到的,位置式PID的 I 环节,是对过去所有时间
的偏差进行积分,其输出与过去所有时间都有关,而增量式的PID只于最近的三个时刻
的偏差有关。
其实,增量式PID我觉得也没有很多需要理解的,自然而然的代入应用即可。
//电机控制 增量式 P I 算法
Err_speed=Expect_speed-actual_speed;
Err_dev_speed=Err_speed-Err_speed_last;
Err_speed_last=Err_speed;
gradinets=(int) (PID_P*Err_dev_speed+PID_I*Err_speed);
float PID_Cal(float Speed)
{
pid.SetSpeed = Speed;
pid.Err = pid.SetSpeed - pid.ActualSpeed;//误差的计算,即比例控制
pid.Integral += pid.Err;//误差相加,即积分控制
pid.Voltage = pid.Kp * pid.Err + pid.Ki * pid.Integral + pid.Kd *
(pid.Err - pid.Err_last);//根据位置型PID控制的公式
pid.Err_last = pid.Err;
pid.ActualSpeed = pid.Voltage * 1.0; //转换
return pid.ActualSpeed;//PID控制后的实际输出值
}
(ノ´▽`)ノ♪ 终于写到了这里了 (╬ ̄皿 ̄)=○ 实不相瞒,这篇陆陆续续写十天了,要写疯了? ಠ_ಠ 不想写了,我觉得没人有耐心看到这里了 ▄█▀█● 不写了直接放文档吧,以后有心情了再更一篇[我鸽了,时隔这么久我还是没写?,要比较全面的了解一个东西,写一篇文章太难了] (╬◣д◢) 我不会放文档进来啊啊啊啊 (づ ̄3 ̄)づ╭❤~ 别忘了一件三连鸭?