ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

个人PID学习心得

个人PID学习心得


引言


PID 是工业控制领域最通用的闭环控制算法,核心目标是让被控对象精准、稳定地跟随目标值。小到电机定速、恒温箱控温,大到机器人关节、无人机悬停,背后几乎都是 PID 在起作用。 你可以把它理解成一个 “自动调节器”:人手动拧旋钮调速,会一边看转速表一边拧,快了就减一点,慢了就加一点;PID 就是自动完成这个 “看偏差→调输出” 的过程,而且比人更精准、更快速、更稳定。
举一个简单的例子:在用淋浴洗澡调节水温的时候,首先心里先有个想要的温度(比如 40℃); 用手试一下当前水温,发现有点凉; 往热水方向拧一点阀门,等几秒再试; 如果还凉就再拧一点,如果烫了就往回拧一点; 反复调整,直到水温稳定在你想要的温度。 这个 “定目标→测实际→比偏差→调输出→稳目标” 的过程,就是一次闭环控制。而 PID,就是把这个人工调节的过程,变成一套数学算法,让单片机、控制器自动完成这件事。


一、入门:P、I、D 是什么,三个环节到底在干嘛

PID 由比例(P)、积分(I)、微分(D)三个环节组成,每个环节分工明确,是「缺什么补什么」的关系,不是三个都必须用。

1. P(比例)环节:系统的即时驱动力

  • 本质:误差有多大,控制力度就有多大,误差一出现立刻产生反向拉力。
  • 作用:决定系统响应速度,是整个控制的基础骨架。
  • 去掉 P 会怎样:系统失去最直接的调节力,响应会极其迟缓,光靠积分慢慢爬升,很久才能接近目标值

2. I(积分)环节:稳态精度的保障

  • 本质:对历史误差持续累加,只要误差不为零,控制量就一直增加 / 减小,直到把误差彻底消除。
  • 作用:消除稳态误差(静差)。比如电机受摩擦力影响,纯 P 控制永远达不到目标转速,加积分就能慢慢把偏差补回来。
  • 去掉 I 会怎样:系统最终会稳定在离目标值有偏差的位置,负载越大,静差越大。

3. D(微分)环节:动态过程的阻尼器

  • 本质:看误差的变化趋势,误差增长越快,反向制动力度越强,相当于 “提前刹车”。
  • 作用:抑制超调、减少振荡、缩短调节时间。
  • 去掉 D 会怎样:系统阻尼不足,到达目标值时刹不住车,容易冲过目标,形成来回振荡,调节时间变长。

P 管「现在」,快速拉偏差; I 管「过去」,彻底消静差; D 管「未来」,提前防超调。

这是最基础的原理版本,对应位置式 PID 公式:u(k) = Kₚ e(k) + Kᵢ Σ₍ᵢ₌₀₎ᵏ e(i) + K_d [e(k)−e(k−1)]

e(k)指当前误差,当前误差为设定的目标值减去当前的实际值

对于第一部分可能存疑的讲解

前置认知 1:两种误差 —— 动态误差与稳态误差

很多人分不清 “普通误差” 和 “静差”,其实按时间阶段一分就清楚:

  • 动态误差:系统还在变化、还没稳定下来时的误差。比如电机刚启动、正在往目标位置转的过程中,偏差一直在缩小,这时候的误差都是动态误差。
  • 稳态误差(静差):系统已经稳定下来、不再大幅变化后,依然残留的固定偏差。比如电机转了半天,最终稳稳停在离目标位置差 5 个脉冲的地方,不多也不少,这 5 个脉冲就是静差。

PID 三个环节里,P 和 D 主要管动态过程,I 专门管稳态静差。

前置认知 2:离散采样 —— 为什么公式里总有个 “k”

现实里的温度、位置、速度都是连续变化的,但单片机是数字芯片,不能连续不停地计算,只能每隔固定时间读一次传感器、算一次 PID、输出一次控制量。这个固定的时间间隔叫采样周期(比如你代码里的 40ms)。

我们把每一次采样计算的时刻按顺序编号:第 0 次、第 1 次、第 2 次…… 第 k 次,这个k就是 “第 k 个采样时刻” 的意思。

  • e(k):第 k 次采样时,算出来的当前误差
  • e(k-1):上一次,也就是第 k-1 次采样时的误差
  • u(k):第 k 次采样时,PID 最终输出的控制量

所有离散 PID 公式,本质都是 “每隔一个采样周期,算一次这三个数”。对应到你的 Keil 工程里,就是定时器中断每 40ms 进来一次,执行一遍 PID 计算。


PID 由比例(P)、积分(I)、微分(D)三个独立环节组成,每个环节各司其职,是「缺什么补什么」的关系,不是三个都必须用。每个环节都对应一个 “增益系数”(Kp、Ki、Kd),用来调节这个环节作用的强弱。

1. P(比例)环节:系统的即时驱动力

本质

误差有多大,控制力度就成比例地有多大。误差一出现,立刻产生反向的拉力,误差越大,拉得越狠。

系数 Kp(比例增益)

用来调节比例作用的强弱:

  • Kp 越大,同样的误差输出的控制力度就越大,系统响应越猛;
  • Kp 越小,控制力度越弱,系统响应越平缓。
作用

决定系统的响应速度,是整个控制系统的基础骨架。所有闭环控制都离不开比例环节,它是最直接、最快速的调节力。

去掉 P 会怎样

