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)+Ti10te(τ)dτ+Tddtde(t)]u(t)=Kpe(t)+Ki0te(τ)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=0ne(i)+Kd[e(n)e(n1)]

示例代码:

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(n1)]+Kie(n)+Kd[e(n)2e(n1)+e(n2)]u(n)=u(n1)+Δ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=0ne(i)+Kd[e(n)e(n1)]

积分分离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=0ne(i)+Kd[e(n)e(n1)]α={10e(n)Ae(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=0nf[e(i)]e(i)+Kd[e(n)e(n1)]f[e(i)]= 1AAe(i)+B0e(i)BB<e(i)A+Be(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=0ne(i)+ud(n)ud(n)=(1α)ud(n1)+αKd[e(n)e(n1)]

微分先行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=0ne(i)Kd[y(n)y(n1)]

Logo

「智能机器人开发者大赛」官方平台,致力于为开发者和参赛选手提供赛事技术指导、行业标准解读及团队实战案例解析;聚焦智能机器人开发全栈技术闭环,助力开发者攻克技术瓶颈,促进软硬件集成、场景应用及商业化落地的深度研讨。 加入智能机器人开发者社区iRobot Developer,与全球极客并肩突破技术边界,定义机器人开发的未来范式!

更多推荐