三相逆变器两步模型预测控制:原理、仿真与调参实战
三相逆变器最让人头疼的从来不是满载起机而是负载切换那一瞬间的输出电压恢复。我试过用两步预测控制算法两步MPC来压住这个波动效果比单步预测整整好了一截。本文想把这里面的“为什么多走一步”讲透从传统双闭环PI为什么压不住到两步预测到底补上了什么再到仿真和实物之间的几个真实坑最后给出一套可以直接参考的调参和落地方案。适合正在做离网逆变器、UPS、储能变流器输出电压控制的工程师也适合刚接触模型预测控制、想搞清楚“两步”来龙去脉的在校同学。1. 输出电压不稳定的根源双闭环PI调不动的那几个环节1.1 先把“稳定”拆成三个硬指标谈到三相逆变器输出电压稳定我们实际在关心三件事稳态电压误差、输出电压总谐波畸变率THD、负载突变时的动态恢复时间和超调。大多数项目里稳态误差要求不超过±2%THD要求低于3%或5%动态恢复时间则根据应用场景而定有的要求5ms内回到稳态有的要求2ms以内。离网逆变器的输出侧通常接一个LC滤波器L和C组成二阶低通滤波器把开关纹波滤掉输出干净的工频正弦波。问题是这个LC滤波器在谐振频率附近会形成一个明显的阻抗峰而负载又不是纯电阻——最常见的是整流性负载电流是尖峰状的谐波含量很高。输出电压一旦在某个谐波频率附近被激励起来波形就会出现“平顶畸变”THD超标严重的还能听到滤波电感发出明显噪声。1.2 传统电压电流双环为什么越调越抖传统做法是电压外环加电感电流内环外环给内环发电流指令内环负责快速跟踪。理论上这套双环可以工作但在三相离网带整流负载的场景下有先天弱点电压环带宽不能太高否则LC谐振峰附近会产生负相移系统容易振荡。把电压环带宽压低又导致对高频谐波分量的抑制能力不足负载电流里的低次谐波绝大部分都落到输出电压上。我在调某个储能离网逆变器时尝试过加大电压外环的PI增益来压THD结果一加载就出现低频振荡输出波形像“呼吸”一样起伏功率管电流明显过冲。后来把增益降回去THD又回到4%以上。这就是双环PI在线性化工作点附近再努力也无法在每个采样周期针对实际开关状态做精细优化的原因。1.3 有限集模型预测控制进入视野模型预测控制MPC的思路完全不同它不做线性化也不用调制器而是直接基于逆变器的8个开关矢量6个有效矢量和2个零矢量在当前采样时刻对每个候选开关状态做“虚拟试验”——预测未来一个或几个采样周期的输出电压代入代价函数算分得分最低的那个开关矢量就是下一拍要执行的。这个“枚举—预测—评价—选择”的过程每个采样周期都重复一次本质上是滚动优化。这种思路对带非线性负载特别友好因为代价函数可以直接对标输出电压误差不需要把谐波问题折算成带宽问题。于是我开始把MPC往项目里搬但真正让波形“稳下来”的是我把单步预测改成两步预测之后的事。2. 看似只多算一步两步预测到底补上了什么2.1 单步预测的标准流程与隐藏缺陷先看经典的单步FCS-MPC流程。在k时刻采样得到电感电流、输出电压、负载电流然后遍历8个开关矢量对每个矢量预测k1时刻的输出电压套进代价函数选出最优。看起来天衣无缝但实际数字控制器里有一个躲不开的物理事实采样、枚举、比较、PWM更新这整条计算链需要时间。在低成本控制板上这段代码可能要跑10到30微秒甚至更长。问题出在这里k时刻采样产生的计算结果虽然写在“当前周期”但因为PWM寄存器要等到下一个控制周期才更新选出的开关矢量实际在k1时刻才生效。也就是说你用“k时刻的状态预测k1时刻的输出”但开关矢量要到k1才应用模型里的第一拍预测和目标信号对不上——中间白白晚了一拍。这一拍在工频周期里不算大但足以让输出电压跟踪产生相位滞后THD无法压到最佳水平负载突变时还会出现更深的电压跌落。2.2 两步预测的本质把时间轴对齐两步预测的核心动作不是简单把预测窗口从1变成2而是先用“当前正在执行的开关矢量”把状态从k时刻推到k1时刻得到一个虚拟状态然后从这个虚拟状态开始继续枚举8个开关矢量预测到k2时刻代价函数对标的目标也外推到k2时刻。这一步很关键当前正在执行的开关矢量是上一个控制周期选出来的它是已知的、固定的。预测第一步不需要枚举直接算。到了第二步才枚举8个矢量最后选出的开关状态在k1时刻开始执行、k2时刻产生效果和代价函数里评估的时刻完全对齐。所以两步预测的本质是“一拍补偿、一拍选优”把数字控制器自身的计算延时从控制链路里抹掉了。2.3 两步预测和预测水平线N2是一回事吗很多人以为把预测水平线从N1改成N2就是两步预测于是去枚举64种开关组合结果计算量暴增控制周期拉长效果反而变差。这两者不是一回事。真正的两步预测延时补偿型第一步用固定开关状态不参与枚举总计算量只是单步预测的两倍不到而水平线N2的有限集MPC需要在两个控制周期内选择两个开关序列枚举量指数增长实际工程中很少直接这么干。我在项目里采用的是“第一步外推当前执行状态第二步枚举单矢量”的组合方案计算量和实现复杂度都控制在很舒服的范围内。2.4 参考值也得跟着外推两拍否则还是对不齐还有一个容易忽略的细节代价函数里的输出电压参考值不能拿当前的V_ref去和k2时刻的预测值比必须把参考值也外推两拍。最常用的线性外推公式是V_ref(k2) 3V_ref(k) - 3V_ref(k-1) V_ref(k-2)如果控制周期是50微秒输出是50Hz两拍只占0.9度的电角度直接用当前参考值近似误差不大但如果输出频率到400Hz、控制周期到100微秒这个角度差就不能忽略了必须做外推。我建议在代码里统一改成线性外推多三行代码换来的是稳态跟踪不偏角。3. 从状态方程到代码两步MPC建模仿真全流程3.1 LC滤波器的离散状态方程要把两步预测写成代码先得有准确的离散状态方程。以三相两电平逆变器加LC滤波器为例在αβ静止坐标系下电感电流和电容电压满足L * (di_L/dt) V_inv - V_o - R * i_L C * (dV_o/dt) i_L - i_o其中V_inv是逆变器输出电压矢量由当前开关状态和直流母线电压决定R是电感等效串联电阻i_o是负载电流。采用前向欧拉离散化时注意计算顺序先更新电感电流再用更新后的电流更新电容电压。顺序反了会让系统多出半个采样周期的隐含延时短时间内看不出来但负载突变时动态表现会解释不了地变差。离散化后的预测公式如下i_L(k1) i_L(k) Ts/L * (V_inv(k) - V_o(k) - R*i_L(k)) V_o(k1) V_o(k) Ts/C * (i_L(k1) - i_o(k))这里V_inv(k)是8个开关矢量对应的αβ轴电压。为了方便可以预先算好一张查询表把8个开关状态对应的(V_alpha, V_beta)存成常量数组运行时直接查表省去三角函数计算。3.2 代价函数不能只盯输出电压代价函数设计是MPC的灵魂。最简单的形式是只惩罚输出电压预测值和参考值的误差J (V_ref_alpha - V_o_alpha)² (V_ref_beta - V_o_beta)²但实践中纯粹只盯输出电压电感电流会在参考电压变化率大的地方冲得很高功率管的电流应力偏大输出波形也容易带毛刺。我的做法是在代价函数里加一个电容电流惩罚项J (V_ref - V_o_pred)² λ * (i_c_pred)²其中i_c_pred是预测的电容电流。这一项的作用类似于阻尼它不希望电容电流变化过猛从而抑制LC谐振峰的激励。权重λ需要整定太小没效果太大又会让控制目标偏离电压跟踪。后面我会专门讲这个λ在调试时引发的一个坑。3.3 两步预测核心代码片段下面这段Matlab风格的伪代码是我在仿真阶段反复调整后的版本注释里写清了每一步的意图function Sopt mpc_2step(il_ab, vo_ab, io_ab, vref_k2, Vdc, L, C, R, Ts, lambda) % il_ab/vo_ab/io_ab: 当前采样值αβ分量 % vref_k2: 外推到k2时刻的参考电压矢量 % 8个开关状态对应αβ电压查表 u_alpha [...]; u_beta [...]; S_set [0 0 0; 1 0 0; 1 1 0; 0 1 0; 0 1 1; 0 0 1; 1 0 1; 1 1 1]; % 第一步用当前正在执行的开关矢量外推k1状态 S_cur get_pwm_state(); % 从PWM寄存器读实际状态 vin_alpha (S_cur(1)-0.5) * Vdc; vin_beta (S_cur(2)-0.5) * Vdc; il_k1 il_ab Ts/L * ([vin_alpha; vin_beta] - vo_ab - R*il_ab); vo_k1 vo_ab Ts/C * (il_k1 - io_ab); % 第二步枚举8个开关矢量从k1外推k2并评价 Jmin 1e10; Sopt S_set(1, :); for j 1:8 vin_a (S_set(j,1)-0.5) * Vdc; vin_b (S_set(j,2)-0.5) * Vdc; il_k2 il_k1 Ts/L * ([vin_a; vin_b] - vo_k1 - R*il_k1); vo_k2 vo_k1 Ts/C * (il_k2 - io_ab); ic_k2 il_k2 - io_ab; J sum((vref_k2 - vo_k2).^2) lambda * sum(ic_k2.^2); if J Jmin Jmin J; Sopt S_set(j, :); end end end注意第一步里读取的S_cur必须是PWM寄存器里“当前真正正在执行”的开关状态而不是上一个周期CPU算好的目标值。如果这两个搞混了第一步外推就推错了方向两步预测反而比单步预测更差。3.4 采样周期和参数选型参考在实物调通前我建议先把LC参数和采样周期定下来。下面这组参数来自我当时搭建的模拟项目供参考参数数值说明L1 mH滤波电感C10 uF滤波电容R0.1 Ω电感等效串联电阻Vdc400 V直流母线额定电压Ts50 us控制周期输出频率50 Hz三相正弦输出谐振频率1592 Hz由1/(2π√(LC))计算LC谐振频率在工作频率和开关频率之间留出足够间隔。采样周期Ts要结合控制板算力选太大会让离散化误差增大太小又跑不完两步枚举。实测在50微秒控制周期下一个中等性能的DSP内核可以轻松跑完8次枚举加代价函数计算CPU占用不高。3.5 仿真阶段必须加计算延时很多人在Simulink里做MPC电气模型用Simscape或PLECS控制部分写S-Function仿真结果漂亮得不得了单步预测THD也压得很低。一搬到实验台就露馅原因往往是仿真里没有模拟“从采样到PWM更新”的计算延时。我的建议是在控制输出到PWM调制之间显式加一个Delay模块延时设为一个Ts或略多一点模拟真实的计算时延。这样单步预测的弱点会在仿真里直接暴露出来两步预测的优势也更容易量化。不加这个延时你后面所有结论都建立在“计算零延时”这个不现实假设上迟早翻车。4. 仿真很好看、上机就翻车三次踩坑与完整排查链路4.1 第一个坑PWM更新时序和采样中断错位第一次把两步预测代码烧到控制器带纯电阻负载时波形尚可但只要把负载从满载切到半载输出电压会出现一个低频包络波动看起来像“呼吸”一样慢慢起伏。我的排查链路从示波器开始同时抓取PWM输出引脚、ADC采样触发信号以及一个在中断服务函数里翻转的IO引脚。结果发现IO翻转发生在采样中断的末尾但PWM新占空比要等到下一个PWM周期顶点才批量更新。也就是说我以为的两拍延时实际变成了三拍第一步预测用的“当前执行状态”和真正执行状态差了一拍。修复方法是把PWM模块改成“采样顶点立即刷新、下一个周期生效”的模式同时把第一步读取的S_cur从PWM影子寄存器里取实际生效值而不是从CPU变量里取。这样时序才真正对齐。这个坑的根子是控制板PWM更新的缓冲区机制而不是MPC算法本身。4.2 第二个坑电压采样噪声把预测方向带偏第二次翻车在空载状态。输出电压波形在采样点附近出现明显抖动带阻性负载时反而好一些。起初我怀疑是权重λ调得不对后来又怀疑离散化步长折腾了大半天没有结果。后来用示波器直接观察电压采样链路才发现开关切换瞬间的高速电压尖峰正好打在采样点上ADC采到的值里掺了一大堆毛刺。给采样回路加一阶RC低通滤波后毛刺小了但滤波电容带来的相位滞后让预测模型的输入和真实状态对不上抖振变得更明显。最终方案是双管齐下把ADC采样故意安排在PWM载波的中间点避开开关切换的振铃区采样数字滤波只做轻微的平均再配合两步预测自带的一拍补偿来抵消相位滞后。这里要记住一个原则MPC对预测输入的真实性极度敏感采样抗干扰做不好模型再准也白搭。4.3 第三个坑权重因子λ调到“看起来很好”第三次踩坑是我自己造成的。为了进一步压低空载振荡我把代价函数里的λ一路往上加终于把波形调得纹丝不动心里还挺得意。但带整流负载测试时THD不仅没降反而升了输出还伴随明显的差模噪声。后续排查发现λ过大的本质是给电容电流惩罚项赋予了过高的权重预测算法为了把电容电流变化压到最小宁可牺牲输出电压的跟踪精度导致输出正弦波变形。控制目标被带偏了当然稳不住。把λ退回到合理区间、再补上软启动斜坡后问题消失。这说明权重因子的整定不能只看空载或阻性负载必须在典型负载组合下综合评价。我一般从λ0开始每加0.01跑一次负载切换仿真直到电压恢复时间最短且无振铃再取一个留有余量的中间值。4.4 排查经验的总结三次翻车有一个共通点问题都不在MPC公式本身而在“数字控制系统的真实时序”和“测量链路的真实性”。这也是所有先进控制算法落地时最容易被低估的一环。遇到波形异常先别急着改控制参数优先把采样时序、PWM更新逻辑、测量噪声这三件事用示波器确认清楚。5. 波形对比与调参经验两天内从“能转”到“好用”5.1 实测数据对比搭好实验台后我对三套方案做了同一组工况的对比线性负载、整流负载、50%到100%负载突加。结果如下指标双闭环PI单步MPC两步MPC线性负载THD3.8%2.7%1.6%整流负载THD6.5%4.2%2.4%突加负载电压跌落8%5.2%3.1%恢复时间6 ms3.1 ms1.6 ms稳态电压误差1.8%1.2%0.9%这套数据来自我当时的模拟项目不同硬件上绝对数值会有差异但趋势很有参考性两步预测在动态恢复和带非线性负载时的收益最明显稳态THD的提升也很可观。5.2 两步预测什么时候收益最大结合我这段时间的经验两步预测并不是在所有逆变器场景下都有立竿见影的效果。收益最大的场景有三个共同点输出侧带LC滤波、负载含整流或开关类非线性、控制器算力足够在50微秒内跑完枚举。如果你的系统是并网逆变器且采用LCL滤波器配合SPWM调制的成熟方案不必非得换成MPC但如果是离网、多变负载、电压质量要求高两步预测的性价比非常突出。5.3 参数敏感性和工程化建议模型预测控制的短板是依赖模型参数。电感值会随电流增大而下降电容的容值会随温度和老化偏移负载电流又是时变的。我给项目做的处理是离线标定一张分段电感表根据当前电流在线查表预测同时在第一个预测步里用小范围修正器抵消模型误差。实际操作中还有个经验突加负载瞬间负载电流需要用前一拍的采样值近似但负载电流突变的斜率非常大直接用恒值预测会有误差。至少要做一阶外推i_o(k1) 2*i_o(k) - i_o(k-1)这样动态恢复时间能进一步缩短我在实测中通过这个改动把恢复时间从2.2ms压到1.6ms不算夸张但效果确实可见。最后再分享一个实用小技巧调试两步MPC时如果发现空载或轻载状态下输出电压有难以锁定的振荡我习惯临时把代价函数里的λ加到正常值的5到10倍让预测算法被迫牺牲电压精度去阻尼电容电流。这时候系统会稳定下来但输出波形会偏软。可以用这个办法快速定位谐振点确认振荡源在LC滤波器然后再把λ退回正常值。这个办法我在现场排查时反复用比盲调PI省时间得多。对于想入手的同行我建议第一步先别急着上实物把单步预测在仿真里不加延时跑通再显式加入一拍延时亲眼看看波形变差的过程然后改成两步预测恢复波形。这个对比做完你就比很多只会照抄代码的人更清楚这“多走一步”到底值在哪。