写点什么

PID 控制算法理论学习基础——单级 PID 控制

作者:芯动大师
  • 2025-07-12
    四川
  • 本文字数:2083 字

    阅读完需:约 7 分钟

PID控制算法理论学习基础——单级PID控制

这是一篇我在学习 PID 控制算法的过程中的学习记录。在一开始学习 PID 的时候,我也看了市面上许多的资料,好的资料固然有,但是更多的是不知所云。(有的是写的太过深奥,有的则是照搬挪用,对原理则一问三不知)这一直让我对 PID 摸不着头脑。所以我打算从 0 开始去一层层学习它,直到自己掌握它的精髓。我不认为我有多聪明,所以相当多的部分我都写的很详细,觉得过于冗余的小伙伴可以跳着看。

我并不是计算机科学\电控类专业的学生,所以对知识的理解可能有不到位的地方,还请大家指正。

​最后,希望这篇长文对大家有所帮助,这也是我完成它的目标之一。

1.1 单级 PID 的原理理解

这里强烈建议还不理解 PID 基本原理的同学观看视频:https://www.bilibili.com/video/BV1xQ4y1T7yv

单级 PID 也就是只使用一个 PID 控制块。一般讲到 PID,大家都喜欢用调节洗澡水的水温来举例:

  • Kp(比例项),即希望调节到的温度与现在的温度差的越大,我们拧动加热旋钮的幅度就越大,这个差值越小,我们拧动加热旋钮的幅度就越小;

  • Ki(积分项),即 P 比例调节控制了一段时间之后,发现实际值与期望值还是有误差,那就继续拧懂加热旋钮,这是一个在时间上不断累积的过程,故为积分项;

  • Kd(微分项),当实际值与期望值的误差的导数,也就是水温变化的速度,这一项即控制达到期望值,即控制当前水温到达目标水温的速度。

然后将上面三项相加,就得到了基本的 PID 控制:

即下图

谈谈我对于 PID 控制的一些理解:


  1. 首先面对一个需要 PID 的控制系统的时候,增大 P(比例控制系数)可以使得系统的反应灵敏,但是相应地会无法避免地产生稳态误差并且单纯使用比例控制的系统无法消除这种误差;

  2. 在得到一个较为灵敏同时拥有较小的稳态误差的系统时,这时引入 I(积分控制项),积分控制可以有效地消除稳态误差,但是会使得系统达到稳态的时间延长,也是就是出现了震荡;

  3. 在 PI 控制完成之后,一般来说对于一些对时间不是很敏感的系统都已经拥有较好的控制表现了,对于时间要求苛刻的系统就需要引入 D(微分控制项)来进一步缩短系统达到稳态的时间(减少震荡);

  4. D 项的一个很不友好的特性就是对环境噪声极其敏感,引入 D 之后很容易就会使得先前已经稳定的系统突然变混乱起来,所以通常也需要较多的时间类来获取试验 D 的取值。

以上就是一个简单的 PID 控制系统的介绍。从实现来看,其实有着两种不同的实现方式,一种叫位置式 PID,另外一种则为增量式 PID。其中位置式 PID 我较少在平衡控制等项目中见过,而增量式 PID 则大量运用在电机的控制上(驱动平衡类项目),下面来简单说一下这两种 PID 控制的实现。

1.2 单级 PID 的代码实现

其中我们知道 PID 的公式如下:

但是我们会选用下面这个式子来进行实际的工程运用。可以看到除了积分变为累加之外(毕竟现实中数据都是一段一段不是连续的),D(微分项)中的形式变了,这是为了避免一个被称为“微分冲击”的现象,具体的原因在系列 3 中会有提到,这里可以暂时不去管它。

这里使用的是以 tank_like 模型(即四个电机的角度固定,靠转动的差速转弯的小车模型,与之相对的是 Car_like 模型,前面两个轮子可以偏转一定角度转弯)的四轮小车为例,需要控制其四轮转动同步(也就是能走直线)。

tank_like 模型与 Car_like 模型:


为了能够判断小车每个轮子的转动方向以及转动的幅度,需要使用带有编码器的电机,或者使用光电门也是同样的原理。这样就能获取到小车每一个轮子的实时速度值,与目标的速度 作差 后就是这个 PID 系统的输入。

​ 而小车上单片机向电机输入的 PWM 波(可以控制小车电机油门),就这个 PID 系统的输出。

如下图:


//位置式PID//定义所需要的变量float Kp, Ki, Kd;float Motor1_speed;//电机当前的速度float target_speed;//我们需要电机达到的速度float err_now;//当前速度与电机期望值的差,也就是当前的误差值float err_last;//上一次计算的误差值float err_Sum;//积分项,将累计时间内所有的误差值float output;//经过PID算法后输出的数据,其实是一个控制PWM占空比的参数,我们只需要直接放在输出PWM的函数里就好了
//PID算法err_now = target_speed -Motor1_speed;err_Sum += err_now;if(err_Sum > x) err_Sum = x;//这里需要设定一个极限值,以防积分变量溢出,其实一般来说并不会达到这个极限值,因为误差并不都是正数//没有对D进行操作output = Kp * err_now + Ki * err_Sum +Kd * (err_now - err_last);//PID公式if(output > x) output = x;//这里需要对输出也进行一个限制,这里倒不是限制溢出,而是PWM输出的参数本身就有最大值,超过了就无效了。TIM_SetCompare1(TIMx, output);//对产生PWM的定时器通道一进行输出err_last = err_now;//将使用完的当前误差值赋给上一次的误差值,进行下一轮循环
复制代码

增量式 PID 的原理就是不直接使用每一次 PID 产生的输出,而是将两次 PID 产生的输出相减,得到一个 PID 增量,再使用这个增量对系统进行输出。与位置式 PID 不同的地方就在于因为需要使用到前后两次的 PID 公式,那么也就需要当前误差、上一次误差与上上次的误差。在得到输出的增量之后就类似使用积分项一样直接将时间上的每一次增量相加,得到的结果在 TIM_SetCompare1()中输出就可以,代码就不赘述了。


发布于: 刚刚阅读数: 4
用户头像

芯动大师

关注

凡事预则立,不预则废! 2022-06-01 加入

某公司芯片AE工程师,嵌入式开发工程师,InfoQ签约作者,阿里云专家博主,华为云·云享专家,51CTO专家博主,腾讯云社区优秀共创官。

评论

发布
暂无评论
PID控制算法理论学习基础——单级PID控制_PID_芯动大师_InfoQ写作社区