前言
考虑这样一个需求:有一辆小车,可以通过单片机控制 PWM 波的占空比 操控其电机转速,进而控制小车的速度。
我们让小车放在起点,然后设置一个目标位置,让小车直线运动,到达目标位置。
目标: 让小车自己控制车速,稳稳当当地停在目标位置。
一、问题分析
最简单的解决方案
首先我们想,如何让小车能够自己控制车速,停在目标位置?
最简单的解决方法是:
- 测量起点和终点的距离
- 给小车设置固定速度
- 算出运行时间,在时间到达时减速停止
存在的问题
| 问题 | 说明 |
|---|---|
| 距离成为输入项 | 需要我们自行考虑各种误差 |
| 误差作为已知量输入 | 这些误差会随环境等因素动态改变 |
| 变通性差 | 如果小车换了距离、换了地方,都需要手动调整参数 |
二、比例控制(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
- 《自动控制原理》
评论