系统失去最核心的即时调节力,响应会极其迟缓。就像开车跟车时,不管差多远都只轻轻踩一点油门,要很久才能跟上前车,光靠积分慢慢爬升,系统几乎没有动态响应能力。

初学者核心疑问:把 Kp 调得无限大,静差不就消失了?

不能,这是纯 P 控制的固有缺陷。原因很简单:控制量和误差成正比,控制量 = Kp × 误差。如果误差为 0,控制量就为 0。 但真实系统里有摩擦力、负载阻力,控制量为 0 的话,电机根本转不动,必然会停在 “误差不大不小、控制量刚好能克服阻力” 的位置,误差永远不会为 0。 Kp 越大,这个静差会越小,但永远不可能彻底消除 ——Kp 大到一定程度,系统就会开始振荡,反而不稳定了。

2. I(积分)环节:稳态精度的保障

本质

对历史所有误差持续累加,只要误差不为零,控制量就一直增加 / 减小,一点点把偏差磨平,直到误差彻底为零才停止。

系数 Ki(积分增益)

用来调节积分累积的速度:

  • Ki 越大,积分累积越快,消除静差的速度越快;
  • Ki 越小,积分累积越慢,消除静差越平缓。
作用

专门消除稳态误差(静差)。这是比例环节做不到的事。比如电机受摩擦力影响,纯 P 控制永远达不到目标位置,加积分就能通过持续累积小误差,慢慢把偏差补回来,最终精准停在目标位置。

去掉 I 会怎样

系统最终会稳定在离目标值有固定偏差的位置,负载越大、摩擦力越大,静差就越大。

初学者核心疑问:积分不是高数里的曲线面积吗?为什么这里是加起来?

本质是一回事,只是连续和离散的区别:

  • 高数里的连续积分,是对连续时间的误差曲线求面积;
  • 单片机里的离散积分,是每隔一个采样周期加一次误差,用 “一次次累加” 近似代替 “连续面积”。

采样周期越短,离散累加就越接近真实的连续积分。对应到代码里,就是一个变量每次都加上当前误差:ErrorInt += Error0,这行代码就是在做积分。

3. D(微分)环节:动态过程的阻尼器

本质不看误差本身多大,看误差变化得有多快。误差增长越快,反向的制动力度就越强,相当于 “提前刹车”—— 不等误差变大,就提前把势头压下去。
系数 Kd(微分增益)

用来调节阻尼作用的强弱:

  • Kd 越大,阻尼越强,抑制超调和振荡的效果越明显;
  • Kd 越小,阻尼越弱,系统越容易超调振荡。
作用

抑制超调、减少振荡、缩短调节时间。系统惯性越大、越容易冲过目标,微分环节的作用就越重要。

去掉 D 会怎样

系统阻尼不足,到达目标值时刹不住车,容易冲过目标值,然后再往回修正,形成来回振荡,调节时间大幅变长。就像汽车没有减震器,过一个坑会上下弹跳很久才能平稳。

初学者核心疑问:D 越大阻尼越强,那 D 越大越好?

绝对不是,D 是典型的双刃剑。微分的本质是 “变化率”,信号变化越快,微分输出越大。真实传感器信号里必然混有高频噪声(电磁干扰、机械振动),这些噪声跳变极快、变化率极大,Kd 越大,噪声就被放得越大。 D 太大的后果:电机出现高频抖振、滋滋响,执行器频繁来回动作,不仅控制精度全失,还会磨损机械结构。所以工程上用微分,一定会配合滤波措施,而且 Kd 绝不会往大了调。

不是所有系统都要用全 PID,按需组合即可:

  • 只要求能动、允许有偏差 → 纯 P 控制
  • 要求无静差、信号噪声大 → PI 控制(工业 80% 常规场景的首选)
  • 大惯性、允许有静差 → PD 控制
  • 大惯性 + 要求无静差 + 要求小超调 → 全 PID 控制
补充内容 :为什么叫 “位置式” PID

很多人会疑惑 “是不是只能用来控位置”,其实是按输出形式命名的:

  • 它输出的是控制量的绝对数值(比如 PWM 占空比 65%、阀门开度 45°),直接对应执行器的最终工作位置 / 状态,所以叫 “位置式”。
  • 它不仅能控位置,调速、控温、控压都可以用,“位置式” 描述的是输出的形态,不是控制的对象。

为什么固定线性 PID 不可能全工况最优?

线性 PID 的所有理论分析、参数整定,都建立在被控对象是线性定常系统这个大前提上。但实际工程中的电机、阀门、机械机构全都是非线性系统,只是在某一个小的工作点附近,可以近似成线性模型。 不同转速、不同负载,对应不同的工作点,对应不同的线性化模型,自然就对应不同的最优 PID 参数。用一组固定参数去覆盖全工况,本质上就是用一个线性模型去拟合所有非线性区间,必然有的工况偏快、有的工况偏慢,不可能处处最优。


附:位置式 PID 公式完整拆解

这是最基础的位置式 PID 公式,对应你代码里的原始版本:

u(k) = Kₚ · e(k) + Kᵢ · Σ₍ᵢ₌₀₎ᵏ e(i) + K_d · [e(k) − e(k−1)]

我们把它拆成三部分,和上面讲的一一对应:

  1. 比例项:Kp * e(k)→ 当前误差乘以比例系数,即时拉力
  2. 积分项:Ki * 所有历史误差的和→ 误差累加乘以积分系数,消除静差
  3. 微分项:Kd * (本次误差 - 上次误差)→ 误差变化量乘以微分系数,提供阻尼

