上周把某篇SCI二区论文里的混合有限集模型预测控制(FCS-MPC)方案,在Simulink里完整复现了一轮。坦率说,这个题目拆开看就是三件事:模块化多电平换流器(MMC)、整流工况、有限集模型预测控制。但真做起来,控制架构、离散建模、启动逻辑、参数反推,每一样都有不少讲究,绝不是把论文里的框图搬进Simulink就能跑通的。
如果你正准备复现这类文章,或者想用MMC整流器做毕业设计、课题预研,这篇复盘应该能帮你少走几天弯路。我按自己的实际操作顺序来讲:先把论文方案里的关键逻辑拆清楚,再讲Simulink模型怎么搭、控制器三层实现怎么写,最后是真刀真枪调试时踩过的坑和验证方法。
1. 复现前的三件关键事
1.1 先分清"混合"这个词在这类论文里指什么
很多人一看"混合有限集模型预测控制"就头疼,觉得这是不是又搞了个什么新算法。其实这类文章里的"混合",通常有两层意思。
第一层是指控制结构上的混合:不是像两电平逆变器那样直接枚举所有开关状态,而是把整个问题拆成"模型预测控制 + 最近电平逼近 + 电容电压排序"三层来混合处理。MMC每个桥臂有N个子模块,每个子模块输出要么是电容电压Vc,要么是0,所以一个桥臂的开关组合是2的N次方。N稍微大一点,比如24个子模块,直接枚举完全不可行。论文里常见的思路,是先让MPC算出一个连续的桥臂电压参考值,然后用最近电平逼近(NLM)把它量化成"该投入几个子模块",最后用排序法决定哪几个子模块投入。这样就把组合爆炸问题化解掉了,控制效果又保留了预测控制快速响应的优点。
第二层是指代价函数里的混合:交流电流跟踪、环流抑制、电容电压均衡、开关频率控制,这些目标在同一个代价函数里加权求和。到底是先算连续电压再量化,还是直接枚举有限状态,区别非常大。我在复现前把这两个层面的含义理清楚后,后面看论文里的框图就顺多了。
1.2 整流器工况下的MMC,哪里和逆变器不一样
MMC最常见的资料是逆变器或者STATCOM,但整流器并不只是功率流向反一下。最核心的区别在于:整流器的直流侧电压是被控对象,交流侧电流参考值不是外部给定的,而是由直流电压外环算出来的。
我复现时用的是三相MMC整流器,交流侧接三相电压源,直流侧接电阻负载。控制目标很明确:把直流电压稳定在800V,同时让交流侧电流接近正弦、功率因数近似为1。既然要控直流电压,就一定需要一个电压外环,典型做法还是PI。但电流内环不再用传统的PWM调制加解耦PI,而是直接用MPC预测下一个控制周期需要的桥臂电压。这就是FCS-MPC在MMC上最实用的打开方式。
至于MMC本身的建模,上下桥臂的关系、环流方程、电容电压动态,整流和逆变是完全一致的。也就是说,如果你之前搭过MMC逆变器的模型,整流器的改动主要在交流源和直流负载的接法,以及外环逻辑上,桥臂内部的子模块模型和排序算法都可以复用。
2. Simulink建模:先搭一个能稳定运行的MMC整流电路
2.1 主电路参数是怎么定下来的
论文里的参数通常不会给得非常全,尤其电容、电感这类元件值,经常需要按功率等级和经验公式反推。我复现时用的是一套低压小功率参数,方便快速迭代。
| 参数 | 数值 | 说明 |
|---|---|---|
| 交流相电压(有效值) | 220V / 50Hz | 三相交流源 |
| 直流母线电压参考 Vdc* | 800V | 整流器输出目标 |
| 每桥臂子模块数 N | 4 | 中低压仿真足够体现排序行为 |
| 子模块电容电压参考 Vc* | 200V | Vdc / N = 800 / 4 |
| 桥臂电感 Ls | 3mH | 用于限制环流和短路电流 |
| 子模块电容 C | 6800μF | 兼顾电容电压纹波和充电速度 |
| 直流侧负载电阻 | 10Ω | 稳态功率约64kW |
| 控制周期 Ts | 50μs | 20kHz采样控制 |
| 仿真步长 | 50μs | 离散求解器,与控制周期一致 |
N为什么取4?如果用更大N,比如24,更能体现模块化特征,但MATLAB Function里每一步都要对24个电容电压排序,调试期会非常慢。N=4时电容电压均衡逻辑已经完整,控制效果也够看出门道,等跑通后再放大N更合理。
桥臂电感Ls的取值,一般按环流抑制效果来定。太小时,桥臂电流里2倍频环流会很大;太大时,电流跟踪变慢,交流侧电压利用率也会下降。3mH是我在0.1pu到0.15pu范围内试出来的折中值。如果系统功率等级不同,这个值必须重新算,不能照抄。
2.2 用受控电压源代替IGBT堆叠,先跑通逻辑再讲精细化
很多同学复现MMC时,习惯直接用Simulink Specialized Power Systems里一个个搭IGBT和二极管组成的半桥子模块。这个思路没错,但调试期千万别这么干。你要是搭了4个子模块还好,N=24时整个电路里上百个开关器件,仿真一次要跑得人崩溃,而且控制逻辑一改,重新编译的时间足够喝三杯咖啡。
我推荐的做法是:先用受控电压源模拟桥臂的投入电压,把"上层控制逻辑"先跑通。具体来说,每个桥臂用一个受控电压源,它的电压就是该桥臂投入的子模块电压之和,由控制器给定。桥臂电流从电路里采样回来,用来计算下一拍电容电压和确定排序方向。子模块电容电压在MATLAB Function里用欧拉法递推更新。
这里有个关键细节:半桥子模块投入时,桥臂电流会流入电容,切除时电容电流为0。所以每个子模块的电容电压递推公式是:
% 子模块电容电压欧拉递推 % ic:流入电容的电流(投入时为桥臂电流,切除时为0) % C:子模块电容值 vc(k+1) = vc(k) + Ts / C * ic;在Simulink里,主电路只需要三相电压源、上下桥臂受控电压源、桥臂电感、直流负载和电压电流测量模块。这样整个电路非常干净,仿真速度也快。等这套等效模型的控制全部调好,再替换成真实IGBT级模型做最终验证,是最省时间的工作流。
3. 混合FCS-MPC控制器的三层实现
论文里的控制框图看着复杂,实际实现起来就是三层:第一层用MPC算连续电压参考,第二层用NLM量化成模块数量,第三层用排序法决定模块位置。每一层都可以在MATLAB Function里独立写,调试时也可以分开看波形。
3.1 第一层:用MPC替代电流内环,一次推导出桥臂电压参考
先写MMC的数学模型。以第j相上桥臂为例,忽略桥臂电阻,KVL方程是:
Ls * (diu_j / dt) = Vdc/2 - v_j - vu_j
其中iu_j是上桥臂电流,v_j是交流侧电压,vu_j是上桥臂投入的总电压。离散化后:
iu_j(k+1) = iu_j(k) + Ts / Ls * (Vdc/2 - v_j(k) - vu_j(k))
同理,下桥臂:
il_j(k+1) = il_j(k) + Ts / Ls * (Vdc/2 + v_j(k) - vl_j(k))
控制的目标是让下一拍的实际桥臂电流等于参考值。上桥臂参考电流可以写成环流参考和输出电流参考的组合:
iu_j_ref = iz_j_ref + ij_ref / 2
下桥臂:
il_j_ref = iz_j_ref - ij_ref / 2
其中ij_ref由直流电压外环PI产生,iz_ref设成0。把"预测值等于参考值"这个条件代回去,反解出所需的桥臂电压参考值:
vu_j_ref = Vdc/2 - v_j(k) - Ls * (iu_j_ref(k+1) - iu_j(k)) / Ts
vl_j_ref = Vdc/2 + v_j(k) - Ls * (il_j_ref(k+1) - il_j(k)) / Ts
这个推导其实就是模型预测里典型的"无差拍"思路。如果设代价函数为J = (iu_ref - iu_pred)^2 + (il_ref - il_pred)^2,最优解就是上面这两个式子。计算量几乎为零,不需要对开关状态做任何枚举。
我在实际仿真里发现,网侧电压v_j(k)这个前馈项非常重要。如果去掉它,交流电流会出现明显的相位偏差和幅值误差,因为它的本质是抵消电网电压的扰动。
3.2 第二层:最近电平逼近,把连续电压折算成模块投入数量
有了上桥臂电压参考vu_j_ref,接下来要做的不是直接给到受控电压源,而是把它量化成"这拍该投入几个子模块"。这就是最近电平逼近:
n_on = round(vu_j_ref / vcu_avg);
vcu_avg是当前桥臂所有子模块电容电压的平均值。这里我踩过一个坑:一开始按论文写的是用额定电容电压Vc*去除,结果电容电压波动稍大时,实际输出电平会系统性偏低,直流电压拉不上去。后来改成用实时平均值,电压利用率明显改善。很多论文不写这个小区别,但仿真里影响挺实在。
量化后要限幅:
n_on = min(max(n_on, 0), N);
下桥臂同样操作。这一步就把连续控制量变成了一个离散的整数电平,对应最近电平逼近调制。需要注意的是,N越大,量化误差越小,交流电流THD越低。N=4时谐波会比其他高一些,但控制逻辑完全成立。
3.3 第三层:排序法做电容均衡,同时要压制开关频率
决定投入几个模块之后,还要决定哪些模块投入。论文里普遍采用电容电压排序法,规则很朴素:
- 如果桥臂电流方向为充电(电流流入电容),投入电容电压最低的n_on个子模块;
- 如果桥臂电流方向为放电,投入电容电压最高的n_on个子模块。
MATLAB Function里用sort天然处理,核心代码类似:
% 上桥臂模块数量限制 n_on = min(max(round(vu_ref / mean(vcu_upper)), 0), N); % 按桥臂电流方向排序 if iu_upper > 0 [~, idx] = sort(vcu_upper); % 充电:低电压优先投入 else [~, idx] = sort(vcu_upper, 'descend'); % 放电:高电压优先投入 end % 生成门极信号 gate_upper = zeros(N, 1); gate_upper(idx(1:n_on)) = 1;这里有个非常现实的工程问题:如果每个控制周期都从头排序,子模块会被频繁投切,等效开关频率可能高到几万赫兹,仿真能跑,但实际装置根本受不了。论文里会提这个坑,但很少给具体做法。我的办法是加一个容差带:只有当桥臂内电容电压的最大最小差超过设定阈值时,才重新排序;否则沿用上一拍的门极状态。阈值取额定电容电压的2%到3%,比如200V参考对应4V到6V。实测下来,交流电流波形几乎不受影响,但开关频率能压到原来的三分之一以下。
代价函数里的"混合"也在这里体现。如果论文里明确写了环流抑制项或开关频率惩罚项,那多半是在第一层和第三层之间又加了一步限制。复现时我建议先把最朴素的版本跑通,再逐步加这些惩罚,不然问题混在一起很难排查。
4. 调试记录:从仿真直接崩掉到波形和论文对齐
4.1 启动瞬间的问题:没有预充电就是灾难
我第一次直接按论文给的参考电压800V上电,仿真跑到5毫秒就崩了。交流侧电流尖峰超过额定值几十倍,直流电容被瞬间充电,整个系统根本稳不住。
原因不复杂:MMC启动时子模块电容电压是0,控制器一上来就要把直流侧拉到800V,电容相当于短路,冲击电流必然巨大。论文里一般不画预充电回路,但复现时必须处理。
我的做法分三步:第一步,交流侧合闸时所有子模块切除,利用反并联二极管给电容不控充电;第二步,直流电压参考从0斜坡上升到800V,速度大概20V/ms,不搞阶跃;第三步,直流负载先断开或串一个大限流电阻,等电容电压基本建立后再接入负载。三步都做完,启动波形才算是正常:直流电压平滑上升,交流电流在半个工频周期内逐渐进入限幅。
这步折腾了我差不多一天,提醒所有复现MMC的人,论文里看不到的启动逻辑往往比控制算法本身更能决定你能不能跑出结果。
4.2 环流抑制与排序抖动,怎么折中
第一版跑通之后,桥臂电流波形明显不好看,里面叠加了很强的2倍频环流分量。原因是我一开始把环流参考直接设成了0,但在第一层反解上下桥臂参考电压时,没有把环流动态单独建模。后来把环流误差也放到代价函数里一起优化,等效做法就是把上下桥臂电流参考分开给,让iz_ref=0这个约束真正起作用。加上之后,环流峰值从额定电流的15%左右降到了6%左右。
另一个让人头疼的问题是排序抖动。不加容差带时,电容电压排序几乎每个控制周期都在变,桥臂电流和直流电压波形都毛糙。我一开始怀疑是采样噪声,后来加滤波也没改善,才意识到是排序太频繁导致开关状态跳变太多。加容差带之后,波形干净了很多。
还有一个非常容易被忽视的点:powergui的仿真步长必须和控制周期Ts一致。如果不一致,比如仿真步长10us但控制周期50us,你会看到一种奇怪的"拍频"毛刺,原理是采样时刻和模型更新时间错拍。把两个步长统一设置,问题立刻消失。
4.3 和论文结果对比,到底该盯哪些指标
复现到波形"看起来像"是不够的,要真正和论文对齐,得盯着可以量化的指标。我自己整理了一张对照表,每一项都要打到论文的标称范围附近才算数。
| 验证项 | 论文/理论目标 | 我的仿真结果 | 说明 |
|---|---|---|---|
| 直流电压稳态均值 | 800V | 799~801V | 电压外环稳态精度 |
| 子模块电容电压波动 | ≤5% | ±2.8% | 主要受C大小影响 |
| 交流电流THD | <5% | 约2.5% | N=4时还不错 |
| 负载阶跃恢复时间 | <20ms | 约12ms | 10Ω跳5Ω,Vdc允许10%偏差 |
| 环流峰值(标幺) | <10% | 约6% | 加环流惩罚项后 |
| 启动最大冲击电流 | 无过流 | 限幅内 | 软启动+限流电阻 |
这里多说一句,对比论文时要特别注意时间轴和纵轴。有些复现报告拿稳态波形直接对比动态波形,这没有意义。我习惯先从论文截图里读出"电压从扰动到恢复用了多少个工频周期",再用同样条件仿真,对比才公平。
5. 复现后的几点实在建议
5.1 论文参数只给一半时,怎么把缺的补回来
SCI论文的仿真参数并不是都齐全,很多只给N、Vdc和功率等级,电容电感要靠自己反推。我的经验是:电容大小主要看电容电压波动允许值,波动要求越严格,C就得越大;电感大小主要看环流抑制和电流响应速度,太大会拖慢动态响应。如果完全没有头绪,先按我前面那张表的比例放缩到目标功率等级,再小幅调。
控制周期Ts也要自己留心。论文里可能写的是20us,但你的仿真环境不一定扛得住。先把Ts放宽到50us跑通,再逐步收紧,观察波形变化,这样可以节省大量等待时间。
5.2 如果想在这个方案上继续做研究,还能动哪些环节
这套"MPC计算连续电压+最近电平逼近+排序均衡"的框架,复现完成后其实留下了很多可改进的口子。比如代价函数里的权重可以做成在线自适应,让系统在启动阶段更看重电压跟踪,稳态更看重电流质量和环流抑制。又比如把单步预测扩展成多步预测,量化后枚举空间只是(N+1)的预测步数次方,比直接枚举开关组合小得多,可以做更深入的MPC研究。
如果目标是实际工程,这套控制思路同样可以移植到逆变器或静止无功补偿装置上,反正MMC的桥臂建模和排序逻辑是通用的。我自己复现之后的下一步,是把MATLAB Function里的算法代码整理成可生成C代码的形式,为后面做实时仿真留个接口。
从零开始复现这套系统,我的建议顺序是:先搭等效桥臂模型,再写三层控制器,然后处理启动问题,最后才考虑替换详细器件模型。每一步都要有明确的波形检查点,不要急着一次性写完所有逻辑。你在实际复现时如果也卡在某些参数怎么都调不平整,多半不是算法问题,而是某个模型细节和论文里没写清楚的环境条件没对齐,耐心排查比换算法更有效。