PID控制算法简介
PID简介
PID(Proportion-Integral-Differential),即比例-积分-微分,是一种常用的闭环控制器。
控制系统结构图:
传递函数:
G(s)=Kp(1+1Tis+Tds)或G(s)=Kp+Kis+Kds G(s) = K_p \left( 1 + \frac{1}{T_i s} + T_d s \right) \\或 \\G(s) = K_p + \frac{K_i}{s} + K_d s G(s)=Kp(1+Tis1+Tds)或G(s)=Kp+sKi+Kds
模拟量公式:
u(t)=Kp[e(t)+1Ti∫0te(τ)dτ+Tdde(t)dt]或u(t)=Kpe(t)+Ki∫0te(τ)dτ+Kdde(t)dt u(t) = K_p \left[ e(t) + \frac{1}{T_i} \int_0^t e(\tau) d\tau + T_d \frac{de(t)}{dt} \right] \\ 或 \\ u(t) = K_p e(t) + K_i \int_0^t e(\tau) d\tau + K_d \frac{de(t)}{dt} u(t)=Kp[e(t)+Ti1∫0te(τ)dτ+Tddtde(t)]或u(t)=Kpe(t)+Ki∫0te(τ)dτ+Kddtde(t)
PID在计算机程序(数字量)中,有传统(位置式)PID和增量式PID两种实现形式。
传统(位置式)PID
数字量公式:
u(n)=Kpe(n)+Ki∑i=0ne(i)+Kd[e(n)−e(n−1)] u(n) = K_p e(n) + K_i \sum_{i=0}^n e(i) + K_d [e(n) - e(n-1)] u(n)=Kpe(n)+Kii=0∑ne(i)+Kd[e(n)−e(n−1)]
示例代码:
typedef struct {
float kp; // 比例系数
float ki; // 积分系数
float kd; // 微分系数
float err; // 误差
float last_err; // 上次误差
float proportion; // 比例项
float integral; // 积分项
float differential; // 微分项
float integral_limit; // 积分限幅
} PID;
PID pid = {
.kp = 1,
.ki = 1,
.kd = 1,
.integral_limit = 1023,
};
void pid_controler(float target, float feedback, float *output)
{
// 更新误差
pid.last_err = pid.err;
pid.err = target - feedback;
// 计算比例项
pid.proportion = pid.kp * pid.err;
// 计算积分项、积分限幅
pid.integral += pid.ki * pid.err;
if(pid.integral > pid.integral_limit) pid.integral = pid.integral_limit;
if(pid.integral < -pid.integral_limit) pid.integral = -pid.integral_limit;
// 计算微分项
pid.differential = pid.kd * (pid.err - pid.last_err);
// 计算输出量
*output = pid.proportion + pid.integral + pid.differential;
}
增量式PID
数字量公式:
Δu(n)=Kp[e(n)−e(n−1)]+Kie(n)+Kd[e(n)−2e(n−1)+e(n−2)]u(n)=u(n−1)+Δu(n) \Delta u(n) = K_p [e(n) - e(n-1)] + K_i e(n) + K_d [e(n) - 2e(n-1) + e(n-2)] \\u(n) = u(n-1) + \Delta u(n) Δu(n)=Kp[e(n)−e(n−1)]+Kie(n)+Kd[e(n)−2e(n−1)+e(n−2)]u(n)=u(n−1)+Δu(n)
从公式上可以看出,增量式PID和传统(位置式)PID可以互相推导,也就意味着增量式PID和传统(位置式)PID只是数据的计算顺序不同,数据的计算结果和控制效果是相同的。增量式PID的优点就是不需要考虑积分饱和问题,也不再需要积分限幅。
示例代码:
typedef struct {
float kp; // 比例系数
float ki; // 积分系数
float kd; // 微分系数
float err; // 误差
float last_err; // 上次误差
float last_last_err; // 上上次误差
float proportion; // 比例项
float integral; // 积分项
float differential; // 微分项
} PID;
PID pid = {
.kp = 1,
.ki = 1,
.kd = 1,
};
void pid_controler(float target, float feedback, float *output)
{
// 更新误差
pid.last_last_err = pid.last_err;
pid.last_err = pid.err;
pid.err = target - feedback;
// 计算比例项
pid.proportion = pid.kp * (pid.err - pid.last_err);
// 计算积分项
pid.integral = pid.ki * pid.err;
// 计算微分项
pid.differential = pid.kd * (pid.err - 2 * pid.last_err + pid.last_last_err);
// 计算输出量
*output += pid.proportion + pid.integral + pid.differential;
}
PID的变种
前馈PID
前馈PID能够让控制系统更快速的达到稳态,减少积分环节消耗的时间。
控制系统结构图:
数字量公式:
u(n)=r(n)+Kpe(n)+Ki∑i=0ne(i)+Kd[e(n)−e(n−1)] u(n) = r(n) + K_p e(n) + K_i \sum_{i=0}^n e(i) + K_d [e(n) - e(n-1)] u(n)=r(n)+Kpe(n)+Kii=0∑ne(i)+Kd[e(n)−e(n−1)]
积分分离PID
积分分离PID的核心思想是,在系统误差较大时暂停积分作用,当误差减小到一定程度时再重新启用积分作用。这样做的目的是,避免因为在误差较大时积分项累积过多而导致的系统超调。
数字量公式:
u(n)=Kpe(n)+Kiα∑i=0ne(i)+Kd[e(n)−e(n−1)]α={1∣e(n)∣≤A0∣e(n)∣>A u(n) = K_p e(n) + K_i \alpha \sum_{i=0}^n e(i) + K_d [e(n) - e(n-1)] \\ \alpha = \begin{cases} 1 & |e(n)| \le A \\ 0 & |e(n)| > A \end{cases} u(n)=Kpe(n)+Kiαi=0∑ne(i)+Kd[e(n)−e(n−1)]α={10∣e(n)∣≤A∣e(n)∣>A
变速积分PID
变速积分PID的核心思想是,在系统误差较大时减小积分累积的速度,而在误差较小时增大积分累积的速度。这样做的目的是,避免因为在误差较大时积分项累积过多而导致的系统超调。变速积分PID可以看成是积分分离PID的升级版。
数字量公式:
u(n)=Kpe(n)+Ki∑i=0nf[e(i)]e(i)+Kd[e(n)−e(n−1)]f[e(i)]={1∣e(i)∣≤BA−∣e(i)∣+BAB<∣e(i)∣≤A+B0∣e(i)∣>A+B u(n) = K_p e(n) + K_i \sum_{i=0}^n f[e(i)] e(i) + K_d [e(n) - e(n-1)] \\ f[e(i)] = \begin{cases} 1 & |e(i)| \le B \\ \frac{A - |e(i)| + B}{A} & B < |e(i)| \le A+B \\ 0 & |e(i)| > A+B \end{cases} u(n)=Kpe(n)+Kii=0∑nf[e(i)]e(i)+Kd[e(n)−e(n−1)]f[e(i)]=⎩
⎨
⎧1AA−∣e(i)∣+B0∣e(i)∣≤BB<∣e(i)∣≤A+B∣e(i)∣>A+B
不完全微分PID
不完全微分PID通过引入一个低通滤波器来平滑微分项的计算结果,从而减少对高频噪声的敏感性。这样做的目的是,防止微分项因为对高频噪声敏感而产生过度调节的问题。
数字量公式:
u(n)=Kpe(n)+Ki∑i=0ne(i)+ud(n)ud(n)=(1−α)ud(n−1)+αKd[e(n)−e(n−1)] u(n) = K_p e(n) + K_i \sum_{i=0}^n e(i) + u_d(n) \\ u_d(n) = (1 - \alpha) u_d(n-1) + \alpha K_d [e(n) - e(n-1)] u(n)=Kpe(n)+Kii=0∑ne(i)+ud(n)ud(n)=(1−α)ud(n−1)+αKd[e(n)−e(n−1)]
微分先行PID
在传统PID控制器中,微分项是基于误差(即目标量与反馈量之差)的变化率来计算的,而在微分先行PID控制器中,微分项是基于反馈量的变化率来计算的。
数字量公式:
u(n)=Kpe(n)+Ki∑i=0ne(i)−Kd[y(n)−y(n−1)] u(n) = K_p e(n) + K_i \sum_{i=0}^n e(i) - K_d [y(n) - y(n-1)] u(n)=Kpe(n)+Kii=0∑ne(i)−Kd[y(n)−y(n−1)]
「智能机器人开发者大赛」官方平台,致力于为开发者和参赛选手提供赛事技术指导、行业标准解读及团队实战案例解析;聚焦智能机器人开发全栈技术闭环,助力开发者攻克技术瓶颈,促进软硬件集成、场景应用及商业化落地的深度研讨。 加入智能机器人开发者社区iRobot Developer,与全球极客并肩突破技术边界,定义机器人开发的未来范式!
更多推荐



所有评论(0)