对应到 C 代码里,就是三行计算加一行合成:

// 比例项 float p_out = Kp * Error0; // 积分项 ErrorInt += Error0; float i_out = Ki * ErrorInt; // 微分项 float d_out = Kd * (Error0 - Error1); // 合成输出 Out = p_out + i_out + d_out;

这就是 PID 从原理→公式→代码的完整对应关系。

到这里,我们已经把 PID 三个环节的作用原理、离散公式和最基础的 C 代码实现全部对应了起来。你在 Keil 工程里写的、放在 40ms 定时器中断里的这段计算逻辑,其实是 PID 所有实现形式中最经典、最贴合数学定义的一种 ——位置式 PID。它直观易懂,是所有人入门 PID 的起点。

但当你把这个基础版本真正烧到单片机里、接上电机跑起来就会发现:理想很丰满,现实很骨感。最典型的问题就是启动时严重超调、负载扰动后长时间回不来,这其中最核心的元凶,就是我们之前提到过的「积分饱和」。而位置式 PID 的结构本身,天生就容易滋生这个问题。

PID 算法发展到今天,并没有停留在课本里的基础公式上。为了解决真实工程里的各类痛点、适配不同的被控对象,它演化出了多种实现结构,其中和位置式 PID 并列、占据了工业现场绝大多数应用的另一大核心分支,就是增量式 PID。

二、位置式PID与增量式PID

1. 位置式 PID:输出绝对控制量

位置式PID的本质是输出第 k 时刻控制量的最终绝对值,数值直接对应执行器的工作状态(比如 PWM 占空比 65%、阀门开度 45°),拿到就能直接驱动执行器。

核心公式:

u(k) = Kp * e(k) + Ki * ∑_{i=0}^k e(i) + Kd * [e(k)-e(k-1)]

// 1. 更新误差 Error1 = Error0; Error0 = Target - Actual; // 2. 独立积分累加器 ErrorInt += Error0; // 3. 三项合成输出 Out = Kp * Error0 + Ki * ErrorInt + Kd * (Error0 - Error1); // 4. 输出限幅(对应执行器饱和) if(Out > 100) Out = 100; if(Out < -100) Out = -100; // 5. 输出到执行器 Motor_SetPWM(Out);
核心特征
  • 有一个独立于输出的积分累加器变量ErrorInt,专门保存历史误差的总和;
  • 输出限幅只作用在最终的Out上,不影响内部积分器的累加。
优缺点
  • 优点:概念直观易懂,定位精度高,直接对应执行器最终状态;
  • 缺点:独立积分器天生容易积分饱和,大偏差启动 / 扰动时超调严重;控制器故障时输出突变,可能冲击执行器。

2. 增量式 PID:输出变化控制量

增量式 PID 是工业现场调速类系统的首选,它不直接输出控制量的最终值,只输出相对于上一时刻的变化量。他的本质是输出第 k 时刻的控制量增量 Δu (k),需要叠加到上一时刻的控制量 u (k-1) 上,才能得到最终的 u (k)。
Δu (k) = u (k) - u (k-1)

把位置式公式代入上式,把 k 和 k-1 时刻的 u 相减,就能推导出增量式公式:

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

可以看到,增量式里不再有 “历史误差总和”,只用最近三次的误差就能计算出变化量。

// 1. 更新误差历史:需要保存连续三次误差 Error2 = Error1; Error1 = Error0; Error0 = Target - Actual; // 2. 计算控制量增量 float delta_u = Kp*(Error0 - Error1) + Ki*Error0 + Kd*(Error0 - 2*Error1 + Error2); // 3. 增量累加到上一次输出,得到当前总控制量 Out += delta_u; // 4. 输出限幅 if(Out > 100) Out = 100; if(Out < -100) Out = -100; // 5. 输出到执行器 Motor_SetPWM(Out);
核心特征
  • 没有独立的积分累加器变量,积分作用隐含在Out += delta_u的递推过程中;
  • 控制器保存的不是 “积分总和”,而是上一时刻的最终输出值Out。
优缺点
  • 优点:输出是增量,误差动作影响小;天然抗积分饱和;手动 / 自动切换时冲击小;
  • 缺点:本身只有变化量,需要执行器自带积分特性(如步进电机)才能精确定位;静态精度略低于位置式。

3. 本质辨析:为什么增量式天然抗积分饱和

位置式:积分器 “后台偷偷攒”

位置式的积分器ErrorInt和最终输出Out是分开的。输出被限幅卡住时,积分器还在继续累加误差,会偷偷堆积大量 “超额积分”。 比如执行器上限 100,计算出的 Out 已经到 120 被限成 100,但 ErrorInt 还在从 200 涨到 300、400。等误差反向变成负的,要先把这几百的超额积分消耗完,Out 才能降到 100 以下,退出饱和。这就是积分饱和导致超调、拖尾的根源。

增量式:积分 “前台直接显”

增量式没有独立积分器,积分的载体就是输出变量Out本身。输出被限幅卡住时,下一轮计算的基准就是限幅后的值,不会额外堆积积分。 比如 Out 被限在 100,下一轮计算 delta_u 时,是在 100 的基础上加,加完还是超 100 就继续限在 100,控制器里永远只存 100 这个值,不会偷偷多出几百的超额积分。等误差反向,delta_u 立刻变成负的,Out 直接从 100 往下降,立刻就能退出饱和。

