比例积分微分(PID)控制器以及比例(P)、比例积分(PI)和比例微分(PD)等较简单的控制系统已伴随我们很长时间。比例控制可追溯至18世纪詹姆斯·瓦特为蒸汽机设计的机械飞球调速器。这种基础机械自动化系统与最新的微控制器或可编程逻辑控制器(PLC)解决方案具有共同特性——所有实现方案都会监测受控设备或流程(自动化控制文献中称为"被控对象")的输出并作出响应。这是一个抑制性负反馈过程。若反馈丢失,被控对象将满负荷运行,存在灾难性故障风险。
PID 控制器简介
我们将探讨如图1所示的伺服电机PID应用。该机构基于PORTENTA Pro C33微控制器和PORTENTA扩展板构建。系统还包含Pololu #4754直流电机和Seeed MDD3A电机控制器。这套组合为研究P、PI、PD及PID控制器提供了绝佳测试平台。这是一个响应迅速且输出可被人观察的系统。在系统开发和调试过程中,我们可以听到、看到并感受到电机的响应。
图 1 :基于伺服电机的PID控制器测试平台,包含Arduino C33、PORTENTA扩展板、Seeed MDD3A电机驱动器和Pololu 4754有刷直流电机。
视频 1 :运行中的伺服电机完成完整旋转后返回起始位置。
技术提示 :PID是统称术语。简单比例控制、比例微分(PD)或比例积分(PI)等较简单的控制器通常被归类为PID控制器的子类。通过将相关增益值设为零来禁用未使用功能,可轻松将PID控制器转换为P、PI或PD控制器。例如,将D增益设为零即可将PID控制器转换为PI控制器。
作者撰写本文的动机
约20年前,我曾在《Nuts & Volts》杂志发表过三篇关于PID的文章。回首看来,我认为那是不错的尝试。但此后,我有机会将PID应用于许多不同场景,包括一些不太明显的应用。更重要的是,我曾指导过许多成功的学生项目。这是个艰难的学习过程,因为它融合了来自多门课程的理念。完成控制理论课程并学习PID及相关数学密集型控制器是一回事。将这些想法实现到一个响应式的现实系统,尤其是带有微控制器所有约束和复杂性的嵌入式系统中,是一种截然不同的体验。
本简报作为控制系统与微控制器主题融合的起点。它偏向于让系统简单运作的实用层面。一旦系统开始运行,并通过经验性调整PID增益和时序参数积累了一些经验,你就可以回头探索数学原理。最终成品如视频1所示。此处伺服电机完成单圈旋转后返回初始位置。
本文 PID 目标
自P、PI、PD和PID控制器最初问世以来,已有数千本相关书籍和文章问世。很可能你已经读过其中一些文章,现在正寻求实现项目并提升其稳定性的实用建议。本工程简报不再重复陈旧的理论内容,而是聚焦PID控制器的实际应用。为方便起见,我们基于您对Arduino微控制器的基础知识,简要探讨FreeRTOS以协助将PID集成到大型生态系统中。
本文具体目标如下:
- 提供偏向教育导向的PID代码框架。例如,将各个PID增益元素以百分比形式探讨。
- 提供可观察各PID分量贡献的实时界面。
- 对各PID分量贡献设置限制。例如,这能让D分量在通常被P分量掩盖时仍可被观察到。
- 基于Arduino教育基础,再将应用扩展至运行在先进硬件上的实时操作系统。
- 展示采用现代高性能微控制器(如主打以太网和蓝牙功能的Arduino PORTENTA C33)的原型设计技术。
- 利用多任务FreeRTOS的灵活性
总之,我们避开已有详尽记载的PID理论,专注于通过交互式经验调谐实现稳健系统。该技术将助您透彻理解PID,从而设计、调试并排查控制系统问题。
请注意DigiKey技术论坛已发布多篇先决文章。请务必查阅这些文章,它们构成本简报至关重要的基础。从现在起,我们假定您已熟悉以下主题:
运动与控制
- 设计一个基于 Arduino 电机控制的稳健正交编码器 ISR 程序
- 逆向工程 Arduino Nano Every 以更改 PWM 频率
- Arduino 控制四线风扇
- 使用 MDD3A H 桥控制有刷直流电机,结合 FreeRTOS 和 Arduino C33
Arduino PORTENTA Pro
- Arduino PORTENTA Pro C33 的 FreeRTOS
- Arduino PORTENTA Pro C33 的高级 PWM 功能
- Arduino PORTENTA Pro C33 的高速中断、FreeRTOS 和 ARM NVIC
技术提示 :PID控制器可设计为具有高程序效率,适合在8位微控制器上运行。例如,该程序可优化为使用快速整数运算而非浮点计算。本文介绍的PID未作优化尝试,因其完全采用浮点数运算。这种偏向教育的实现方式通过采用带浮点运算单元(FPU)的强大现代32位微控制器得到缓解。
PID 控制器有何用途?
比例积分微分(PID)控制器是广泛使用的过程控制算法。术语"过程"描述为在某个稳定设定点长期或连续运行而设计的系统。常见例子包括调节水压、保持恒温或维持机器恒定转速。
PID概念延伸至专用硬件模块,这些模块可以是模拟或数字形式。也可指运行在微控制器或可编程逻辑控制器(PLC)上的代码。本文将重点探讨PID的软件实现及配套微控制器架构。如有需求,我们后续可研究工业级PID硬件模块或PLC软件实现方案。
PID 控制器有哪些输入输出?
如图2所示,PID控制器具有两个输入和一个输出。输入包括被控对象当前位置(反馈)与目标位置(设定点)的模拟量。输出用于控制被控对象,最小化反馈信号与设定点信号的差值。理想情况下被控对象将精确跟随设定点。现实中这并非易事,尤其当物理对象具有动能和势能时。
经典 PID 算法如何运作?
PID控制器是可通过模拟电路或数字方法实现的数学模型。顾名思义,核心算法由三种数学运算组合而成:
-
比例项——根据被控对象测量值与设定点偏差进行控制。误差越大,校正控制动作越强。从时间维度看,比例项作用于当前时刻。
-
积分项——基于误差时间积分的控制动作。微小误差随时间累积会导致大幅控制动作。从时间维度看,积分项作用于历史信息,因为我们累积了所有过往误差。某种程度上,积分项类似低通滤波器,对噪声相对不敏感。
-
微分项——基于变化速率的控制动作,反映被控对象输出的变化快慢。微分项作用与比例积分项相反。被控对象快速变化时,系统会产生大幅控制动作以减速。从时间维度看,微分项作用于未来——快速变化的系统即将越过目标值。某种程度上,微分项类似高通滤波器,对噪声和时序抖动极为敏感。
经典PID算法如图2所示。注意P、I、D各项均基于误差计算。其中误差为设定值与对象反馈值之差。P、I、D各项的强度由对应系数kP、kI、kD决定。最终将P、I、D各项组合生成对象驱动信号。
图 2 :传统(学术型)PID控制器框图。P、I、D各项基于误差信号(设定值与反馈值之差)。
核心PID运算可用这段C代码片段描述。为清晰起见,省略了变量声明及存取方法。可见该代码直接对应图2框图。
技术提示 :如图2时钟所示,采样PID控制系统存在隐含的时间要素。下文所示PID更新方法必须定期调用。例如电机控制系统可能需要每10毫秒更新一次。时间间隔波动会表现为噪声,降低PID控制器的微分性能。
float PIDController::update(float feedback) { // Must be called at regular time intervals
error = setpoint - feedback;
P = error * kP; // now
I += error * kI; // backwards looking accumulation of all previous errors
D = (error - last_error) * kD; // forward looking based on current trend (slow down a fast moving system)
last_error = error;
PID_output = P + I + D;
return PID_output;
}
学生读者或可通过时域方程和离散时间方程识别PID。传统PID方程如下(不作解释):
u(t) = K_p \cdot e(t) + K_i \cdot \int_{0}^{t} e(\tau) \, d\tau + K_d \cdot \frac{d}{dt} e(t)
u[k] = K_p \cdot e[k] + K_i \cdot \sum_{i=0}^{k} e[i] \cdot \Delta t + K_d \cdot \frac{e[k] - e[k-1]}{\Delta t}
我们刚刚探讨了描述传统PID控制器的多种方式。尽管这些描述都真实有效,但对于实际应用中遇到的非线性系统响应和噪声问题,其作用有限。例如,在理想系统中,关联装置可能响应无界的PID指令提供无限功率。实际上,诸如脉宽调制(PWM)驱动的电机控制器等设备受限于物理饱和极限——一旦PWM达到100%,系统就无法再增加功率。噪声是所有反馈测量系统中不可避免的属性,包括本文所介绍的增量编码器。PID更新时间的变化也会引入噪声。
如何改进传统 PID 控制器以提升实际响应?
一个响应迅速的实际PID控制器包含防止积分和微分项相关问题的代码或电路。如图3所示,这包括防止积分饱和的机制、可预测的限制器、直接从反馈获取的微分输入,以及微分输入的低通滤波器。
在继续讨论之前,请注意每个限制器模块被设置为+/-100。因此,我们可以用百分比来讨论P、I和D项的贡献。例如,我们的伺服电机驱动装置可以100%顺时针或逆时针运转。如果发出大幅移动指令,如顺时针方向10圈,P分量将立即饱和并驱动装置100%顺时针运转。
图 3 :实用的改进PID控制器包含针对P、I和D分量的饱和限制模块。包含锁定机制以防止积分饱和。D项还配有低通滤波器(LPF),其输入直接来自反馈以防止微分冲击。
什么是积分饱和?
积分饱和是一种不良状态,积分项会累积至较大值。举例来说,假设伺服电机设定点改变,指令顺时针移动10圈。这样的运动需要几秒钟完成。若不干预,积分项会持续累积(积累大误差),可能增长到远超100%的驱动量。这将导致系统不稳定,在达到最终值前长期振荡——甚至可能无法稳定。
积分器后的饱和模块会将最大值限制在100%。这有所帮助,但超调和振荡仍存在。锁定模块在系统因P项饱和时阻止累积过程,从而起到作用。换句话说,I分量被冻结,直到电机接近指令设定点。组合作用显著减少了超调量,从而缩短了稳定时间。
什么是微分冲击?
微分冲击是指当PD或PID控制器的设定值改变时产生的不良微分作用。回顾图2可见微分项基于误差,而图3显示其与反馈信号本身相关联。在第一种基于误差的情况下,设定值的大幅变化会导致D项贡献量剧烈变化(冲击)。改进后的反馈方案使微分贡献完全由被控对象决定,对设定值变化无冲击响应。
图3还为微分项加入了低通滤波器(LPF)。这是个简单的滑动平均滤波器,用于消除噪声。包括测量过程中的噪声,以及采样过程引起的抖动噪声。配置该滤波器是调谐过程的一部分,需选择参与平均计算的样本数量。
响应式 PID 控制器代码
改进版PID的代码如本清单所示。注意饱和模块通过fLimit()函数实现。这将P、I、D各项的贡献限制在±100范围内。积分锁定是基于P项的初步检查。若P项饱和,则积分项保持当前值。微分项由反馈信号驱动,并采用包含DSamplesAveraged的滑动平均滤波器。
float PIDController::update(float feedback) {
error = setpoint - feedback;
lastSetpoint = setpoint;
P = error * kP;
P = fLimit(P, -100.0, 100.0);
if(fabs(P) != 100) {
I += error * kI;
} else {
; // Hold on I if the P term is saturated.
}
I = fLimit(I, -100, 100);
float runAvgFeedback = runningAverage(feedback, DSamplesAveraged);
D = ( runAvgFeedback - last_feedback) * kD;
D = fLimit(D, -100, 100);
last_feedback = runAvgFeedback;
PID_output = P + I - D;
PID_output = fLimit(PID_output, -100, 100);
return PID_output;
}
最后的思考
本系列后续文章将深入探讨改进版PID代码及配套微控制器结构。我们还将回溯并补充控制系统相关的必要术语。这将有助于更好地理解稳定性。
请在下方留下您的评论和建议。虽无法保证,但我会尝试在后续文章中解答各位的问题。
请点击此链接获取相关Arduino教育内容。


