三相整流器FCS-MPC模型预测控制Simulink仿真全解析 我在一个整流器预研项目上最初还是老老实实用电压外环PI加电流内环PI、再配SVPWM调制的老路子。电流内环要解耦电压外环带宽要和内环拉开再加上电网电感L估计不准整定参数花了两天结果负载突变时电流还是超出了预期。后来把内环换成有限控制集模型预测控制FCS-MPC事情一下子简单了不少不需要调制器不需要内环解耦每次控制周期直接选出最优开关状态输出MATLAB/Simulink里一个自定义函数就能写完核心逻辑。这篇博客就把我搭建的三相整流器基于模型预测的仿真模型完整拆开讲一遍。内容包括三相整流器在dq旋转坐标系下的离散数学模型、Simulink里的分层搭建方法、8个电压矢量的滚动优化代码、代价函数权重怎么调以及我在实际调试过程中踩过的那些坑。希望给正在做三相PWM整流器仿真、或者想把MPC从理论落到Simulink模型里的朋友一个可以直接参考的完整路径。1. 为什么我会用模型预测控制来做三相整流器而不是继续堆PI参数1.1 传统双闭环在不调参这件事上的痛苦三相PWM整流器的常规做法是外环稳住直流电压内环控制dq轴电流再用SVPWM或SPWM生成驱动脉冲。这套方案性能并不差它在大量工业产品里经过验证稳态精度和开关频率固定的特性都很好。但问题在于每次换一套主电路参数内环PI就得重新算一遍。电流内环通常在dq坐标系下工作d轴和q轴之间存在耦合项理论教科书会告诉你用前馈解耦。但真正仿真的时候电感L的标称值和实际值总有一点出入解耦误差一变PI的稳定裕度也跟着变。更麻烦的是如果后面还要接不同短路比的电网L从3mH变成8mH原来那组PI参数就不再是最优甚至可能出现振荡。我在某供电系统预研项目里就是被这个反复调参的过程拖住了进度。仿真平台本身没问题问题出在每个新工况都要重新整定一套参数这件事上。1.2 有限控制集模型预测的基本套路模型预测控制的核心想法很简单先预测再决策。三相两电平整流桥只有6个功率管上下桥臂不能同时导通所以有效开关状态一共是8种组合这8种组合就是所谓的有限控制集。控制算法在每个采样周期做这样几件事读取当前采样值电网电压、电感电流、直流电压。利用三相整流器的数学模型对8个开关状态分别预测下一时刻的电流值。把预测电流和参考电流放进代价函数误差最小的那个开关状态就是本周期要输出的结果。直接把对应的门极脉冲送给功率管等下一个采样周期重复。整个过程不需要三角载波不需要调制器也不需要电流内环PI。我最早看到这个思路的时候感觉像是暴力枚举但跑起来之后发现它对参数变化的适应能力反而比传统方法更直接因为预测模型里的L和R是显式参与的主电路一改改两个常数就行不需要重新凑PI参数。1.3 它到底省掉了什么又带来了什么省掉的东西很明确调制器、内环PI、电流解耦环节。但代价也不是没有。模型预测控制对模型精度的依赖比对PI参数更显性如果L参数估得不准预测电流就会系统性偏差结果可能表现为电流纹波偏大或者稳态误差去不掉。另外它的开关频率不固定不像SPWM那样由载波频率锁定这点在工程上会带来滤波器设计上的麻烦。所以我的态度是MPC不是来取代传统方法的它更适合动态响应要求高、或者你不愿意花大量时间调内环参数的场景。工具选型这件事先想清楚需求再决定用哪套方案。2. 从三相整流器数学方程到步长离散仿真前必须想清楚的事2.1 整流器在dq坐标系下的连续模型仿真不是直接摆一堆Simulink模块就完事先把数学模型写对后面写代码才不会返工。三相电网电压经过电感和等效电阻进入整流桥整流桥交流侧可以看成由开关状态决定的受控电压源。直流侧是电容和负载并联。开关函数定义成Sa 1表示A相上桥臂导通Sa 0表示A相下桥臂导通Sb、Sc同理。整流桥交流侧相电压和直流电压Vdc的关系是va Vdc * (2*Sa - Sb - Sc) / 3 vb Vdc * (-Sa 2*Sb - Sc) / 3 vc Vdc * (-Sa - Sb 2*Sc) / 3这组式子非常关键后面所有预测都是基于它。如果你不自己算查表也行8个开关状态对应8组va/vb/vc。然后进入dq旋转坐标系。设d轴与电网电压矢量同方向三相整流器的电压方程可以写成L * did/dt ed - R*id - vd ω*L*iq L * diq/dt eq - R*iq - vq - ω*L*id这里的ed、eq是电网电压的dq分量vd、vq是整流桥交流侧电压的dq分量ω是电网角频率。2.2 一阶欧拉离散直接把预测式写出来模型预测控制在数字控制器里必须使用离散模型。工程上最常用的一阶欧拉法形式简单采样频率足够高时精度完全够用。对电流微分做近似did/dt ≈ (id(k1) - id(k)) / Ts diq/dt ≈ (iq(k1) - iq(k)) / Ts代入连续方程整理出预测式id(k1) id(k) (Ts/L) * [ed(k) - R*id(k) - vd(k) ω*L*iq(k)] iq(k1) iq(k) (Ts/L) * [eq(k) - R*iq(k) - vq(k) - ω*L*id(k)]这组式子就是滚动优化的核心。每次采样后把8组开关状态分别代入vd/vq算出8个预测电流值然后选代价函数最小的那一组。这里有一个非常容易搞错的地方vd/vq的正负号定义。如果你用Simulink自带的abc到dq0变换模块变换方向可能和我上面写的相反那会出现电流预测总是不对的现象。遇到这种情况不要硬改代码先确认你的Park变换方向和电压方程方向是自洽的。2.3 8个开关状态对应的交流侧电压表为了减少仿真运行时反复做三角函数转换我习惯把8个开关状态的vd/vq离线算好写成常量表在代码里直接查表。假设Vdc为当前直流电压θ为PLL角度开关状态(Sa Sb Sc)vdvq00000001Vdc·cos(θ2π/3)修正值Vdc·sin对应值010......011......100......101......110......11100严格算完这一整张表需要按实际变换系数展开我在仿真代码里是直接调用一个v_lookup(Vdc, theta, state_index)函数来算的。因为Vdc在启动过程会从0爬到600V每次算一次也很快8次循环对20kHz采样率来说开销完全可以接受。如果是想在更低成本的控制器上落地再优化成离线表也不迟。3. 按我的习惯Simulink里分四层把MPC整流器搭起来3.1 主电路和前级测量不要把电压电流量测直接怼进MPCSimulink里搭主电路我直接用Simscape Electrical的元件库三相交流电源、三相RL阻抗支路、Universal Bridge、直流电容、直流负载这些都有现成模块。三相两电平桥我选的是IGBT/Diode结构因为整流工况下反并联二极管在启动阶段还要走不控整流这个细节很关键。搭建顺序三相电源设置为线电压380V、频率50Hz。三相RL支路参数L5mH、R0.05ΩR把线路电阻和电感寄生电阻都算进去了。Universal Bridge选择三相臂、IGBT/Diode直流侧接电容2200μF。直流负载先用10Ω后面做负载突变时可以换成阶跃投切电阻。电压电流测量不要直接接进MATLAB Function中间一定要通过信号转换和零阶保持器。Simscape物理信号和Simulink普通信号之间需要转换模块这个看似不起眼实际上很多人第一次跑模型报数据类型不匹配就是卡在这里。我习惯这样处理电流测量模块输出物理信号加一个Simulink PS-Simulink Converter转换成普通信号再过零阶保持器采样周期设成Ts50μs也就是20kHz的控制频率。这样做的好处是MPC里面每一拍拿到的输入信号都是同一个采样时刻的快照而不是连续斜坡信号。3.2 坐标变换与PLL锁不到相角后面全是白搭MPC预测用的ed/eq和id/iq都在旋转坐标系下所以必须先有准确的电网电压相角θ。我用的是Simscape电气库里的三相PLL模块输入三相电压输出角度θ。有一点要注意测量出来的三相电压是经过RL支路之后的整流桥输入电压不是电源电压本身。如果用这个电压去锁相得到的角度里会带一点电感压降造成的相位偏移。不过对于仿真入门来说影响不大如果做高精度控制一般建议直接从电网母线侧取电压信号参与锁相。θ出来后用库里的abc_to_dq0变换模块分别变换三相电网电压和三相输入电流得到ed/eq和id/iq。dq变换系数选幅值不变形式和我的预测模型保持一致。3.3 MATLAB Function里写8个电压矢量的滚动优化核心控制算法我放在一个MATLAB Function里输入是ed、eq、id、iq、id_ref、iq_ref、Vdc、theta输出是6路门极脉冲。先给一个可以直接用的简化版本function gates fcs_mpc_rectifier(ed, eq, id, iq, id_ref, iq_ref, Vdc, theta) % 三相两电平整流器 有限控制集模型预测电流控制 % 输入电网电压dq分量、电流dq分量、电流参考值、直流电压、PLL角度 % 输出6路门极脉冲 [Sa Sb Sc ~Sa ~Sb ~Sc] % 参数可以在函数里直接定义也可以作为持久变量从外部传入 L 5e-3; R 0.05; Ts 50e-6; w 2*pi*50; % 8个开关状态 states [0 0 0; 0 0 1; 0 1 0; 0 1 1; 1 0 0; 1 0 1; 1 1 0; 1 1 1]; % 当前PLL角度 ct cos(theta); st sin(theta); % 初始化最优值 J_min inf; best_idx 1; for idx 1:8 Sa states(idx,1); Sb states(idx,2); Sc states(idx,3); % 整流桥交流侧相电压 va Vdc * (2*Sa - Sb - Sc) / 3; vb Vdc * (-Sa 2*Sb - Sc) / 3; vc Vdc * (-Sa - Sb 2*Sc) / 3; % abc - dq vd 2/3 * (va*ct vb*cos(theta-2*pi/3) vc*cos(theta2*pi/3)); vq -2/3 * (va*st vb*sin(theta-2*pi/3) vc*sin(theta2*pi/3)); % 预测下一拍电流 id_p id (Ts/L) * (ed - R*id - vd w*L*iq); iq_p iq (Ts/L) * (eq - R*iq - vq - w*L*id); % 代价函数 J (id_ref - id_p)^2 (iq_ref - iq_p)^2; if J J_min J_min J; best_idx idx; end end % 根据最优状态输出门极脉冲 Sa states(best_idx,1); Sb states(best_idx,2); Sc states(best_idx,3); gates [Sa; Sb; Sc; 1-Sa; 1-Sb; 1-Sc]; end这段代码是用来跑通的版本不是最终优化版本。后面提到的延迟补偿、开关惩罚项都在这个框架上加。3.4 电压外环PI的输出怎么限幅才能喂给内环直流电压要稳住必须有一个外环给出id_ref。这个外环我用的还是PI因为MPC内部管的是电流动态电压外环用PI完全没有问题。电压PI的作用是Vdc偏高就减小id_refVdc偏低就增大id_ref。但如果id_ref不限幅启动瞬间电容充电电流会非常吓人可能烧管子或者让仿真发散。我把PI输出限幅设在±40A。40A这个数值是结合启动电流峰值估计出来的你可以按你的器件额定电流调整。积分环节也要限幅不然限幅之后积分继续累加会形成严重的超调。我用的初值是Kp0.6、Ki20这个值不一定适用于所有系统以我给的参数跑通之后再按阶跃响应微调即可。iq_ref直接给0意思是控制整流器工作在单位功率因数状态也就是网侧电流只含功分量。如果你还想做无功补偿iq_ref可以作为无功控制的输出通道。4. 代价函数不是公式抄完就完事权重系数与开关切换惩罚4.1 最基础的代价函数长什么样我上面给的代码里代价函数是J (id_ref - id_p)^2 (iq_ref - iq_p)^2两项都是电流误差平方单位一致所以默认权重都是1。这个形式作为入门完全够用它让算法在8个开关状态里选一个让预测电流最接近参考值的状态。但运行一段时间你会发现一个问题算法为了把电流误差压到极小会非常频繁地切换开关状态。因为相邻采样点参考电流变化一点最优状态可能就从100跳到000下一拍又跳回来。开关频率变高电流纹波也没见得好多少功率器件的开关损耗倒是上去了。4.2 要不要加开关惩罚项加多大合适解决这个问题最直接的办法是在代价函数里加一项开关切换惩罚项。定义上一拍输出状态为Sa_old、Sb_old、Sc_old当前候选状态为Sa、Sb、Sc三者逐位比较有几个位不同就记几次切换。用汉明距离来表示n_sw abs(Sa - Sa_old) abs(Sb - Sb_old) abs(Sc - Sc_old)代价函数变成J (id_ref - id_p)^2 (iq_ref - iq_p)^2 λ_sw * n_swλ_sw这个系数就看你对开关频率的忍耐程度。它的物理含义可以理解为多切换一个功率管相当于允许引入多大的电流平方误差。假设你允许因为少切换一次而损失0.5A的跟踪精度那电流误差项的差值是0.25 A²λ_sw就可以从0.25附近开始试。我自己的调整流程先设λ_sw0跑一遍记录平均开关频率和电流纹波。把λ_sw加到0.1再看开关频率有没有下降。逐步增大到0.3左右直到开关频率明显下降、但电流THD还在可接受范围。每个系统的量纲一致这个流程是通用的。4.3 权重调整里容易被忽略的一个细节有一点必须提醒代价函数里的电流误差项是预测值而不是实际值的误差。模型偏差越大代价函数本身的可信度越低。所以当你发现怎么调λ_sw都不对劲的时候先回头确认离散模型参数有没有写错而不是死磕权重。另外如果你后续想直接控制直流电压代价函数里加Vdc项电流项和电压项的量纲就不一致了。那时候不能简单把权重都设为1而要先做归一化处理或者用标幺值系统。这个我在后面扩展部分会再提一下。5. 仿真结果跟预期一致吗启动、稳态、动态和THD5.1 启动过程和直流电压建立用我上面给的参数启动仿真直流电压不会一开始就受控因为启动瞬间直流电容没电MPC的输出在低电压下工作桥臂基本走的是反并联二极管的不控整流路径。Vdc从0V先自然爬升到约510V左右也就是380V线电压经不控整流得到的峰值电压等Vdc超过这个值之后Boost特性才起作用MPC开始通过控制电流把电压拉向600V。我仿真的结果是大约0.25s进入稳态启动过程直流电压超调在5%左右没有振荡。这个启动过程取决于电压外环PI参数和电流限幅值如果你想更快建立电压可以适当提高id_ref限幅但代价是启动电流峰值变大。5.2 负载突变时MPC的动态响应整流器项目最关心的往往是动态性能。我把负载电阻从10Ω切换成5Ω相当于输出功率从36kW变成72kW按Vdc600V估算。由于电压外环PI响应需要时间直流电压会先跌落然后id_ref增加MPC在1到2个控制周期内就能把实际电流跟踪到新的参考值附近。整个恢复时间大概在20到30ms具体取决于外环带宽。这个结果说明一个关键问题MPC的内环动态很快但系统的整体动态响应仍然受电压外环PI限制。如果你希望直流电压跌得更少可以加大电压环PI的Kp但要注意不能太激进否则启动超调和负载阶跃都会出现电压振铃。5.3 网侧电流波形、单位功率因数和THD稳态下看三相电流波形接近正弦但会比SPWM方案多一些“毛刺”这是MPC开关频率不固定带来的高频分量。把网侧A相电压和A相电流放到同一个示波器里会发现电流相位和电压基本一致功率因数接近1。对电流波形做FFT分析我的仿真模型THD大约在3%到5%之间主要谐波呈现为宽频分布而不是集中在某几次谐波。这是因为MPC的开关频率在频谱上较为分散。5.4 和传统PI加SVPWM方案的对照为了确认MPC到底值不值得用我在同一套主电路上又跑了一版传统双闭环加SVPWM做对照结果大体上对比项模型预测控制PISVPWM是否需要调制器否是开关频率不固定固定电流内环动态非常快受PI带宽限制内环参数整定主要调权重系数需要整定PI和解耦项网侧电流THD一般谱分散较好频谱集中参数变化适应性较好需要重新调参控制器计算量较大较小我个人在项目里的感受是如果你在做一个参数经常变化、动态要求又高的平台MPC的优势非常明显如果工况固定、追求极限稳态波形质量那传统的调制方法仍然值得保留。6. 这一路调试下来我踩掉的那些坑6.1 预测符号写反导致电流倒灌最开始跑模型时直流电压建立不起来电流越来越大像是整流器变成了逆变器能量从直流侧倒灌回电网。查了半天最后发现是dq变换正负号的问题。这个问题特别隐蔽因为不报错波形看起来只是方向不对。我的排查方法是在仿真里只给一组固定的开关状态手动计算预测电流方向和公式推导对照。一旦发现符号反了电流偏差会越来越大解决办法就是统一坐标变换方向。拿到验证过的代码之后我把这组基础模型封存起来后面再搭维也纳整流器或者其它变换器都以这版方向定义为基准。6.2 Simulink数据类型和零阶保持器的细节Simulink里MATLAB Function的输入输出默认是double类型。但Universal Bridge的门极信号有时候会被识别成Boolean直接把0和1的double数组接进去仿真会报类型不匹配。我的做法是在函数输出后面加一个DataType Conversion模块再进Universal Bridge。另外一个容易被忽略的问题是零阶保持器。如果不加零阶保持器MATLAB Function的输入信号在仿真步进内部会被看成连续变化导致同一个控制周期内多次执行函数结果看似能用但实际上控制时序和真实硬件对不上。所有进入控制函数的信号都过一遍采样器采样时间设成Ts模型行为才和真实控制器一致。6.3 采样频率和求解器设置MPC的预测模型使用一阶欧拉离散Ts越小越准但计算量越大。我在三相两电平整流器上用Ts50μs跑20kHz效果还不错。如果Ts大于100μs一阶欧拉法的预测误差会明显增加电流纹波变大甚至可能不稳定。Simulink求解器我建议用固定步长离散求解器步长不超过10μs也就是Ts的1/5。如果步长太大PLL角度更新跟不上采样时序开关状态和坐标变换会错位。我一开始用可变步长求解器仿出了很多奇怪的高频毛刺改成固定步长后问题消失。6.4 延迟补偿预测一拍比不预测强太多实际控制系统从ADC采样到PWM输出中间一定存在计算延迟。MPC在这个周期计算出的最优开关状态最早也要到下一个周期才能施加到功率管上。如果你完全忽略这个延迟在低采样频率下稳定性会受到很大影响。补偿方法很简单在MATLAB Function里做两步预测。先根据当前采样值预测出id(k1)、iq(k1)再把id(k1)、iq(k1)当作当前值代入同一个预测公式算出id(k2)、iq(k2)。代价函数使用的就是k2时刻的预测电流。代码改动量不大实际效果非常明显。做了两步预测之后同样一组主电路参数下允许的最大采样周期可以放宽不少波形也更加干净。7. 我最后留下的几句话和后续扩展方向做三相整流器的MPC仿真真正难的不是Simulink建模也不是写那8行循环而是把数学模型的每一个符号都验证到位。我在这套模型上踩过符号反号、零阶保持器、采样时序这些坑之后最大的体悟是模型预测控制把传统PI调参的痛苦转移到了模型准确性和代价函数设计上你少写了一堆解耦代码但必须比谁都清楚自己的离散方程。如果你在这套模型基础上继续扩展可以往这几个方向走。第一把电流内环换成直接功率控制代价函数里同时包含有功和无功误差启动和动态响应会更快。第二加入权重自适应在线调整λ_sw让稳态和动态都保持比较好表现。第三加LCL滤波器改善网侧电流波形然后做谐振抑制。第四把三相两电平桥换成三电平NPC结构MPC的控制集从8个变成27个原理类似但代价函数设计和开关状态表会复杂不少。我自己的习惯是每次改主电路参数先跑一遍不控整流阶段确认直流电压自然爬升正常再切入MPC控制。这一步能帮你把主电路问题和算法问题分开排查速度快很多。希望这篇博客能让你在三相整流器MPC仿真这条路上少走一点弯路。