注解:增量式不是 “没有积分累积”,只是积分的存在形式变了单看 Δu (k) 的计算公式,确实只用到最近三次误差,没有显式的历史误差求和;但最终作用在执行器上的总控制量 u (k),本质上是从初始时刻到当前所有增量的一步步累加:

u (k) = u (0) + ∑_{i=1}^k Δu (i)

积分环节并没有消失,而是从「直接累加误差」的显式积分器,变成了「通过输出递推间接实现」的隐式积分器。我们说增量式 “没有独立积分累加器”,指的是没有单独保存 “误差总和” 的变量,不代表它没有积分作用 —— 恰恰相反,它的积分作用贯穿在每一次的输出递推里。

也正是因为积分的载体从 “独立的误差变量” 变成了 “输出变量本身”,输出限幅才能直接钳位住积分的累积过程,不会在后台偷偷堆积超额积分,这才是增量式天然抗积分饱和的核心根源。

在这一部分中,我最开始学习的时候也出现了一些理解错误,如:

1.对积分饱和产生前提的认知缺失,我当时认为的积分饱和出现的状况是“实际值和目标值一直存在一个误差,积分项一直累计出现的状况”,但积分饱和的核心前提是执行器输出饱和。单纯的误差累积是积分环节的正常工作状态;只有当控制量超出执行器极限、执行器不再随误差增大而变化,但积分项仍在继续累积时,才叫积分饱和。

2.对增量式为什么能抗积分饱和理解错误,我当时认为“增量式 PID 中操控的误差数据只是局部的,而位置式 PID 操控的数据是全局的,积分项累加相对于增量式较多,因此更容易出现积分饱和状况”

正确结论是增量式最终的总控制量本质也是所有历史增量的全局累加,和位置式一样包含完整的积分作用。两者的核心区别是积分的载体和限幅的作用位置不同:
  • 位置式:有独立的误差积分器变量,输出限幅只截断最终输出,不影响内部积分器,积分会在后台偷偷超额堆积;
  • 增量式:积分作用隐含在输出递推过程中,输出限幅直接钳位住积分的载体,不会额外堆积超额积分。

3.对两种 PID 优缺点的知识空白

核心盲区

  • 不知道位置式的核心优势是定位精度高、缺点是易积分饱和;
  • 不知道增量式的核心优势是抗饱和、切换冲击小,缺点是本身不能直接输出绝对位置;
  • 无法对应到 “定位置用位置式、定速度用增量式” 的工程选型逻辑。

三、积分环节的三大改进:攻克积分饱和难题

上一部分我们讲到,位置式 PID 因为独立积分器的存在,天生容易出现积分饱和 —— 大偏差启动、负载突变时,积分器在后台超额累积,导致系统超调严重、恢复拖尾。但工程上很多定位场景又必须用位置式来保证绝对精度,这时候就需要对积分环节做针对性改进。

针对积分饱和问题,工业上有三种经典的改进算法,按实现复杂度和控制效果依次是:积分限幅、积分分离、变速积分。它们都在位置式 PID 的框架内,通过约束积分器的行为,在尽量保留积分消静差能力的同时,最大程度削弱积分饱和的影响。


前置:再明确积分饱和的根源

位置式 PID 中,独立积分器ErrorInt不受输出限幅约束:输出Out被执行器上限卡住时,积分器还在持续累加误差,偷偷堆积大量 “超额积分”。等误差反向后,必须先消耗完这些超额积分,输出才能退出饱和区,最终表现为严重超调、长时间拖尾。

所有积分改进算法的核心思路完全一致:约束积分器在大偏差阶段的累积行为,不让它攒出太多超额值。


1. 积分限幅:最简单的入门级改进

本质

不是只限制最终输出Out,而是直接给积分累加器本身设置上下限,从源头卡住积分的最大累积量。 原始位置式是 “输出限幅、积分不管”,积分限幅是 “直接限积分本身”。

核心逻辑

积分项的最大输出,不应该超过执行器的最大输出范围。反过来推算,积分累加器的最大值 = 执行器输出上限 ÷ Ki。 比如执行器上限 100,Ki=0.5,那ErrorInt最大就不能超过 200;否则积分项输出就超过 100,超出的部分全是无效的饱和量。

工程经验:一般不会卡到 100%,留 10%~20% 的动态余量给比例项和微分项,避免大偏差时输出直接顶满。

代码实现(可直接加入你的位置式 PID)
ErrorInt += Error0; // 积分限幅:±80为积分项输出上限,留20%余量给比例、微分 if(ErrorInt > 80/Ki) ErrorInt = 80/Ki; if(ErrorInt < -80/Ki) ErrorInt = -80/Ki;
优缺点
  • 优点:实现最简单,只加两行代码,改动最小,是所有位置式 PID 的基础防护;
  • 缺点:比较粗暴,大偏差时积分依然在累积,只是到顶就停,依然存在一定程度的饱和,效果有限。
适用场景

负载变化小、启动不频繁、对超调要求不高的简单系统。


2. 积分分离:工程最常用的改进方案

本质

设置一个误差阈值,大偏差阶段直接关闭积分,只用 PD 控制快速收敛;偏差缩小到阈值以内后,再投入积分消除静差。 从根源上避免了大偏差阶段的积分累积,核心思路是「该用的时候用,不该用的时候关掉」。

核心原理

大偏差时,系统的首要任务是快速把偏差拉回来,这时候比例 + 微分是主力,积分不仅帮不上忙,还会因为持续累积导致饱和超调,纯属添乱。 等偏差已经很小、系统接近稳态了,PD 消不掉的静差,再交给积分来慢慢磨。两个阶段各司其职。

