前言

考虑这样一个需求:有一辆小车,可以通过单片机控制 PWM 波的占空比 操控其电机转速,进而控制小车的速度。

我们让小车放在起点,然后设置一个目标位置,让小车直线运动,到达目标位置。

目标: 让小车自己控制车速,稳稳当当地停在目标位置。


一、问题分析

最简单的解决方案

首先我们想,如何让小车能够自己控制车速,停在目标位置?

最简单的解决方法是:

  1. 测量起点和终点的距离
  2. 给小车设置固定速度
  3. 算出运行时间,在时间到达时减速停止

存在的问题

问题说明
距离成为输入项需要我们自行考虑各种误差
误差作为已知量输入这些误差会随环境等因素动态改变
变通性差如果小车换了距离、换了地方,都需要手动调整参数

二、比例控制(P)

核心思路

要让小车自己动态确定当前应该是什么占空比:

  • 目的: 让小车到达目标位置
  • 手段: 控制占空比

那我们就应该让小车能够实时根据当前所在位置计算占空比。

比例关系

小车离目标位置越远,应该有大速度;小车离目标位置越近,应该有小速度。

也就是说,离目标位置的距离与占空比成正相关。从简单思路思考,我们考虑是正比例函数关系:

输出 = Kp × 误差

其中:

  • 误差 = 目标位置 - 当前位置(有方向性)
  • Kp = 比例参数(Proportion)

Kp 参数的影响

Kp 值效果
过小响应速度较慢
过大由于惯性,会出现过冲现象

稳态误差问题

当小车以这样的算法获得电机转速后,理论上在初始获得大速度,在目标位置速度恰好为 0。

但是存在一个问题:

要让小车动起来,有一个 占空比的阈值。也就是说,并不是 PWM 波占空比从 0 变成 0.000000001,小车就能动起来的。

实际上,单片机输出给电机的 PWM 波的功率需要达到一个 最低阈值,电机才能够克服阻力让轮胎转起来。

结果: 小车在到达目标位置之前就会停下,因为输出 PWM 波的占空比与当前误差成正比例关系,在没达到目标位置时,PWM 占空比已低于启动阈值。


三、比例 + 积分控制(PI)

解决稳态误差的思路

方法一:添加静态偏置(不推荐)

从简单思路也就是正比例函数入手,可以尝试稍微提升一点,使用线性函数,也就是添加一个常数,用于静态偏置:

输出 = Kp × 误差 + 常数

根据当前环境情况、小车情况,添加一个固定的常数,以消除稳定某个平衡点时需要克服的静态输出。

问题: 这个常数仍然受环境因素、器件误差等因素动态变化,我们仍然希望能让小车自适应这些因素的变化。

方法二:引入积分项(推荐)

对于稳态误差的本质,是动态环境因素、器件误差等因素带来的影响。要想让小车自己适应不同环境下的这些影响,就要把它们考虑到公式里面,用一个小车能够自己采集的量进行表述和引入。

积分量的物理含义: 误差在时间上的累积。

积分项的作用

积分量的作用是记录之前的误差总和,并借此来影响 PWM 波占空比的输出。

为什么之前误差的总和有这么个作用?

理解起来很简单:在小车到达目标位置之前停下时,之前误差在时间上的累积都是正向的。所以这个影响会导致此时也输出一个较高的 PWM 波占空比,从而推动小车继续前进。

PI 控制公式

为了让这个积分量与 PWM 波形的占空比输出成正相关,我们引入一个 Ki 参数:

输出 = Kp × 误差 + Ki × 积分量

其中 i 是积分的含义(Integration)。

积分项带来的新问题

这样确实解决了小车停于目标位置之前(稳态误差/静差)的问题,但实际上也引入了新问题:

问题原因解决方案
过冲现象积分项累积导致限制积分项上限
积分饱和单向误差累积越来越大抗饱和处理

积分饱和的解决

通过对 Ki 参数的控制,可以限制积分项对整个式子的影响。

但这也带来一个问题:在最后这点距离时,积分项成为超越比例因素的重要影响因素是必然的(因为比例因素在误差小的时候影响已经很小了)。

于是小车就会出现 冲过目标位置 的情况。然后由于此时有了反向误差,比例因素重新成为主导,让小车退回来。

震荡过程:

冲过目标位置 → 反向误差产生 → 比例项主导退回 → 
积分项仍为正向 → 退回距离比原来近 → 往复震荡 → 最终停在目标位置

⚠️ 虽然这样的震荡似乎可以接受,但在某些场景(如无人机定高飞行)是致命的。


