位置式PID与增量式PID:两种算法的数学推导、优缺点对比、适用场景分析

做电机控制这些年,我见过不少新手在PID实现上栽跟头。明明算法原理都懂,一写代码就出问题。说白了,就是没搞清楚位置式和增量式的本质区别。

这一章,咱们就把这两种PID算法掰开揉碎了讲。我会从数学推导开始,再到实际项目中的坑,最后告诉你什么场景该用哪个。

1. 位置式PID:最直观的算法

位置式PID,顾名思义,直接计算当前时刻的控制量。它的数学形式是这样的:

u(k) = Kp * e(k) + Ki * Σe(i) + Kd * [e(k) - e(k-1)]

其中:

  • u(k):第k时刻的控制输出
  • e(k):第k时刻的偏差(目标值 - 实际值)
  • Σe(i):从开始到现在的偏差累加
  • Kp, Ki, Kd:比例、积分、微分系数

这个公式看着简单,但有个关键问题——积分项会一直累加。我在做直流电机调速时遇到过这种情况:电机启动瞬间偏差很大,积分项疯狂累加,等电机转起来后,这个积分值已经大到离谱,导致系统严重超调。

⚠ 避坑指南:位置式PID的积分饱和是新手最容易踩的坑。我曾经在一个温控项目中,积分项累加到了满量程的3倍,系统直接失控。解决办法是加积分限幅,或者用抗积分饱和算法。

2. 增量式PID:只算变化量

增量式PID的思路完全不同——它只计算当前控制量相对于上一次的变化量。数学推导如下:

先写出k-1时刻的位置式:

u(k-1) = Kp * e(k-1) + Ki * Σe(i-1) + Kd * [e(k-1) - e(k-2)]

然后用u(k)减去u(k-1),得到增量:

Δu(k) = Kp * [e(k) - e(k-1)] + Ki * e(k) + Kd * [e(k) - 2*e(k-1) + e(k-2)]

最终的控制输出:

u(k) = u(k-1) + Δu(k)

你想想看,这个公式有什么好处?没有积分累加项。每次只算变化量,就算偏差很大,也不会出现积分饱和的问题。

💡 个人经验:我在做四轴飞行器姿态控制时,用的就是增量式PID。飞行器姿态变化快,如果位置式PID的积分项处理不好,飞机会抖得像筛子一样。增量式天然避免了这个问题。

3. 两种算法的核心差异

为了让你看得更清楚,我整理了一个对比表:

对比维度 位置式PID 增量式PID
计算方式 直接计算全量控制输出 只计算控制量的变化值
积分项 偏差累加,可能饱和 无累加项,天然抗饱和
输出突变 切换时可能产生大跳变 输出平滑,无跳变
故障影响 输出异常可能导致执行器全开 输出异常影响较小
内存需求 需存储所有历史偏差 只需存储最近3个偏差
手动/自动切换 需做无扰切换处理 天然支持无扰切换

4. 适用场景分析

搞清楚了差异,咱们来看看实际项目中该怎么选。

4.1 位置式PID适合的场景

  • 执行器有记忆功能:比如步进电机的位置控制,每次给一个绝对位置值
  • 系统对积分精度要求高:比如高精度温控,需要精确消除静差
  • 控制周期固定且较长:有足够时间处理积分饱和问题
  • 输出直接对应物理量:比如阀门开度、加热功率等

4.2 增量式PID适合的场景

  • 执行器是积分元件:比如伺服电机的速度环,增量输出直接对应加速度
  • 系统需要频繁切换:比如手动/自动模式切换,增量式天然无扰
  • 对输出突变敏感:比如精密运动控制,不允许控制量跳变
  • 嵌入式资源受限:只需存储3个偏差值,内存占用极小
🔧 实战建议:我个人习惯在电机速度环和位置环中使用增量式PID,在温度控制这类大惯性系统中使用位置式PID。当然,这不是绝对的,具体还要看你的执行器特性和控制要求。

5. 两种算法的代码实现对比

光说不练假把式。我写两个简单的C语言实现,你看看区别:

// 位置式PID
float PositionalPID(float setpoint, float feedback) {
    float error = setpoint - feedback;
    integral += error;  // 积分累加
    float derivative = error - prev_error;
    
    float output = Kp * error + Ki * integral + Kd * derivative;
    
    // 输出限幅
    if (output > max_output) output = max_output;
    if (output < min_output) output = min_output;
    
    prev_error = error;
    return output;
}

// 增量式PID
float IncrementalPID(float setpoint, float feedback) {
    float error = setpoint - feedback;
    float delta = Kp * (error - prev_error) 
                + Ki * error 
                + Kd * (error - 2*prev_error + prev_prev_error);
    
    output += delta;  // 累加增量
    
    // 输出限幅
    if (output > max_output) output = max_output;
    if (output < min_output) output = min_output;
    
    prev_prev_error = prev_error;
    prev_error = error;
    return output;
}

看到区别了吗?位置式PID的integral变量会一直增长,而增量式PID只用了3个偏差值做计算。这就是为什么增量式PID在嵌入式系统里更受欢迎。

6. 知识结构图

下面这张图帮你理清两种算法的核心逻辑和选择路径:

位置式PID与增量式PID对比结构图 位置式PID vs 增量式PID 核心对比 位置式PID 增量式PID 直接计算全量控制输出 积分项累加,可能饱和 切换时输出可能跳变 只计算控制量的变化值 无积分累加,天然抗饱和 输出平滑,支持无扰切换 适用场景选择 位置式PID适用 执行器有记忆功能 高精度积分控制、大惯性系统 增量式PID适用 执行器为积分元件 频繁切换、资源受限、精密控制 对比

7. 我的选择建议

说了这么多,到底该怎么选?我总结几条实战经验:

  1. 电机速度环和位置环:优先用增量式PID。电机响应快,增量式能避免积分饱和导致的超调。
  2. 温度、压力等大惯性系统:位置式PID更合适。这类系统需要精确的积分作用来消除静差。
  3. 系统需要频繁切换模式:增量式PID是首选。无扰切换特性让你少掉很多头发。
  4. 单片机资源紧张:增量式PID只需要3个变量,位置式需要存储所有历史偏差,高下立判。
⚠ 重要提醒:不管你选哪种算法,输出限幅和积分限幅都是必须加的。我曾经在一个项目中忘了加积分限幅,结果积分项跑到天上去,系统直接崩溃。这个教训,希望你不要重蹈覆辙。