代码实现
#define ERR_THRESHOLD 50 // 积分分离阈值,根据实际工况调整 if( abs(Error0) <= ERR_THRESHOLD ) { // 小偏差:投入积分,消除静差 ErrorInt += Error0; } else { // 大偏差:切除积分,避免饱和 ErrorInt = 0; }
关键参数:阈值怎么选
  • 阈值太大:大偏差时积分还在工作,分离效果差,依然饱和;
  • 阈值太小:积分投入太晚,稳态误差消除慢,甚至长时间达不到目标。
  • 经验值:一般设在满量程的 10%~20%,比如总行程 800 脉冲,阈值设 50~100。
优缺点
  • 优点:效果明显优于积分限幅,启动、阶跃时的超调量大幅下降;实现难度中等,逻辑清晰;
  • 缺点:开关式切换,积分投入瞬间有阶跃,可能引起小幅的输出波动。
适用场景

启动频繁、负载变化大、对超调要求较高的系统,是工业现场性价比最高的首选方案。


3. 变速积分:控制品质最高的平滑方案

本质

不是简单的 “开 / 关” 二值逻辑,而是用一个连续的加权系数,让积分强度随误差大小平滑变化:误差越大,积分增益越弱;误差越小,积分增益越强。 全程没有硬开关点,实现平滑过渡,从根源上避免了积分分离的阶跃波动。

核心原理
  • 大偏差:积分权重趋近于 0,以 PD 为主,快速收敛,几乎不累积饱和;
  • 中等偏差:积分权重线性变化,平滑过渡,没有突变;
  • 小偏差:积分权重趋近于 1,全积分投入,快速消除静差。
代码实现
#define ERR_THRESHOLD 50 // 积分全投入的阈值 float f; // 积分加权系数,范围0~1 if( abs(Error0) <= ERR_THRESHOLD ) { f = 1.0; // 小偏差,全积分工作 } else if( abs(Error0) <= 2*ERR_THRESHOLD ) { // 中间区间,线性平滑过渡 f = ( 2*ERR_THRESHOLD - abs(Error0) ) / ERR_THRESHOLD; } else { f = 0; // 大偏差,积分完全关闭 } // 加权后的积分累加 ErrorInt += f * Error0;
优缺点
  • 优点:没有开关突变,调节过程平滑,超调量最小,控制品质最高;
  • 缺点:实现稍复杂,参数更多,需要调试阈值和过渡区间。
适用场景

对平稳性要求高、超调要求严格的高精度控制系统。

四、微分环节的两大改进:从理想到工程可用

上一部分我们解决了积分环节的「积分饱和」通病,这一部分我们来看微分环节。理论上微分能提供超前相位、抑制超调,是改善系统动态性能的核心手段,但理想微分在真实工程里几乎从来不用—— 它有一个致命的先天缺陷,就是对高频噪声的无限放大。

工程上所有用到微分的场景,用的都是经过改造的「工程实用微分」。其中最经典、最通用的两大改进就是:不完全微分和微分先行。前者解决微分本身的噪声问题,后者解决设定值跳变的冲击问题。


4.1 前置:理想微分为什么工程上用不了?

本质:天生的高频噪声放大器

理想微分的传递函数是G(s) = T_d · s,代入正弦信号分析,它的幅值增益和信号频率成正比:

|G(jω)| = T_d · ω 信号变化越快(频率越高),微分的放大倍数就越大;当频率趋近无穷大时,增益也趋近无穷大。

工程后果:执行器高频抖振

真实系统里,所有传感器信号都必然叠加着高频噪声:电磁干扰、电刷火花、机械振动、采样毛刺,幅度通常只有满量程的 0.1%~1%,肉眼几乎看不出来。 但经过理想微分后,这些高频噪声会被放大几十甚至上百倍,原本毫伏级的噪声,直接变成伏级的控制量波动。

  • 现象:电机出现高频滋滋响、执行器频繁来回抖振;
  • 危害:控制精度完全失效,加速机械磨损,甚至烧毁驱动电路。

这就是理想微分只能停留在课本里,工程上必须改造的根本原因。


4.2 不完全微分:工程微分的标配

这是所有微分应用的默认标准形式,只要用微分,就必须用不完全微分。

本质:给微分串一个一阶低通滤波器

在理想微分的输出端,串联一个一阶惯性低通滤波器,构成不完全微分。 连续域传递函数:

G(s) = (T_d · s) / (1 + (T_d / N) s)

  • 分子:理想微分,提供相位超前和阻尼;
  • 分母:一阶低通,压制高频增益。
工作原理

分频段看特性:

  1. 低频段:信号变化慢,低通近似直通,不完全微分的作用和理想微分几乎一致,正常提供 90° 相位超前,阻尼效果基本不受影响;
  2. 高频段:低通起强衰减作用,增益不再随频率无限上升,最终被限制在 N 倍,大幅抑制高频噪声。
离散代码实现(对应你的工程代码)
// 滤波系数 a:0~1,越大滤波越强,工程常用 0.85~0.95 float a = 0.9; DifOut = (1 - a) * Kd * (Error0 - Error1) + a * DifOut;

本质说明:不是 “两次微分误差的加权平均”,而是对理想微分的输出结果做一阶低通平滑。滤波对象是微分的输出,不是误差本身。

代价与折中

