资讯动态

位置式PID与增量式PID的区别、推导及实际选型经验

发布时间:2026/10/16 2:51:07 来源:尧图企业网站定制
做嵌入式这些年PID这个算法几乎避不开。无论你搞温控、电机调速、平衡小车还是无人机只要涉及闭环控制最后基本都会落到这两种PID变体上位置式PID和增量式PID。很多刚入门的开发者经常在这两者之间犹豫网上教程也不少但大多是各讲各的很少有人把两者的联系、边界和选型逻辑讲透彻。这篇就专门聊聊位置式PID和增量式PID的公式推导、代码实现、适用场景以及我在实际调参中踩过的坑希望能给正在选型或者调参调试的同行一些参考。这个话题有个比较有意思的点从控制理论的角度看两者本质上是一样的算法只是在输出形式和执行方式上做了不同的处理但在实际工程中这个差异会直接影响系统的安全性和调试体验。我自己第一次从位置式切到增量式时就明显感觉到执行器行为和故障处理方式完全不一样。所以这篇不是单纯讲两个公式而是把公式背后那层工程含义也一并拆开。1. 位置式PID公式拆解与模板代码1.1 离散化公式到底在算什么位置式PID的输出直接就是执行机构需要到达的“绝对位置”或者“绝对数值”。它的离散化公式长这样U(k) Kp * e(k) Ki * Σe(i) Kd * [e(k) - e(k-1)]其中e(k)是第k次采样的偏差Σe(i)是从启动到现在的累计偏差e(k) - e(k-1)是当前偏差与上一次偏差的差值。这个公式看着简单但真正理解它需要先想明白一件事我们是在对一个连续系统的控制方程做离散化。连续PID输出是比例项、积分项、微分项的连续叠加采样控制只能在一个个时间点上做计算所以用求和代替积分用差分代替微分这就是上面公式的来历。为什么叫“位置式”关键在这个U(k)的含义上。位置式输出的是控制量的全量值比如加热PWM的占空比、阀门的开度百分比、伺服电机的目标位置直接对应被控对象的绝对状态。这也意味着如果U(k)突然跳变执行机构就会立刻被推到一个新位置冲击感会很强。我在实际项目中见过不少人把位置式PID写得过于随意直接把误差累加就直接丢给执行器结果出现一个很容易被忽略的问题累计误差项。Σe(i)是无限累加的如果e(i)一直不为0这个积分项会越积越大最终完全主导输出控制器表现为“反应迟钝”甚至“爬行”。所以位置式PID的代码模板里积分项必须有处理策略否则系统分分钟给你表演一场积分饱和。1.2 位置式PID的标准代码模板这里给一份我用过多次的C语言风格模板不算最优但结构清晰方便改成你自己的变量名和数据结构typedef struct { float Kp; float Ki; float Kd; float target; float feedback; float integral; float last_error; float out_max; float out_min; } PositionalPID; float PositionalPID_Calc(PositionalPID *pid, float target, float feedback) { float error target - feedback; float output; /* 积分项累加 */ pid-integral error; /* 微分项用一阶差分 */ float derivative error - pid-last_error; /* 位置式输出 */ output pid-Kp * error pid-Ki * pid-integral pid-Kd * derivative; /* 限幅 */ if (output pid-out_max) { output pid-out_max; /* 实际中经常在这里做积分限幅见下方说明 */ } else if (output pid-out_min) { output pid-out_min; } pid-last_error error; return output; }这段代码有个值得推敲的细节我在限幅注释里加了一句话“通常在这里做积分限幅”。这句话很多人不重视但它是位置式PID稳定性的关键。最简单的做法是给积分项单独设上限I_max当integral超过这个上限时就不再累加进阶一点的做法就是抗积分饱和下面细说。1.3 位置式PID的积分饱和与抗饱和措施积分饱和就是前面提到的“积分项越积越大控制器反应迟钝”的现象。举个实际的例子加热系统温度从20℃往100℃加热偏差很大积分项会疯狂累加。等温度真的到了100℃积分项可能已经积累到一个巨大数值输出还在按照这个积分项的“惯性”继续加热温度就会冲到110℃、120℃才被拉回来。你打了个方向盘车还停不下来说的就是这种感觉。解决积分饱和我实践下来最有效的方法是积分分离和抗积分饱和反馈两者可以搭配使用。积分分离的思路偏差大的时候暂时关闭积分作用只用PD尽快逼近目标当偏差缩小到阈值以内再恢复积分用来消除静差。if (error integral_limit || error -integral_limit) { pid-integral 0; /* 偏差大时直接清掉积分或不累加 */ } else { pid-integral error; }抗积分饱和反馈的思路则更精细先计算未限幅的输出值U_unclamped如果U_unclamped超出限幅值就反向削弱积分项让输出尽快回到限幅范围内。这个方法在变频器控制、阀门控制里非常实用。注意积分项是位置式PID的灵魂也是它最容易翻车的部分。删掉积分项会带来静差不限制它会带来超调所以正确的做法不是取舍而是给它加上规则。这个理解到位了位置式PID你就掌握了一半。2. 增量式PID推导逻辑与实现细节2.1 增量式的公式是怎么推出来的增量式PID的输出不是直接给执行器一个“目标值”而是给一个“变化量”。它是在位置式的基础上推出来的把第k次的计算结果减去第k-1次的计算结果相邻两次输出的差值就是增量。位置式第k次输出 U(k) Kp * e(k) Ki * Σe(i) Kd * [e(k) - e(k-1)]位置式第k-1次输出 U(k-1) Kp * e(k-1) Ki * Σe(i-1) Kd * [e(k-1) - e(k-2)]两式相减得到增量ΔU(k) U(k) - U(k-1) Kp * [e(k) - e(k-1)] Ki * e(k) Kd * [e(k) - 2e(k-1) e(k-2)]我个人觉得这个公式非常好用因为它的每一项物理意义都特别清楚Kp项是偏差变化的灵敏度偏差在变快还是变慢它都能立刻反应过来。Ki项是当前偏差的权重相当于通过“增量”间接把历史偏差的累积作用顾及进去了。Kd项是偏差变化的加速度项用e(k) - 2e(k-1) e(k-2)这组二阶差分比位置式的单差分更能感知变化趋势的转折。注意一个关键点增量式公式里没有任何累计项。历史积分效应被“增量累加”这个动作隐式包含了执行器位置上保留着过去全部的控制信息。这也就是为什么增量式PID天然不容易出现积分饱和失控因为每次只动一点点。2.2 增量式PID的代码模板与执行器配合增量式PID的代码比位置式还要轻巧因为它不需要维护积分累加器只需要记住前两个周期的误差值typedef struct { float Kp; float Ki; float Kd; float target; float feedback; float error_prev1; float error_prev2; float delta_max; } IncrementalPID; float IncrementalPID_Calc(IncrementalPID *pid, float target, float feedback) { float error target - feedback; float delta_output; /* 增量式核心 */ delta_output pid-Kp * (error - pid-error_prev1) pid-Ki * error pid-Kd * (error - 2.0f * pid-error_prev1 pid-error_prev2); /* 增量限幅防止执行器动作过猛 */ if (delta_output pid-delta_max) { delta_output pid-delta_max; } else if (delta_output -pid-delta_max) { delta_output -pid-delta_max; } /* 更新历史误差 */ pid-error_prev2 pid-error_prev1; pid-error_prev1 error; return delta_output; }调用时要做一次累加delta IncrementalPID_Calc(pid, target, feedback); actuator_output delta;增量式PID必须配合一个“带记忆性的执行器”使用这是很多人忽略的重点。所谓带记忆性是指执行器本身就保存着当前状态外部只需要告诉它“加一点”或者“减一点”。典型的例子是带位置环的伺服系统驱动器内部有当前位置寄存你发送脉冲增量它自己会朝那个方向运动还有带累加功能的PID控制器软件输出增量直接加在上一次指令上落到外部执行器上。如果你的执行器内部没有记忆能力比如一个电加热管只能接收绝对功率值那就不能用增量式你得在外面额外维护一个输出累加变量本质上又回到了位置式的存储逻辑。2.3 增量式PID的“伪优点”辨析网上有说法称增量式PID没有积分作用还能消除静差这其实是误解。应该说增量式PID的积分作用被隐藏在了累加过程中。它之所以不容易超调失控不是因为少了积分而是因为输出变化被增量限幅限制了每次输出的冲击都控制在安全范围以内。也存在一种代码实现上的“增量式陷阱”。有些工程师为了减少计算量直接省略Kd项把增量式退化成PI控制器。这在某些滞后系统中能跑但遇到快速变化的工况你就会发现系统响应总慢半拍因为缺少微分项的预判能力。所以除非你明确知道系统对微分不敏感否则不要轻易砍掉D项。3. 位置式PID和增量式PID怎么选场景决定方案3.1 不同场景下的选型复盘回溯我用过的一些实际项目可以归纳出几个清晰的选型规律控制电加热温度时我用的是位置式PID。原因很直接加热棒和可控硅调节的是输出功率功率本身是绝对值概念位置式直接输出占空比物理意义清晰。更重要的是温度是慢变过程即使偶尔积分饱和超调的代价也可控用抗饱和措施能解决大部分问题。控制直流电机转速时我用的是增量式PID。原因是电机的PWM输入对“突变”非常敏感位置式全量输出很容易让电压发生跳变产生转速冲击和电流尖峰。增量式每次只输出一个微小的占空比调整值电机转速平滑过渡噪音也小很多。控制无人机姿态时内环用的是增量式外环用位置式。这个组合很典型角速度环作为内环控制周期短、需要快速平滑修正用增量式角度环作为外环响应速度慢且需要绝对角度收敛用位置式保证无静差。我把自己的选型思路整理成一张表方便大家按特征对照判断维度适合位置式适合增量式执行器特性接收绝对值指令阀门开度、功率给定接收增量指令伺服脉冲、步进方向脉冲输出突变风险可以接受或有专门限幅保护要求输出平滑无冲击积分饱和风险需要额外做抗饱和处理天然不易积分饱和故障安全考虑输出全量丢失可能造成危险如阀门全开输出增量丢失影响小系统维持在原位附近计算资源需维护积分累加变量只需保存两个历史误差内存更省3.2 增量式PID在故障安全上的优势增量式PID的一个隐藏优势在系统异常或通信中断时才会体现出来。如果用的是位置式PID一旦控制器输出被异常清零执行器会直接回到“零位”。在阀门控制系统里这意味着阀门可能瞬间被强制关闭或打开如果没有抱闸或失电保护现场设备存在较大风险。我之前调一个液位控制项目时就遇到过PLC重启瞬间输出清零电动阀直接全关液位瞬间波动还好系统有联锁保护才没造成事故。增量式PID则不太一样。它的输出是一个变化量即使控制器输出意外清零执行器也只会停止在当前状态附近不会跳变。很多电机和阀门系统选择增量式故障安全问题是很重要的考量点。3.3 两类PID的变种与互补使用实际工程中很少只用一种PID打天下更多是混合使用或者给PID加上各种变种逻辑。比如温度控制中常用“位置式PID Bang-Bang预加热”启动阶段温度偏差很大不进入PID调节直接用100%功率加热温度接近目标时切换进PID这样既保证了加热速度又避免纯粹位置式PID在启动初期带来的超调。再比如伺服控制中用“位置式外环 增量式内环”外环角度偏差给出速度指令内环再对速度指令做增量式平滑。这种串级结构能发挥两者优势外环负责“大方向”内环负责“精细动作”配合起来比单环PID效果好很多。我自己还用过一种简单有效的变种把位置式PID和增量式PID做一个加权切换偏差大时以增量式为主偏差小时以位置式为主。这个思路类似积分分离的进阶版本质上是利用增量式的平稳性和位置式的收敛性。4. PID参数整定从经验到方法4.1 临界比例度法实操流程参数整定是PID调试里最耗时、也最有技术含量的一环。我最常用的方法是临界比例度法很简单但能提供一个不错的起始参数组合。先把积分项和微分项关掉只保留纯比例控制。然后把Kp从零开始慢慢往上加观察系统响应。当输出出现等幅振荡时记下此时的Kp为临界增益Kc同时用一个秒表或示波器测出振荡周期Tc。然后按照经验公式向下换算控制器形式KpKiKdP0.5 * Kc--PI0.45 * Kc0.45 * Kc / Tc-PID0.6 * Kc0.6 * Kc / (Tc/2)0.6 * Kc * (Tc/8)注意这里的Ki和Kd单位与公式形式有关如果你的积分项乘以的是采样周期T那换算关系要相应调整Ki Kp * T / TiKd Kp * Td / T。很多人在这一步踩坑明明临界参数没问题换到离散公式就发散了多半是没考虑采样周期的换算。4.2 手动整定参数的调节方向临界比例度法能给出一个不错的起点但最终的精细调节还是要靠手动微调。连续的整定经验我总结为这几条系统响应慢加大Kp。Kp加大后如果开始振荡就减到振荡前的80%左右。静差消除不掉先加Ki观察超调。超调太大就回调Kp同时可以适当增大积分时间常数Ti。系统超调量和振荡次数都大先加Kd。微分项会为系统提供“阻尼”对快速过程效果明显但Kd过大会引入噪声。温度、液位这类大惯性系统Ki不宜过大Kd也别设太高否则微分对缓慢变化不敏感反而把测量噪声放得很大。参数整定的本质是平衡四个特性稳定性、快速性、准确性、鲁棒性。不存在一组万能参数只有针对当前工况最优的参数。所以我调完一套参数后通常会在目标值附近做一次阶跃测试观察超调量和调节时间能否满足需求。4.3 采样周期对参数的影响采样周期T的选择对PID效果影响很大而且这个影响是隐性的。同样一组Kp、Ki、Kd在1ms采样和10ms采样下表现完全不同。采样周期要满足香农采样定理至少是系统最小时间常数的1/10左右太慢会让系统丢失高频信息太快则会让微分项计算被噪声淹没。要注意当你改了采样周期PID参数数值需要重新换算。很多工程师忽略这一点系统换了个定时中断周期后参数直接“失效”其实就是积分和微分环节的离散化尺度变了。我自己习惯把采样周期固定写在PID结构体里每次换算都基于这个T来算Ki和Kd避免“换周期忘换参数”的问题。5. 调参之路上的坑与排查实录5.1 温控系统振荡积分饱和的典型教训有一次调一个塑胶挤出机的温度控制设定200℃温度始终在190℃到215℃之间波动始终稳定不下来。波形图一看就是典型的“积分饱和引发的极限环振荡”。排查思路先看温度接近设定值时的输出值发现加热占空比仍然是100%说明积分项还积压着大量历史偏差。把积分项清零试了一下温度确实落到195℃附近但静差也出来了证实问题出在积分处理上。最终改进方案是积分分离温度偏差超过10℃时积分项不累加低于10℃再恢复积分作用。改完以后温度稳定在199.8℃左右波动不超过0.3℃。这个案例让我意识到积分饱和不是参数问题是算法结构问题必须从代码层面防住它。5.2 电机转速噪声放大微分项失控案另一个项目是直流电机测速控制用增量式PID转速反馈来自编码器。调参时发现一个诡异现象电机转速基本稳定但PWM输出高频抖动电机发出刺耳的嗡鸣声。排查后发现编码器反馈信号本身有轻微抖动微分项对相邻两次偏差差值的细小波动极其敏感放大后反应到PWM上就成了高频扰动。Kd越大噪声放得越狠。解决办法有两个层面硬件上给编码器信号加了RC低通滤波软件上给微分项添加了一阶低通滤波。我最后选择在PID里对偏差序列先做滑动平均再做差分计算量增加不多但噪声抑制效果明显。所以用微分项时请一定确认反馈信号质量够好否则宁可少用或者不用D。5.3 执行器卡顿与输出死区问题还有一种常见问题执行器本身有死区微小增量输出驱动不了它。增量式PID输出0.1%的增量步进电机可能根本没反应位置式PID输出0.5%的偏差量阀门也不会动。这个问题的本质是执行机构分辨率跟不上控制精度。我处理过的方法是在PID输出后面加一个“死区补偿”检测到输出增量小于执行器最小响应阈值时把增量强制抬升到阈值附近或者在执行器控制逻辑里加“微动补偿”逻辑让执行器在死区范围内做周期性微动作。死区补偿要注意方向和反馈的配合否则很容易在补偿点上产生震荡。如果阀门的死区是1%而你又把补偿做成1%的阶跃系统就会在目标附近来回摆动。6. 最后的一些经验心得位置式和增量式PID从数学上看确实同源但在工程使用上是两种思路一个管“绝对值”一个管“变化量”。选型前先想清楚执行器要什么再看系统对冲击和故障的容忍度顺下来结论往往很自然。我个人的习惯是只要能接受绝对值输出且系统惯性较大优先位置式因为它控制逻辑直观、便于调试凡是执行器对突变更敏感、或者故障安全要求较高的果断增量式。两者不是竞争关系更多是互补关系。最后再分享一个小技巧如果你正在开发一个多闭环系统建议在PID调试接口里预设“位置式/增量式模式切换”的开关调试时可以先在位置式下观察整体收敛性再切到增量式下优化平滑性。这个开关我保留在很多项目里带来的调试便利性远超你写它花掉的那点时间。调试PID没有万能公式但把算法的结构差异和工程边界理解透了你就能少走很多弯路。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