四、比例 + 积分 + 微分控制(PID)

解决震荡问题

如何解决反复震荡的问题?

核心: 解决小车冲过头的问题

为了解决冲过头的问题,应该添加一个 抑制因素——抑制小车以大速度超过目标位置的因素。

微分项的引入

可以理解的是,我们可以引入一个 微分量。这个微分量是对误差在时间上进行微分。

我们知道,误差就是目标位置与当前位置的距离,那么对其在时间上进行微分实际上就是 对误差变化速率的一种表述

也就是说,微分量反映的是误差变化的快慢

微分项的作用

比如说,小车即将穿过目标位置的时候:

  • 虽然比例项的影响很小
  • 在积分项的主要影响下,小车趋向于高速冲过目标位置
  • 此时就会产生较大的误差变化率

微分项的逻辑: “我不管你误差是在减小还是增大,减小多少,增大多少,我只关注你是不是有大变化。有了大变化,我就抑制你的这种变化。”

微分项会对积分项过冲的行为进行抑制,从而减轻震荡幅度和震荡次数。

微分项实际上就是根据误差的变化率来预测误差的变化趋势,并抑制这种趋势。

关于启动时的疑问

问题: 在刚开始出发时,小车速度不是很大吗?此时的误差变化率不是最大的时候吗?此时微分项不会过于抑制比例项的作用吗?

解答:

为了让微分量能够影响到 PWM 输出波的占空比,我们给它加上一个 Kd 参数,让它与其成正相关:

输出 = Kp × 误差 + Ki × 积分量 + Kd × 微分量

Kd 参数的调节:

情况现象调整方向
Kd 过大小车迅速加速后迅速减速,出现加速 - 减速循环调小 Kd
Kd 过小微分项作用不足,过冲明显调大 Kd

理想效果:

  • 出发时:受比例因素主导,加速
  • 加速后:受到微分项作用略微减速
  • 到达最后要过冲时:积分项进行抑制
  • 最终维持非常好的控制效果

微分项的其他特性

好处:提高初始响应

系统启动时,代码里面初始化的误差往往是 0。在获得初始误差的瞬间,误差会从 0 突然增大到某个值。

此时误差的变化率为正,所以微分项会产生很大的正向影响,提高系统的响应速度

弊端:对噪声敏感

微分项对噪声极其敏感。生活中的音频噪音往往是十分尖锐的波形,也就是说其斜率非常大。

而微分项实际上就是误差变化率的一种表述(斜率的表述)。倘若有噪声影响到了微分项,会对其造成比较大的影响。

Kd 中的 d 的含义是微分(Differential)


五、PID 算法完整公式

标准形式

输出 = Kp × 误差 + Ki × 积分量 + Kd × 微分量

各项作用总结

公式作用影响阶段
比例项Kp × 误差根据当前误差调整输出全程主导
积分项Ki × 积分量消除稳态误差误差小时主导
微分项Kd × 微分量抑制过冲,减轻震荡误差变化大时主导

影响方向

在由起点到目标位置的过程中:

  • 比例项积分项:对输出施与正向影响
  • 微分项:起到负向影响(因为此时误差变化率是负的,误差在减小)

六、数字实现

离散化处理

由于计算机系统是按照周期执行指令的,单片机无法真正意义上的积分和微分:

运算数字实现方式
积分量每一次误差的求和进行近似
微分量相邻误差的差值(差分)进行近似

采样周期的影响

采样周期影响
过短计算压力大
过长控制不准确

七、参数整定

参数重要性

PID 算法中的三个参数 Kp、Ki、Kd 的合适选值非常重要,直接影响到了控制系统的效果。

调参方法

方法说明
手动调参法根据经验手动调整
试错法反复试验找到合适值
齐格勒 - 尼科尔斯法Ziegler-Nichols 方法
临界比例度法找到临界振荡点
响应曲线法根据系统响应曲线调整
衰减曲线法根据衰减比调整

八、增量式 PID

上述内容讲解的是 位置式 PID 算法

还有一种 增量式 PID 算法:将上述式子写出第 K 次和第 K+1 次的输出,相减得到的式子。


总结

PID 算法通过比例、积分、微分三个环节的协同作用,实现了对系统的精确控制:

  • P(比例):响应当前误差
  • I(积分):消除历史累积误差
  • D(微分):预测未来误差趋势

三个参数需要根据具体应用场景进行整定,才能获得最佳的控制效果。


参考资料

  • Ziegler, J. G., & Nichols, N. B. (1942). Optimum settings for automatic controllers
  • 《自动控制原理》