低通滤波器本身会引入相位滞后,抵消掉微分的一部分相位超前量,最终净相位超前小于 90°,等效于:

  • 阻尼强度略有下降;
  • 阶跃响应峰值降低、出现时间略延后。

这是为了让微分能在有噪声的真实环境里工作,必须付出的代价,属于典型的「噪声抑制」和「响应速度」的工程折中。

参数选择

公式里的 N(或离散的滤波系数 a)是调节折中程度的旋钮:

表格

N 取值滤波强度相位滞后接近理想微分程度适用场景
5~8强大弱工业现场、电磁干扰强
8~12中中等中等绝大多数常规场景(默认值)
12~20弱小强实验室、高精度低噪声传感器

4.3 微分先行:随动系统的专属优化

解决的问题:设定值阶跃冲击

标准 PID 是对误差e(k) = sp(k) - pv(k)做微分。当设定值 sp 阶跃跳变(比如从 0 直接跳到 100),误差瞬间从 0 变 100,微分输出一个极窄极高的尖峰脉冲,直接把执行器打满,造成:

  • 机械冲击,损坏传动结构;
  • 严重超调,系统震荡。

微分先行就是专门解决这个问题的。

本质:只对反馈量做微分,不对设定值做微分

把微分的作用对象从「误差」改成「只对反馈量 pv」,设定值的跳变不会体现在微分输出上。

  • 标准微分:D = K_d · [e(k)-e(k-1)] = K_d · [Δsp - Δpv]
  • 微分先行:D = K_d · [pv(k-1)-pv(k)] = -K_d · Δpv

设定值跳变时,只有反馈的平滑跟随过程,没有尖峰冲击。

代码实现
// 微分先行:只对实际值Actual做微分,不对目标值Target做微分 float a = 0.9; DifOut = (1 - a) * Kd * (LastActual - Actual) + a * DifOut; LastActual = Actual; // 保存上一时刻的实际值
关键认知:定值系统下微分先行没用

如果是恒温、恒压、稳态调速这类设定值固定不变的系统,微分先行和标准微分效果完全没有区别。 原因很简单:sp 恒定不变时,Δe = -Δpv,误差的变化率和反馈量的变化率大小完全相等,只是符号相反,而符号不影响阻尼效果。

一句话:微分先行只在设定值频繁变化的随动系统(比如位置伺服、轨迹跟踪、机器人关节)里才有价值,定值系统用它纯属于多此一举。


4.4 两大改进的本质区别与选型

很多初学者容易把这两个混为一谈,其实它们解决的根本不是一个层面的问题:

表格

改进方案解决的核心问题优化层面适用场景使用地位
不完全微分微分环节高频噪声放大信号特性层面所有用到微分的场景工程标配,凡用微分必加
微分先行设定值阶跃跳变的输出冲击输入特性层面设定值频繁变动的随动系统可选优化,定值系统不用
工程组合原则
  • 只用微分,就必须加不完全微分;
  • 只有设定值会频繁跳变,才需要追加微分先行;
  • 两者可以叠加使用:先做微分先行(只对反馈微分),再做不完全微分(低通滤波),是高精度随动系统的标准组合。

我在该部分学习过程中的疑惑与解答:

1.理想微分的致命缺陷是:对高频噪声的增益趋近于无穷大。 工程中所有传感器信号都必然带有高频电磁噪声、机械振动噪声,理想微分的传递函数是G(s)=T_d s,频率越高增益越大,毫伏级的噪声会被放大成伏级的控制量波动,直接导致执行器高频抖振、磨损加剧,甚至系统失稳。

2.微分先行的适用场景:

微分先行专门解决的是:设定值阶跃跳变时,标准 PID 的微分环节输出尖峰脉冲,冲击执行器的问题。标准 PID 对误差e(k)=sp(k)-pv(k) 做微分。当设定值 sp 从 0 直接跳到 100,误差瞬间从 0 变 100,微分输出一个极窄极高的脉冲,直接把执行器打满,造成机械冲击、严重超调,甚至损坏设备。 微分先行只对反馈量 pv 做微分,不对设定值 sp 做微分。sp 跳变时,误差突变不会体现在微分输出上,只会有平滑的跟随过程,没有冲击。

3.如果是定值控制系统(设定值固定不变,比如恒温、恒压、稳态调速),微分先行和标准全 PID 的微分效果有没有区别?为什么?

定值控制系统中,sp 恒定不变,因此Δe(k) = Δ(sp-pv) = -Δpv(k),误差的变化率和反馈量的变化率大小完全相等,只是符号相反,而符号不影响阻尼效果。 所以定值系统下,微分先行和标准 PID 的微分效果没有任何区别,原因是设定值不动,对谁微分结果都一样。微分先行只在随动系统(设定值频繁变化,比如位置伺服、轨迹跟踪)中才有价值,定值系统用它纯属于多此一举。

补充:不完全微分的固有代价与工程折中

很多初学者刚理解不完全微分的好处后,又会发现:加了低通滤波之后,微分的反应好像变慢了,阶跃输入时输出峰值变低、出现得更晚。这不是代码写错了,也不是算法的 bug,这是一阶低通滤波本身的物理特性带来的必然结果,是我们为了抑制噪声主动付出的代价。

一、缺陷的本质:不是纯时延,是相位超前量被抵消

很多人会说 “不完全微分有延迟”,这个表述不准确。 理想微分的核心价值,是能给系统提供+90° 的相位超前—— 误差还在上升时,微分就提前输出反向制动力,相当于 “提前刹车”,这也是它能抑制超调的根源。

