【电赛/毕设终极杀器】超越 PID 与 LQR!控制界的黑魔法:自抗扰控制 (ADRC) 原理与 STM32 硬核部署指南

📅 2026/7/5 2:28:11 👁️ 阅读次数 📝 编程学习
【电赛/毕设终极杀器】超越 PID 与 LQR!控制界的黑魔法:自抗扰控制 (ADRC) 原理与 STM32 硬核部署指南

前言
凌晨 5 点,你的无人机终于能悬停了。但当你给无人机挂上一个待投放的小沙包时,原本完美的 PID 参数瞬间失效,无人机疯狂摇摆直至炸机。
为什么?
PID 的痛点:它只能“看到误差才去补救”,反应永远慢半拍;而且参数完全绑定了当前的重量和重心,重量一变,参数全废!
LQR 的痛点:它需要你写出绝对精确的“物理数学模型”。但现实中,地毯的摩擦力、电机的磨损、风的阻力,你怎么可能精确建模?!

有没有一种算法,既不需要精确的物理模型,又能瞬间把所有未知干扰(不管你是挂了重物,还是被大风吹)强行抵消掉?
有!它就是中国学者的骄傲、被誉为“面向 21 世纪的控制理论”——ADRC(自抗扰控制)
本文将带你跨越理论的鸿沟,用最直白的人话和短短几十行 C 代码,在 STM32 里装上这个工业界最顶级的“抗扰引擎”!

@TOC


一、 认知颠覆:ADRC 到底在干一件什么“神仙事”?

不管是系统内部的老化(电机没力气了),还是外部的干扰(大风吹、撞到石头),在 ADRC 的眼里,统统被打包成一个词——“总扰动(Total Disturbance)”

ADRC 的核心哲学:我不需要知道干扰是怎么来的,我只需要把它“看”出来,然后在它破坏系统之前,反向干掉它!

🏆 核心灵魂:扩张状态观测器(ESO)

这是 ADRC 最牛逼的地方。
假设你给电机发了 50 的 PWM,按照经验,电机应该转 100 圈/秒。
但是,传感器传回来的数据是 80 圈/秒。

  • PID 是怎么做的?“哦,差了 20 圈,我加大一点 PWM 试试。”

  • ESO(观测器)是怎么做的?“我发了 50 的力,你应该转 100 圈,但你只转了 80 圈。说明现实世界中,有一个等效于 -20圈 的‘未知妖孽(总扰动)’在阻碍你!

ESO 极其敏锐,它能在微秒级的时间内,实时计算出这个“总扰动”的大小!
既然知道了扰动有多大,接下来就太简单了:在原本的控制输出上,直接加上一个反向的力,把扰动“同等抵消”掉!这就是“自抗扰”。


二、 化繁为简:为什么我们要用 LADRC(线性自抗扰)?

如果你去查文献,标准的 ADRC 包含 TD(跟踪微分器)、NLSEF(非线性状态误差反馈)和 ESO。它足足有10 多个参数要调!在电赛四天三夜里,调这 10 个参数会让你精神分裂。

降维打击:高志强教授提出的 LADRC(线性自抗扰)!
高教授用极其巧妙的频域理论,把这 10 个玄学参数,强行缩减成了3 个具有明确物理意义的参数

  1. b0b0​
    (控制增益):代表你的系统“给多大推力,就有多大加速度”。这是唯一需要大概估算的物理量。
  2. ωoωo​
    (观测器带宽):代表 ESO “看”扰动的速度有多快。越大,抗干扰越敏锐(但太大容易引入传感器噪声)。
  3. ωcωc​
    (控制器带宽):代表系统追踪目标的速度有多快。越大,响应越快。

震撼事实:用了 LADRC,你调参就像调收音机频道一样简单,只需要拧

ωoωo​
ωcωc​
这两个旋钮,系统就能稳如磐石!

三、 STM32 纯 C 语言实战:二阶 LADRC 极速部署代码

别看论文里的矩阵微分方程吓人。在单片机的离散时间(

dtdt

)里,二阶 LADRC 仅仅是几个极简的迭代公式!

下面这段代码,完美适用于电机位置控制、倒立摆角度控制、无人机姿态控制(这些都是典型的二阶系统:输出受加速度控制)。

1. 参数与结构体定义

codeC

