引言:PID(Proportional-Integral-Derivative)控制算法作为经典的控制理论,广泛应用于工业自动化、嵌入式系统以及各种动态控制场景中。它以简单有效的结构和强大的适应性成为自动控制领域的重要工具。无论是无人机的姿态控制、平衡小车的动态稳定,还是温控系统中的精确调节,PID 都能通过调节比例(P)、积分(I)和微分(D)参数,帮助实现精准的目标追踪与稳定控制。
本教程从基础理论到实际项目,系统性地讲解 PID 控制的原理及其实现方法,帮助读者快速入门并掌握调参技巧与实战应用。通过结合具体案例(如无人机和平衡小车),读者不仅能理解 PID 的数学意义,更能将理论应用于工程实践中。我们还提供了从代码实现到多环协同的全流程讲解,使本教程成为 PID 学习的全方位指南。
目录
一、PID是什么?
1.PID的引入
我们想象一个场景,当一个坦克,我们希望此坦克沿着前进方向移动100m,控制程序应该如何编写呢?或许你会觉得非常简单,不就是一行驱动电机的代码吗?让机器人全速前进100m,也就是路程=速度/时间,只需要代码编程为驱动电机的时间即可完成上述任务,可是现实真的如此吗?我们设想如果地面不平坦呢?或者是阻力因素,电机发热导致驱动问题等等一些列的因素,以至于上述所设想的代码落地实现向前前进100m实际并没有到达100m,这种问题我们该如何解决?此时我们引入PID。
2.开环和闭环
PID控制算法是自动控制领域常见的一种控制策略,广泛应用于各种工业自动化系统。PID是比例-积分-微分(Proportional-Integral-Derivative)的缩写,控制器根据这三项的加权和来调整控制量,使系统稳定地达到预定目标。
在控制系统中,我们通常可以分为开环控制和闭环控制两种类型。接下来,我将详细解释它们在PID控制中的应用和实现。
开环控制
开环控制是指控制系统的输出不反馈给控制器。在开环控制系统中,控制器仅根据设定的输入(参考值)输出控制信号,并不考虑系统的实际输出(即没有反馈)。这种控制方式在系统行为比较简单且不容易受扰动时可以使用,但对于复杂的、容易受外界因素干扰的系统,开环控制会面临很大的局限性。
闭环控制
闭环控制(也叫反馈控制)是指控制系统的输出信号反馈到控制器,并根据反馈结果调整控制量。闭环控制的核心思想是系统会持续调整输出,以确保误差最小化。PID控制器正是通过反馈机制调整其输出。
因此我们对于上述的概念有了掌握之后,回到引入时的问题,我们第一次设计的代码就是开环了。
由于我们需要解决我所说的阻碍到达理想目标值的问题,因此我们需要用闭环控制!
如下就是开环控制与闭环控制的总结对比表格了。
特点 | 开环控制 | 闭环控制 |
---|---|---|
反馈 | 无反馈,输出不依赖于反馈信号 | 有反馈,控制器根据反馈调整输出 |
适应性 | 适用于简单、稳定的系统,无法应对扰动 | 适用于复杂、受扰动的系统,有较好的适应性 |
控制精度 | 精度较低,因为无法修正误差 | 精度较高,因为能根据误差调整控制信号 |
实现复杂度 | 实现较简单,不需要反馈机制 | 实现较复杂,需要处理反馈信号、误差等 |
计算量 | 较小,仅基于输入进行控制 | 需要处理比例、积分和微分,计算量较大 |
3.闭环控制的实现方式
此时我们着重的理解闭环控制以及实现方式,闭环控制是指通过将系统的输出信号反馈到控制器中,并根据输出与目标之间的误差调整控制信号。PID控制算法是实现闭环控制的经典方法。以下是闭环控制的常见实现方式。
闭环控制系统通常包含以下几个基本部分:
- 设定值(Setpoint):系统希望达到的目标值。
- 测量值(Process Variable, PV):系统的实际输出(通过传感器或测量设备获得)。
- 误差(Error):设定值与测量值之间的差异,通常定义为:
- 控制器:根据误差计算控制信号,通常采用PID控制器。
- 执行器(Actuator):接收控制信号并调整系统输入(如电机、阀门等)。
- 反馈回路:将测量值反馈给控制器,形成闭环控制。
在闭环控制中,PID控制算法是最常见的控制方法,结合了比例(P)、积分(I)和微分(D)三部分。其基本思想是,通过综合考虑当前误差(P项)、过去的误差积累(I项)和误差变化的速率(D项)来生成控制信号。
闭环控制的第一步是获取系统的实时输出。通常通过传感器来测量系统的状态或输出变量(例如温度、位置、速度等)。然后将该值与设定值进行比较,计算误差。
误差是系统目标值与实际测量值之间的差异。在PID控制中,误差是控制信号计算的基础。
// 误差计算
float error = setpoint - actual_value;
具体流程:设定值 (Setpoint)->测量值 (Process Variable)->误差 (Error)->PID控制器 (P + I + D)->控制信号 (Control Signal)->执行器 (Actuator)->反馈至系统输出,更新测量值。
其中 控制信号 (Control Signal)需要反馈给 测量值 (Process Variable)。
4.适用系统
PID控制器通常适用于线性系统,但并非所有应用场景下的系统都严格是线性系统。具体来说,PID控制器在一些近似线性的系统中表现得非常好,尤其是在系统的输入和输出之间存在一定的线性关系时。然而,对于某些复杂的系统(特别是具有强非线性特征的系统),PID控制可能需要进行调整或与其他控制方法结合使用。
通俗易懂的来说线性系统的例子:
- 电动机的速度控制
- 温度控制系统
- 简单的液位控制
准确来说适用于二阶以内段线性系统。
所谓二阶段以内线性系统,一般指的是具有两阶段动态行为的系统,并且这些行为仍然可以用线性模型描述。例如,某些系统可能存在一个初始的快速响应阶段(如开环操作阶段)和一个稳态响应阶段(如闭环控制阶段),但这两个阶段的动态行为可以通过线性方程来建模。
在这种情况下,PID控制器仍然可以适用,但需要针对每个阶段的动态特性进行适当的调节。例如,初始阶段可能需要较高的比例增益以快速响应,而在稳态阶段则可能更侧重于积分和微分控制以减小稳态误差和抑制振荡。
二阶段线性系统的例子:
- 电力驱动系统:电动机从启动到稳定工作,电流和速度变化的阶段。
- 机械系统:如某些自动化装置在启动时的响应阶段与其稳定运行阶段。
- 温控系统:初始加热阶段与最终温度稳定阶段。
PID控制在非线性系统中的应用(了解!!!)
尽管PID控制器最适用于线性系统,但在一些非线性系统中,它仍然可以发挥作用,特别是在非线性特性不强的情况下。在很多实际应用中,系统的非线性行为通常仅在某些操作范围内出现,因此,通过适当的线性化处理或调整PID参数,PID控制器也能处理一些弱非线性系统。
例如,某些温控系统和电机控制系统虽然在实际运行中表现出一定的非线性特征,但PID控制器仍然能够通过局部线性化(即在特定工作点附近)进行有效控制。
非线性系统中的PID调整:
- 增益调度:在不同的操作点使用不同的PID增益。
- 非线性补偿:引入外部模型来补偿系统的非线性部分。
二、PID的数学表达式及含义
1.从连续到离散的转换
先直接给出下述连续到离散的PID公式,你可能一脸懵了,我们接下来会解析每个参数。
PID控制器通过比例(P)、积分(I)和微分(D)三个部分共同作用来调节控制信号。其数学表达式如下:
连续时间PID控制器的表达式:
- u(t) 是控制器的输出(控制信号),通常是用来调整系统输入的量(如电压、流量等)。
- e(t)=r(t)−y(t)e(t) = r(t) - y(t)e(t)=r(t)−y(t) 是误差,即设定值 r(t)r(t)r(t) 和实际输出 y(t)y(t)y(t) 之间的差值。
- KpK_pKp 是比例增益,决定系统对当前误差的响应强度。
- KiK_iKi 是积分增益,决定误差积累对控制信号的影响,用于消除稳态误差。
- KdK_dKd 是微分增益,决定误差变化率对控制信号的影响,用于减少系统的振荡。
离散时间PID控制器的表达式:
在数字控制系统中,PID控制器通常需要转换为离散形式。离散时间PID控制器的表达式为:
- u(k) 是离散时刻 kkk 时的控制输出。
- e(k)=r(k)−y(k)e(k) = r(k) - y(k)e(k)=r(k)−y(k) 是离散时刻 kkk 的误差。
- KpK_pKp 是比例增益。
- KiK_iKi 是积分增益。
- KdK_dKd 是微分增益。
- Δt\Delta tΔt 是采样时间(即离散时间步长)。
从连续到离散的转换:
-
比例项(P):在离散时间中,比例项 Kpe(k)K_p e(k)Kpe(k) 保持不变,直接使用当前误差。
-
积分项(I):连续时间中的积分操作 ∫0te(τ)dτ\int_0^t e(\tau) d\tau∫0te(τ)dτ 转换为离散求和,表示为误差的累积,即 ∑i=0ke(i)Δt\sum_{i=0}^k e(i) \Delta t∑i=0ke(i)Δt。
-
微分项(D):连续时间中的微分操作 ddte(t)\frac{d}{dt} e(t)dtde(t) 转换为离散差分,表示为当前误差和上一时刻误差之差除以采样时间 Δt\Delta tΔt。
- 连续PID控制器使用误差、误差积分和误差微分的连续形式。
- 离散PID控制器则通过误差的累加和差分实现相同的功能,适用于数字控制系统中。
2.PID调参是调什么?
因此通过上述的公式后,我们着重观察Kp,Ki,Kd这三个参数,因此调的话也是针对这三个参数了,但是我们也不需要每个闭环控制都需要涉及到这三个参数,这三个参数的作用我们后续也会一一讲到,我们目前只需要知道我们需要调的是这三个参数即可!
PID调参主要是调节比例增益、积分增益、微分增益,以便优化系统的响应速度、稳定性、精确度和抑制振荡。
3.P算法含义和作用讲解
比例增益 KpK_pKp
- 调节内容:比例增益 KpK_pKp 控制系统对当前误差的响应强度。增大比例增益会使系统对误差的反应更迅速。
- 调节目标:提高响应速度,减小稳态误差。
- 效果:
- 过低的 KpK_pKp:系统响应缓慢,可能无法快速纠正误差。
- 过高的 KpK_pKp:可能导致系统的过冲(超调)和振荡,甚至不稳定。
4.D算法含义和作用讲解
微分增益 KdK_dKd
- 调节内容:微分增益 KdK_dKd 控制系统对误差变化速率的响应。它通过预测误差的变化趋势来提前做出调整。
- 调节目标:减少系统的振荡、过冲和不稳定性,改善动态响应的平稳性。
- 效果:
- 过低的 KdK_dKd:可能导致系统响应较为迟缓,产生较大的过冲或振荡。
- 过高的 KdK_dKd:可能导致系统对噪声过度敏感,产生不必要的波动。
5.I 算法含义和作用讲解
积分增益 KiK_iKi
- 调节内容:积分增益 KiK_iKi 控制系统对历史误差的积累响应。它通过累计误差来消除系统中的稳态误差。
- 调节目标:消除稳态误差,确保系统最终达到设定目标值。
- 效果:
- 过低的 KiK_iKi:系统可能存在稳态误差,即输出无法准确达到设定值。
- 过高的 KiK_iKi:可能导致系统的响应过度,出现过冲、振荡或慢速响应。
三、模拟调参-无人机案例
1.从模拟调参中理解P、I和D的含义和作用
我们观察下述的实际案例,你会解决上述的参数疑惑,以及调参顺序,如下所示:
可以看出来上述无人机在没有加入PID控制算法时,目标值与实际值有着非常大的差距。
加入P参数!所以第一个步骤就是:误差越大,升力就要越大,这是一个线性关系,所以升力F=0.01*error误差值,这个就是P算法,proportional(比例的缩写) ,其中这个Kp就是0.01,这个Kp越大,升力跟误差的比例就越大,其实也就是 F * 1 = error * Kp,控制系统的响应速度越快,在接近高度目标时,产生的震荡越严重,所以并不是越大越好。震荡的原因是:升力跟误差成正比,误差为0,升力也会0,加速度为0,可是速度不为0,因为V是状态量时刻内不可能立马减为0,会继续上升,导致震荡。
加入D参数!为了解决系统震荡的问题,引入第二个步骤,PID算法中的D,Derivative微分算法的缩写,因为我们在一中用的是error距离误差,所以对距离error求微分,结果就是速度,因为速度就是物体位置随时间的变化速率。公式就是d(error)/dt = V,当无人机接近目标高度时,即使误差较小,D算法会依据误差变化的速度提前减小升力,防止无人机继续上升。D算法本质上是对系统未来趋势的预估,通过调节控制量来防止超调和震荡。 所以这个就是 F = kd * d(error)/dt,kd就是D,参数都不能太大否则反冲,得找平衡点,根据上述逻辑去调参。
所以综上第二个步骤Kd,就是为了解决在加速度为0时,还会震荡,这个震荡就必须通过F去抑制,所以第二个步骤后公式就为:F = Kp * error + kd * d(error)/dt,可以看出当error接近0时 这时刻,F=kd*d(error)/dt,用来抑制。
但是我们可以发现第一个步骤以及第二个步骤,无论如何这个error都不会消除成0,因为误差存在,无人机的升力也一定存在,所以我们需要累计误差值(比如随时间积累误差),如果长时间误差得不到修正的话,我们就需要给无人机提供更大的升力,迫使无人机上升,这就是第三个步骤,i算法,i是Integral的缩写,积分算法,I会对误差进行累计,从而提供更大的升力,加入Ki之后,无人机会朝着目标靠拢,最后会error会变成0。
所以公式就是:F=Ki * f error dt,最终结合就是Kd Ki Kp的三者加权求和。
2.无人机PID调参的总结
在调参之前,明确系统的目标性能要求,例如:
- 响应速度:系统需要多快达到目标值?
- 稳态误差:允许的偏差范围是多少?
- 稳定性:是否需要避免过冲或振荡?
调参思路如下
- 先调P:
- 从小到大增加 KpK_pKp,使系统能够快速响应,但不过度振荡。
- 再调D:
- 增加 KdK_dKd,在减小超调的同时保证系统平稳。
- 最后调I:
- 调整 KiK_iKi,消除稳态误差,避免过大导致系统滞后或振荡。
P参数调节(快速响应)
- 目的:提高系统的响应速度。
- 方法:
- 从较小的 KpK_pKp 开始逐步增加,观察系统的反应。
- 调至系统能够快速响应目标,但不过多振荡。
- 注意事项:
- KpK_pKp 太低:系统反应迟缓。
- KpK_pKp 太高:系统可能发生严重超调或振荡。
D参数调节(减小振荡)
- 目的:预测误差变化趋势,减少过冲和振荡。
- 方法:
- 在调整好 KpK_pKp 后,逐步增加 KdK_dKd。
- 调至系统在接近目标时平稳,振荡减小。
- 注意事项:
- KdK_dKd 太低:系统振荡未抑制。
- KdK_dKd 太高:可能放大噪声,导致输出波动。
I参数调节(消除偏差)
- 目的:累计误差,修正稳态误差。
- 方法:
- 在 KpK_pKp 和 KdK_dKd 调整完毕后,再逐步增加 KiK_iKi。
- 调至系统稳态误差为零。
- 注意事项:
- KiK_iKi 太低:无法完全消除稳态误差。
- KiK_iKi 太高:可能导致系统反应过慢或振荡。
无人机场景应用要点
- KpK_pKp 控制初始快速上升。
- KdK_dKd 避免接近目标时的持续震荡。
- KiK_iKi 解决长时间偏差未修正的问题,确保无人机最终稳定在目标高度。
最后还是想说本质调参就是实操的过程一定要动手去做,总结方法。
四、从数学表达式到代码
如下为简单的代码结构图:
现在开始我们就要从上述的理论转到实际代码中了,可移植到STM32、AVR、8051等嵌入式系统中,如下所示:
#include <stdio.h>
// PID控制器结构体
typedef struct {
float kp; // 比例系数
float ki; // 积分系数
float kd; // 微分系数
float setpoint; // 目标值
float prev_error; // 前一时刻误差
float integral; // 积分累积
} PIDController;
// 初始化PID控制器
void PID_Init(PIDController* pid, float kp, float ki, float kd, float setpoint) {
pid->kp = kp;
pid->ki = ki;
pid->kd = kd;
pid->setpoint = setpoint;
pid->prev_error = 0.0f;
pid->integral = 0.0f;
}
// 计算PID控制输出
float PID_Compute(PIDController* pid, float current_value, float dt) {
// 计算误差
float error = pid->setpoint - current_value;
// 比例项
float p_term = pid->kp * error;
// 积分项
pid->integral += error * dt;
float i_term = pid->ki * pid->integral;
// 微分项
float d_term = pid->kd * (error - pid->prev_error) / dt;
// 更新前一误差
pid->prev_error = error;
// 总输出
return p_term + i_term + d_term;
}
控制一个模拟系统如下所示:
#include <stdio.h>
#include <unistd.h> // 使用usleep函数
// 模拟系统
typedef struct {
float value; // 系统状态值
} System;
// 更新系统状态(简单模拟)
void System_Update(System* system, float control_input) {
// 假设控制输入与系统状态直接相关,控制器输出缩放因子为0.1
system->value += control_input * 0.1f;
}
// 主程序
int main() {
PIDController pid;
System system;
// 初始化PID控制器和系统
PID_Init(&pid, 1.0f, 0.1f, 0.05f, 10.0f); // Kp, Ki, Kd, Setpoint
system.value = 0.0f; // 初始系统状态值
float dt = 0.1f; // 时间步长,单位秒
// 运行PID控制
for (int step = 0; step < 100; step++) {
float control = PID_Compute(&pid, system.value, dt); // 计算PID输出
System_Update(&system, control); // 更新系统状态
// 输出当前系统状态和控制量
printf("Step %d: Value = %.2f, Control = %.2f\n", step + 1, system.value, control);
usleep((int)(dt * 1000000)); // 延时,模拟实时系统
}
return 0;
}
- PID_Init:初始化PID控制器,包括设定目标值和参数。
- PID_Compute:计算控制量,考虑误差的比例、积分和微分项。
- System_Update:模拟被控对象的状态更新,真实系统中可替换为硬件接口函数。
- 时间步长
dt
:实际系统中由定时器中断控制,用于计算积分和微分。
防积分饱和:在 PID_Compute
中限制积分项的累积范围:
if (pid->integral > max_integral) pid->integral = max_integral;
if (pid->integral < -max_integral) pid->integral = -max_integral;
噪声滤波:对微分项添加滤波,降低高频噪声对控制输出的影响,例如低通滤波等等。
五、实际使用中PID的各类组合
1.只有一个环的情况
单一环路的情况
- 控制对象:系统有一个明确的控制目标,例如保持速度、温度、位置等。
- 输入信号:目标值(Setpoint)和当前状态值(反馈)。
- 输出信号:直接控制执行器(如电机、电磁阀等)。
组合方式 | 数学表达式 | 特点 | 应用场景 | 优点 | 缺点 |
---|---|---|---|---|---|
P | u(t)=Kp⋅e(t)u(t) = K_p \cdot e(t)u(t)=Kp⋅e(t) | - 控制量与误差成正比 - 简单快速 - 存在稳态误差 | - 加热系统温度调节 - 电机粗略速度控制 | - 实现简单 - 响应速度快 | - 存在稳态误差 - 可能产生振荡 |
PI | u(t)=Kp⋅e(t)+Ki∫e(t)dtu(t) = K_p \cdot e(t) + K_i \int e(t) dtu(t)=Kp⋅e(t)+Ki∫e(t)dt | - 消除稳态误差 - 积分项累计误差,提高长期稳定性 | - 恒温恒湿控制 - 电机精确速度控制 | - 消除稳态误差 - 提高控制精度 | - 积分饱和风险 - 动态响应较慢 |
PD | u(t)=Kp⋅e(t)+Kdde(t)dtu(t) = K_p \cdot e(t) + K_d \frac{de(t)}{dt}u(t)=Kp⋅e(t)+Kddtde(t) | - 提高动态性能 - 抑制振荡,减少过冲 | - 无人机高度控制 - 伺服控制 | - 动态性能优异 - 减少振荡,响应更平稳 | - 无法完全消除稳态误差 - 对噪声敏感 |
PID | u(t)=Kp⋅e(t)+Ki∫e(t)dt+Kdde(t)dtu(t) = K_p \cdot e(t) + K_i \int e(t) dt + K_d \frac{de(t)}{dt}u(t)=Kp⋅e(t)+Ki∫e(t)dt+Kddtde(t) | - 综合比例、积分、微分 - 动态与稳态性能平衡 | - 工业过程控制 - 自动驾驶 | - 动态与稳态性能兼顾 - 适应性强 | - 参数调整复杂 - 实现成本较高 |
2.多个环的情况
多环PID控制 不同组合形式的总结表格,主要分析了多个控制环路的结构、应用场景如下:
控制环类型 | 特点 | 典型应用场景 | 优点 | 缺点 |
---|---|---|---|---|
主从控制 (Master-Slave) | - 外环(主)控制系统主要目标 - 内环(从)控制快速动态响应 - 外环输出为内环设定值 | - 电机速度与电流控制 - 温度与加热功率控制 | - 动态性能和稳态性能分离 - 响应速度快 | - 参数调试复杂 - 耦合可能导致不稳定 |
多变量耦合控制 | - 各环之间存在耦合关系,需考虑整体协调 - 每个环独立调节相关变量 | - 机器人多关节控制 - 化工过程温度与压力控制 | - 可控变量多 - 提高复杂系统控制性能 | - 数学模型复杂 - 参数调优时间较长 |
分层控制 | - 高层规划全局目标 - 低层实现具体控制目标 | - 无人机姿态与位置控制 - 自动驾驶路径与速度控制 | - 目标分层清晰 - 控制任务划分明确 | - 需要精确的高层规划 - 实现难度高 |
级联控制 (Cascade) | - 内环快速补偿扰动 - 外环实现高层次调节 | - 蒸汽锅炉水位控制 - 精密温度控制 | - 提高抗扰性能 - 响应快速 | - 调试复杂度高 - 适用场景有限 |
交叉控制 (Cross-Coupled) | - 各控制环通过交叉耦合补偿相互影响 - 实现多变量动态耦合控制 | - CNC加工多轴协调控制 - 多风机风速同步控制 | - 实现多变量协调控制 - 动态补偿效果好 | - 耦合关系建模复杂 - 对硬件性能要求高 |
-
电机主从控制:
- 外环(主环):控制速度,计算电流目标值。
- 内环(从环):快速控制电流响应。
-
无人机姿态控制:
- 外环:位置控制(例如高度、水平位置)。
- 内环:姿态控制(例如俯仰角、偏航角)。
-
机器人多关节控制:
- 各关节独立控制(位置或速度),通过耦合模型实现整体协调。
六、平衡小车PID
1.平衡小车代码讲解
上述都是一些简单的初始化流程参数,我们不做多的赘述,我们观察下这段代码是一个中断服务程序,用于处理嵌入式系统中的外部中断。其核心功能是基于PID控制算法,通过两层环(直立环和速度环)控制电机的PWM信号以实现动态平衡控制。
- 功能:外部中断线
10~15
的中断处理程序。 - 触发条件:外部中断信号触发,比如 MPU6050 的姿态更新中断信号。
void EXTI15_10_IRQHandler(void)
- 功能:调用
mpu_dmp_get_data()
函数获取传感器数据(pitch
、roll
和yaw
)。roll
:测量当前系统的倾角。pitch
、yaw
:未用到,可以用于扩展功能。
- 返回值判断:判断获取数据是否成功 (
= 0
表示成功)。
if(mpu_dmp_get_data(&pitch,&roll,&yaw)==0)
变量含义:
measure
:实际测量的倾角值,来自roll
。calcu
:目标倾角值,常量zhongzhi
设定。velocity
:当前速度值,基于两个编码器(encoder2
和encoder3
)的平均值。- 目的:测量当前速度,用于速度环控制。
measure = roll; // roll测量值
calcu = zhongzhi; // roll理论值
velocity = ( read_encoder2() + read_encoder3() )/2; // 速度测量值
控制思想:采用双环控制结构(直立环 + 速度环)。
- 直立环:
- 函数
vertical_PID_value(measure, calcu)
计算倾角误差的 PID 输出。 - 目标:维持系统直立状态,减少倾角偏差。
- 函数
- 速度环:
- 函数
velocity_PID_value(velocity)
计算速度误差的 PID 输出。 - 目标:控制移动速度,维持静止或设定的目标速度。
- 函数
- 合并:
- 两者输出叠加,作为最终 PWM 的控制量。
PWM = vertical_PID_value(measure, calcu) + velocity_PID_value(velocity);
- 功能:限制 PWM 输出范围,避免过大或过小的控制信号。
- 目的:保护硬件,防止超出电机或驱动器的工作范围。
PWM_Xianfu(7000, &PWM); // PWM限幅
功能:根据 motor_flag
控制是否为电机设置 PWM 信号。
motor_flag = 1
:电机正常工作。motor_flag = 0
:电机关闭。
if(motor_flag) SETPWM(PWM); // 给电机PWM
else SETPWM(0); // 关闭电机
- 功能:清除外部中断线 12 的中断标志位。
- 目的:避免中断重复触发。
EXTI_ClearITPendingBit(EXTI_Line12); // 清除LINE12上的中断标志位
2.平衡小车的PID实际代码案例(直立环+速度环+转向环)
如下所示为直立环。
- 输入参数:
measure
:实际测量值(如系统的当前倾角)。calcu
:目标值(如系统的理想倾角)。
- 输出参数:返回 PID 计算出的控制量(用于驱动电机等执行器)。
- 误差计算功能:计算测量值与目标值的偏差(误差)。
- 如果
measure > calcu
:表示当前值高于目标值,需降低控制输出。 - 如果
measure < calcu
:表示当前值低于目标值,需增加控制输出。
- 如果
- 变量意义:
err
:当前时刻的误差值。
- 误差积分(I 分量)功能:将误差值累加,用于积分控制。
- 积分作用在于对过去的误差进行累积补偿,消除系统的稳态误差。
- 如果误差长时间未消除,则积分分量会逐步增加控制量以修正误差。
- 变量意义:
err_sum
:误差的累计值。
- 误差微分(D 分量)功能:计算当前误差与上一次误差的变化量,用于微分控制。
- 微分作用在于预测误差变化趋势,提前做出调整,抑制系统震荡。
- 当误差变化较快时,D 分量的权重会增大,从而抑制系统过冲或震荡。
- 变量意义:
err_difference
:误差的变化量(当前误差 - 上次误差)。
- 更新上次误差功能:将当前误差保存下来,以供下一次计算
err_difference
使用。 - 目的:实现递推式计算。
- 输出=Kp⋅误差+Ki⋅误差累计值+Kd⋅误差变化率
Kp
(比例系数):- 控制误差与输出的直接线性关系。
- 决定系统对误差的即时响应强度。
Ki
(积分系数):- 控制累计误差与输出的关系。
- 决定系统消除稳态误差的能力。
Kd
(微分系数):- 控制误差变化率与输出的关系。
- 决定系统对误差变化趋势的预估能力,抑制震荡。
- 输出值:返回计算得到的控制量,用于调节执行器(如电机的 PWM 信号)。
如下为速度环
滤波处理
- 目的:
- 使用一阶滤波算法平滑测量的速度信号,降低噪声对控制的影响。
- 公式:
- 滤波速度=a⋅当前速度+(1−a)⋅上次滤波速度\text{滤波速度} = a \cdot \text{当前速度} + (1-a) \cdot \text{上次滤波速度}滤波速度=a⋅当前速度+(1−a)⋅上次滤波速度
- 参数说明:
a
:滤波系数,范围为 [0,1]。- a→1a \to 1a→1:实时性高,噪声滤波效果弱。
- a→0a \to 0a→0:实时性低,噪声滤波效果强。
积分计算
- 目的:
- 累计经过滤波的速度信号,用于积分控制,消除稳态误差。
- 风险:
- 累加可能导致积分饱和,需要限幅处理。
累加限幅
- 目的:
- 对速度累积值(
velocity_sum
)进行限制,防止积分值过大导致输出失控。
- 对速度累积值(
- 实现:
- 若累加值超过正/负限制值,则将其强制设定为限制值。
更新历史滤波速度将当前滤波后的速度保存为历史值,以便下一次滤波计算使用。
输出 PID 控制量
VKi
:积分系数,决定控制器对累计速度误差的修正能力。VKp
:比例系数,决定控制器对当前速度误差的即时响应强度。
七、实际调参 —— 平衡小车
1.平衡小车的调参流程
先调参直立环PD->速度环PI,最后再是转向环PD/PID
直立环用于维持小车的直立平衡,其核心是调整小车姿态(如俯仰角)。
目标:保证小车在没有速度输入的情况下保持平衡。
速度环用于调节小车的移动速度(前后运动)。转向环用于调节小车的方向,通常基于航向角或偏航角。
直立环 | 小车保持直立 | KpK_pKp → KdK_dKd → KiK_iKi | 控制输出限幅,防止震荡 |
速度环 | 调节小车前后运动速度 | VKpVK_pVKp → VKiVK_iVKi | 速度累加限幅,防止积分饱和 |
转向环 | 调节小车转向角度 | TKpTK_pTKp → TKdTK_dTKd → TKiTK_iTKi | 注意与直立环、速度环的交叉干扰 |
2.实际项目调参方法讲解
-
明确系统模型与目标:
- 明确被控对象(如平衡小车、电机、温控器等)的动态特性。
- 确定 PID 控制的目标(如位置控制、速度控制等)。
-
选择控制器结构:
- 确定需要用 P、PI、PD 或 PID 结构。
- 简单场景可先用 P 或 PI 结构。
-
设置初始参数:
- 设置初始值为 Kp=0.01K_p = 0.01Kp=0.01、Ki=0K_i = 0Ki=0、Kd=0K_d = 0Kd=0。
- 确保输出限幅机制已在程序中实现。
-
确保安全性:
- 加入紧急停止机制(如限幅保护、错误信号检测等)。
- 在受控环境下调试,避免硬件损坏。