而我们串联的一阶低通滤波器,本身固有的特性是相位滞后:输出信号的相位会落后于输入信号。它串在微分后面,就会抵消掉一部分微分的相位超前,最终整个微分环节的净相位超前量小于 90°。

反映在实际效果上:

  • 不是整个信号晚了几秒,而是微分的 “提前制动” 效果打了折扣,抑制超调的能力略有下降;
  • 阶跃输入时,理想微分瞬间输出一个极高的尖峰,不完全微分的输出峰值更低、峰值出现的时刻略晚。
二、影响程度:由参数精准控制,大部分场景可忽略

这个滞后影响有多大,完全由滤波参数控制,不是固定值。对应不完全微分公式里的参数 N(离散代码里对应滤波系数 a),它就是调节「噪声抑制强度」和「相位滞后程度」的旋钮:

  • N 越小(滤波越强):相位滞后越大,阻尼效果下降越明显,但噪声压得越低;
  • N 越大(滤波越弱):相位滞后越小,越接近理想微分,但噪声抑制效果越差。

工程经验:常规电机调速、位置伺服场景,取N=8~10(对应离散系数a=0.85~0.9)是综合性价比最高的区间。这个参数下,相位滞后的影响非常小,几乎感知不到,同时噪声抑制足够,是绝大多数工业场景的默认选择。

三、工程上的弥补手段

不需要因噎废食,行业有成熟的手段抵消这个副作用:

  1. 适当提高微分增益K_d低通会让微分的整体幅值增益略有下降,只需要适当调大一点K_d,就能弥补幅值损失,部分抵消相位滞后带来的阻尼下降。这是最常用、最简单的手段。
  2. 适当提高采样频率离散化本身会给微分环节带来额外的相位滞后。在硬件允许的范围内,适当提高采样频率,能减小离散化误差,间接改善微分的响应速度。
  3. 分工明确,不重复背锅记住两个微分改进的分工边界:
  • 不完全微分:只管解决「传感器噪声放大」问题;
  • 微分先行:只管解决「设定值阶跃冲击」问题。 不要指望不完全微分同时解决响应速度问题,设定值频繁变动的场景,配合微分先行使用,就能兼顾平滑性和跟随速度。
四、核心工程思维:没有完美算法,只有合适的折中

这是贯穿整个 PID 学习的核心逻辑:

  • 积分环节的改进,是在「消除静差」和「避免积分饱和」之间折中;
  • 微分环节的改进,是在「提供阻尼」和「抑制噪声」之间折中;
  • 位置式和增量式的选择,是在「定位精度」和「抗饱和安全性」之间折中。

五、工程落地避坑:非线性特性与工况漂移

前面我们讲的所有 PID 原理、公式和改进算法,都建立在「被控对象和执行器是线性定常系统」这个理想前提上。但真实工程里,没有绝对线性的硬件。电机的启动死区、摩擦非线性、传感器零点漂移,负载变化带来的特性偏移,这些非线性和时变特性,才是现场调 PID 越调越乱的核心根源。

很多初学者调了半天参数,系统还是振荡、还是有静差,最后发现问题根本不在 PID 算法,而在硬件的非理想特性。这一部分我们就从理想模型落地到真实硬件,讲透两个最常见的执行器非线性问题,以及工况漂移带来的参数失配。


5.1 输入死区:最容易引发振荡的物理非线性

本质定义

输入死区是执行器固有的输入非线性特性:当输入控制量的绝对值小于某一阈值时,执行器完全没有输出、完全不动作;只有输入超过这个阈值,输出才随输入线性变化。 通俗说就是:控制量太小了,推不动,没反应。

来源
  • 电机:启动电压死区、静摩擦力矩,PWM 小于 10% 电机根本不转;
  • 阀门:启动压差、阀芯静摩擦,小开度时阀门打不开;
  • 机械结构:齿轮间隙、传动间隙,小角度输入全部被间隙吃掉。
核心危害:死区 + 积分 = 低频极限环振荡

这是工程上最常见的低频振荡根源,机理非常清晰:

  1. 误差较小时,控制量落在死区范围内,执行器不动,被控量不变,误差保持恒定;
  2. 但积分环节不会停,只要误差不为零就持续累积,控制量不断增大;
  3. 直到控制量冲出死区阈值,执行器突然动作,被控量快速变化,误差反向;
  4. 误差反向后,积分又开始反向累积,控制量减小,再次进入死区后执行器又停止;
  5. 如此往复循环,形成稳定的低频等幅极限环振荡,周期通常几秒到几十秒。

为什么纯 P 控制不会出现持续振荡? 比例输出和误差成正比,误差恒定则输出恒定。当误差小到控制量落在死区内,执行器不动,误差就不再变化,系统直接稳定在死区对应的误差范围内,不会持续累积,也就不会产生来回振荡。

典型误区:靠增大积分增益解决死区

这是初学者最容易踩的坑:死区导致有静差,就去调大 Ki。结果恰恰相反:Ki 越大,积分累积越快,冲出死区的时间越短,极限环振荡的频率越高、动态冲击越大,系统稳定性越差。 积分只能让死区带来的 “表观静差范围” 变小,但代价是引发持续振荡,属于饮鸩止渴。

工程解决方法:死区前馈补偿

最常用也最有效的方法,是在控制量上叠加一个等于死区阈值的偏置量,直接抵消死区的影响。