typedef struct { // 【需要你调的 3 个核心参数】 float wc; // 控制器带宽 (决定响应速度) float wo; // 观测器带宽 (决定抗干扰速度,通常设为 wc 的 3~5 倍) float b0; // 系统增益 (PWM -> 加速度的转换比例) // ESO 观测器增益 (根据 wo 自动计算,无需手调!) float beta1; float beta2; float beta3; // ESO 内部状态估计变量 float z1; // 估计的位置 (或角度) float z2; // 估计的速度 (或角速度) float z3; // !!!估计的总扰动!!! (ADRC的灵魂) float dt; // 运行周期 (如 0.005s) float u; // 最终的输出控制量 (PWM) } LADRC_TypeDef; /** * @brief LADRC 参数初始化 (自动计算观测器增益) */ void LADRC_Init(LADRC_TypeDef *adrc, float wc, float wo, float b0, float dt) { adrc->wc = wc; adrc->wo = wo; adrc->b0 = b0; adrc->dt = dt; // 核心黑魔法:基于带宽极点配置自动计算 beta 参数! adrc->beta1 = 3.0f * wo; adrc->beta2 = 3.0f * wo * wo; adrc->beta3 = wo * wo * wo; adrc->z1 = 0; adrc->z2 = 0; adrc->z3 = 0; adrc->u = 0; }

2. 核心控制执行函数(放进 5ms 定时器中断)

这段代码分两步:第一步让 ESO 观测出总扰动

z3z3​

,第二步利用

z3z3​

抵消扰动并输出控制量!

codeC

/** * @brief 执行一次 LADRC 计算 * @param target: 目标值 (期望角度/位置) * @param measure: 传感器真实测量值 * @retval 最终输出的控制量 (PWM) */ float LADRC_Calculate(LADRC_TypeDef *adrc, float target, float measure) { // ======================================================== // 第一步:线性扩张状态观测器 (LESO) - “火眼金睛”看透一切干扰 // ======================================================== float e = adrc->z1 - measure; // 观测值与真实值的误差 // 更新状态估计 (离散化欧拉积分) adrc->z1 += adrc->dt * (adrc->z2 - adrc->beta1 * e); adrc->z2 += adrc->dt * (adrc->z3 + adrc->b0 * adrc->u - adrc->beta2 * e); // 这里算出来的 z3,就是包含了摩擦力、风阻、负载变化的所有“总扰动”! adrc->z3 += adrc->dt * (-adrc->beta3 * e); // ======================================================== // 第二步:线性误差反馈控制 (LSEF) - 抵消扰动,精准打击 // ======================================================== // 1. 计算 PD 控制规律 (这里也利用了自动配置参数的黑魔法) float Kp = adrc->wc * adrc->wc; float Kd = 2.0f * adrc->wc; // 基础控制量 u0 (基于估计状态,因为经过ESO过滤,自带极强平滑效果) float u0 = Kp * (target - adrc->z1) - Kd * adrc->z2; // 2. 终极杀招:扰动补偿!!! // 无论外界怎么干扰,我直接减去观测到的总扰动 z3! adrc->u = (u0 - adrc->z3) / adrc->b0; // (可选) 加上输出限幅保护代码 // if(adrc->u > MAX_PWM) adrc->u = MAX_PWM; ... return adrc->u; }

看到没?!没有积分器(I),也就永远没有积分饱和、撞墙疯跑的危险!而且你连微分噪声都不用怕,因为 z2 是 ESO 自己推算出的丝滑微分信号,根本不是传感器原始数据求导来的!


四、 玄学破局:LADRC 怎么调参?(工业级套路)

PID 调参是门玄学,但 LADRC 调参是纯粹的工程学!

第一步:估算

b0b0​

(唯一需要试错的物理量)

  • 先随便给一个数(比如 1.0 或 10.0)。

  • 如果系统震荡得很厉害,

    b0b0​
    一点(欺骗系统说它自己很强,它输出的力就会变柔和)。
  • 如果系统反应迟钝像没吃饭一样,

    b0b0​
    一点。
  • 只要

    b0b0​
    调到了一个刚好不震荡的范围,剩下的事情就交给
    ωω
    了!

第二步:调节观测器

ωoωo​

和控制器

ωcωc​
  • 原则

    ωoωo​
    通常是
    ωcωc​
    3 到 5 倍。因为观测器必须比控制器“看”得快,系统才稳。
  • 操作:逐渐增大

    ωcωc​
    (比如从 5 慢慢加到 30),并保持
    ωo=4×ωcωo​=4×ωc​
  • 什么时候停?当你的电机开始发出“滋滋”的高频噪声时(说明

    ωoωo​
    太高,把传感器的底噪当成扰动放大了),立刻停止,并把带宽回调 20%。

大功告成!整个调参过程可能只需要 3 分钟,你的系统鲁棒性就能直接碾压调了 3 天的 PID!


五、 赛场实战:ADRC 降维打击的表现是什么样的?

如果你在电赛中选了两轮平衡自行车或者风力摆,在答辩现场:

  1. 评委要求:“在你的车上放一块 500g 的配重铁块。”

    • PID 队伍:重心大变,I 环积分缓慢累加,小车剧烈摇晃好几秒才勉强站住,甚至直接倒地。

    • ADRC 队伍:加上铁块的瞬间,ESO 在 5 毫秒内计算出 z3 扰动发生了突变,控制量

      uu
      瞬间补偿。肉眼看过去,小车几乎纹丝不动,仿佛铁块根本不存在!
  2. 评委要求:“用手拨一下无人机的机臂。”

    • ADRC 队伍:你的手会感觉到一种极度强烈的“肌肉抵抗感”,外力撤除瞬间,无人机毫无超调地死死钉回原点。

在你的《系统设计报告》上写下:

“本系统摒弃了传统 PID 对精确模型的依赖与积分饱和缺陷,采用二阶自抗扰控制器(LADRC)。利用扩张状态观测器(ESO)对系统内部耦合及外部气流扰动进行实时在线估计与前馈补偿,实现了变负载工况下的极高鲁棒性控制。”

评委看完,不仅国一稳了,甚至可能问你有没有兴趣读他的研究生!


结语

如果说 PID 是古典物理,LQR 是精英物理,那么 ADRC 就是现代工程控制领域的“黑客帝国”。

它打破了西方控制理论中“必须精确建立数学模型”的教条,用极具东方哲学意味的“见招拆招”思想,把所有未知的混沌与无序,全部打包成一个

z3z3​

,然后一剑封喉。

不要再让你的电机在微积分的误差中悲鸣了,用扩张状态观测器,去洞悉物理世界的真实吧!

预祝各位挑战控制巅峰的开发者:扰动秒抵消,悬停如定海神针,负载千变万化,系统稳如泰山!🏆