从PID到LADRC:一个电源工程师的实战升级笔记(以STM32控制Buck电路为例)
从PID到LADRC:一个电源工程师的实战升级笔记(以STM32控制Buck电路为例)
作为一名长期使用PID控制Buck电路的电源工程师,我曾在负载突变和输入电压波动时反复调试参数却收效甚微。直到接触LADRC(线性自抗扰控制),才真正解决了这些痛点。本文将分享我在STM32平台上实现LADRC的完整过程,包括算法离散化、C代码实现、定时器中断配置等实战细节,并通过示波器波形对比展示其抗扰优势。
1. 为什么PID在电源控制中会力不从心
Buck电路作为典型的非线性系统,其动态特性受多种因素影响。传统PID控制在稳态工况下表现尚可,但面对以下场景时往往捉襟见肘:
- 负载阶跃变化:当输出电流从10%突增至90%时,PID需要3-5个周期才能恢复稳定,导致输出电压跌落明显
- 输入电压波动:电网电压瞬变时,PID的积分项容易产生过调
- 参数敏感性:同一组PID参数在不同工作点可能表现迥异
// 典型PID实现代码(存在积分饱和问题) float PID_Update(PID_TypeDef *pid, float error) { pid->integral += error * pid->dt; pid->derivative = (error - pid->prev_error) / pid->dt; float output = pid->Kp * error + pid->Ki * pid->integral + pid->Kd * pid->derivative; pid->prev_error = error; return output; }提示:PID的积分项在扰动持续时容易累积,导致系统响应迟缓甚至振荡
2. LADRC的核心思想与优势
LADRC通过扩张状态观测器(ESO)将系统内外扰动统一估计并补偿,其架构包含三个关键部分:
| 模块 | 功能 | 实现要点 |
|---|---|---|
| LESO | 实时估计总扰动 | 需选择合适的观测器带宽wo |
| LSEF | 生成基本控制量 | 控制器带宽wc决定响应速度 |
| 扰动补偿 | 前馈抵消扰动 | 补偿系数b0需准确设置 |
实际测试对比(24V输入,12V/5A输出Buck电路):
- PID响应:负载阶跃时电压跌落1.2V,恢复时间8ms
- LADRC响应:电压跌落仅0.3V,恢复时间2ms
3. STM32上的LADRC实现细节
3.1 算法离散化(零阶保持法)
对于二阶系统,连续域状态方程离散化后得到:
% 连续系统矩阵 A = [0 1 0; 0 0 1; 0 0 0]; B = [0; b0; 0]; C = [1 0 0]; % 离散化(采样周期h=100us) h = 1e-4; Ad = expm(A*h); Bd = A\(Ad-eye(3))*B;对应的C语言实现:
void LESO_Update(float y, float u) { float e = y - z1; z1 += h * (z2 + beta1 * e); z2 += h * (z3 + beta2 * e + b0 * u); z3 += h * beta3 * e; }3.2 定时器与ADC配置要点
定时器设置:
- 使用TIM1产生PWM(频率100kHz)
- TIM2配置为100us中断用于控制算法
- 中断优先级高于ADC采样
ADC采样策略:
- 在PWM周期中点采样输出电压
- DMA传输+均值滤波(4次采样)
- 校准偏移电压(典型值±5mV)
// STM32CubeMX生成的PWM配置 htim1.Instance = TIM1; htim1.Init.Prescaler = 0; htim1.Init.CounterMode = TIM_COUNTERMODE_UP; htim1.Init.Period = 168-1; // 100kHz @168MHz htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);4. 参数整定实战经验
通过大量实验总结出以下调参步骤:
确定b0初值:
- 给Buck电路施加50%占空比阶跃
- 测量输出电压变化率dv/dt
- 计算:
b0 ≈ (Vin/L)*D*(1-D)
调节wc和wo:
- 初始设置wo=4*wc
- 逐步增加wc直到出现超调
- 回退20%作为最终值
微调指南:
- 输出电压抖动:减小wo
- 响应迟缓:增大wc
- 负载调整率差:检查b0准确性
实测参数示例(24V→12V/5A Buck):
b0 = 1.2e6 wc = 2000 wo = 8000 beta1 = 3*wo beta2 = 3*wo² beta3 = wo³5. 资源占用与优化技巧
在STM32F407(168MHz)上的实测数据:
| 项目 | PID方案 | LADRC方案 |
|---|---|---|
| CPU占用率 | 3% | 7% |
| RAM占用 | 128B | 320B |
| 代码体积 | 1.2KB | 2.8KB |
| 中断执行时间 | 8μs | 15μs |
优化建议:
- 使用ARM的DSP库加速浮点运算
- 将ESO状态变量转为Q15格式定点数
- 对于多相Buck,共用同一个ESO实例
// 定点数优化示例(Q15格式) int16_t z1_q15 = 0; int16_t b0_q15 = __SSAT((int32_t)(b0*32767), 16); void LESO_Q15(int16_t y, int16_t u) { int16_t e = y - z1_q15; z1_q15 += (__SMULBB(z2_q15, h_q15) + __SMULBB(beta1_q15, e)) >> 15; // ...其余状态更新类似 }移植到STM32G0等低端MCU时,可将采样周期延长至200μs,wo相应降低到2000rad/s,仍能保持良好性能。