#define DEAD_ZONE 10 // 死区阈值,根据实际电机测试得到 // 死区补偿:输出不为零时,叠加死区偏置 if(Out > 0) Out += DEAD_ZONE; else if(Out < 0) Out -= DEAD_ZONE;
  • 原理:控制量为正时,提前加一个死区值,让输出刚一出现就能跨过死区;
  • 注意:这是前馈补偿,不是靠积分去硬扛,从根源上消除死区的非线性。

5.2 输出偏移:最容易被忽略的零点漂移

本质定义

输出偏移是系统的零点线性漂移特性:当输入控制量为 0 时,实际输出不为 0,存在一个固定的偏置量。 通俗说就是:零输入有输出,零点不准。

来源
  • 传感器:零点校准误差、温度漂移;
  • 放大器:运算放大器偏置电压;
  • 执行器:阀门关不严的漏流、电机零位不对。
核心特性

它属于线性零点偏移,不是非线性。整个输出曲线只是整体往上或往下平移了一段,斜率不变,没有死区那种 “推不动” 的拐点。

与积分环节的关系
  • 积分环节可以完全消除输出偏移的稳态影响:输出偏移相当于前向通道的常值扰动,积分可以通过累积误差,调整控制量的静态偏置来完全抵消它,最终稳态误差为零。
  • 但不建议全靠积分兜底:偏移会压缩控制量的动态范围,比如正偏移会让正向输出余量变小、负向余量变大;大偏移还可能导致系统提前进入饱和。如果偏移随温度、时间漂移,积分虽然能跟踪稳态,但动态过程会出现偏差。
工程建议

优先做硬件零点校准,把偏移控制在最小范围,再让积分处理剩余的小偏差,不要把所有问题都丢给积分。


5.3 工况漂移:为什么固定参数不能全工况最优

本质

PID 的所有理论分析、参数整定,都默认被控对象是线性定常系统。但真实的电机、阀门、机械机构,特性都会随工作状态变化:

  • 转速不同:反电动势系数、粘性摩擦系数不一样;
  • 负载不同:等效转动惯量、力矩特性不一样;
  • 温度不同:线圈电阻、润滑油粘度不一样。

不同的转速、负载、温度,对应不同的工作点。在每个工作点附近,系统可以近似成一个线性模型;但工作点变了,对应的线性模型参数就变了。

核心结论

所谓的「最优 PID 参数」,从来不是一个普适的最佳数值,而是某一个特定工作点、某一个特定性能指标下的最优解。

  • 它绑定具体的工作点(比如 1000 转、额定负载);
  • 它绑定具体的性能指标(比如超调≤5%、调节时间最短);
  • 它绑定近似线性的前提。

脱离工作点谈 “最优 PID 参数”,本身就是一句空话。

典型现象

这就是工程上 “高速稳如狗,低速乱振荡” 的根源: 按高速额定工况整定的 PID 参数,相位裕度充足、运行稳定;切换到低速重载后,被控对象模型漂移,等效时间常数变大、阻尼减弱,原来的参数就显得增益过高、阻尼不足,直接引发低频振荡。

反过来按低速整定的参数,高速下就会显得响应过慢、过于保守。

解决方向
  1. 增益调度:针对高速 / 低速、轻载 / 重载等典型工作点,分别整定最优 PID 参数,工况切换时自动调用对应参数。这是工业上最常用的方案,性价比最高。
  2. 自适应 PID:在线辨识系统模型参数,实时调整 PID 增益,始终保持最优阻尼比。适合工况大范围连续变化的场景。

我在该部分的疑惑与解答:

1. 输入死区:把固有物理缺陷当成人为设计的功能

错误认知:输入死区是人为给误差加一个可容忍区间,误差在范围内就输出置零,避免不必要的输出损耗。纠正:输入死区是执行器 / 被控对象固有的物理非线性特性:控制量小于某一阈值时,执行器完全没有输出、完全不动作,是客观存在的硬件缺陷,不是人为设计的算法功能。错误根源:把 “死区补偿算法” 和 “输入死区本身” 搞混,把硬件固有问题当成了主动设计的功能。

2. 输出偏移:定义完全颠倒

错误认知:输出偏移是输出不足以驱动时,适当增加一个输出值。纠正:输出偏移是系统的零点线性漂移特性:输入控制量为 0 时,实际输出不为 0,存在固定偏置。本质是 “零输入有输出,零点不准”,不是 “输出不够补输出”。错误根源:混淆了 “偏移现象” 和 “补偿手段”,把解决问题的方法当成了问题本身。

3.极限环振荡的成因判断错误

错误认知:死区 + 积分出现振荡是因为高频电磁脉冲、机械振动;甚至以为输入死区可以避免低频振荡。纠正:死区提供了 “停顿点”,积分提供了 “持续驱动力”,两者结合必然产生来回往复的低频等幅极限环振荡。输入死区恰恰是引发低频振荡的典型根源,不是避免振荡。错误根源:只看到死区 “小信号不动作” 的表面现象,没理解积分持续累积的内在逻辑,因果完全倒置。

4. 死区的解决方法完全错误

错误认知:输入死区可以通过增大积分增益来消除,积分越强,死区的影响越小。纠正:增大 Ki 不仅消除不了死区,反而会让积分累积更快,冲出死区的时间更短,导致极限环振荡的频率更高、动态冲击更大。死区的正确解法是死区前馈补偿(控制量叠加死区阈值偏置),不是靠堆积分增益。错误根源:误以为 “积分能消除所有静差”,忽略了死区是物理非线性,不是线性偏差,积分只会让问题更糟,属于饮鸩止渴。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进