☰
PMSM模型预测控制:单矢量到三矢量的Simulink仿真详解
2026/10/16 8:54:05 网站建设 项目流程

1. 先把技术版图说清楚:单矢量、占空比、双矢量、三矢量各自解决什么问题

做永磁同步电机(PMSM)的模型预测控制(MPC)仿真,很多人第一反应就是搭个单矢量模型跑通再说。单矢量跑通之后,你会发现电流纹波大、稳态噪声明显,这时候有人开始加占空比,有人直接上双矢量、三矢量。我自己的经历也是这样,从单矢量一路改到三矢量,所以想把这一整套逻辑用一篇Simulink仿真的文章讲清楚,让后来的人少走弯路。

1.1 模型预测控制为什么在PMSM上这么受宠

模型预测控制的核心思路并不复杂:你不是要控制电流吗?那我先把逆变器所有能输出的开关状态全部列出来,然后逐个预测“如果这个周期用这个矢量,电流会变成多少”,最后选一个让电流误差最小的矢量执行。整个过程听起来像一个暴力枚举,但在数字控制器里执行起来非常直接,尤其适合带有强耦合、非线性特性的永磁同步电机。

和传统PI控制加空间矢量调制(SVPWM)相比,MPC最大的优势是动态响应快。PI需要调两个环多个参数,遇到负载突变或转速跳变时,电流环可能要几个毫秒才拉回来;而MPC在下一个采样周期就能切换出最合适的电压矢量,动态过程非常干脆。代价是稳态性能差:因为一个控制周期内只作用一个固定的电压矢量,电流在平均意义上被迫绕着参考值波动,形成明显的纹波。

1.2 从开关状态穷举到矢量组合寻优:一条清晰的演进路线

单矢量MPC是整条路线的基础款。两电平三相逆变器一共8个开关状态,对应6个非零电压矢量和2个零矢量,单矢量MPC在每个控制周期里从这8个候选中选出最优的那一个,然后在整个周期内只输出它。这个方案概念最简单,代码也容易写,但它有本质缺陷:分配粒度太粗,导致稳态精度差、开关频率漂移大。

占空比MPC是对单矢量的第一层修补。既然“一个矢量顶整个周期”太粗暴,那我让选中的非零矢量只作用一部分时间,剩下的时间切换到零矢量,相当于在“全有”和“全无”之间做一个折中。这个比例就是占空比,通常可以通过代价函数的二次关系直接解析算出最优值,计算量只比单矢量多一点点,但电流纹波能明显降下来。

双矢量MPC再往前走一步:不再让零矢量来填剩余时间,而是在相邻的两个非零矢量之间分配时间。这样等效电压矢量可以在扇区内的连线上滑动,比“非零矢量加零矢量”的直线路径更贴近实际需要的电压参考,动态和稳态表现都比占空比更好。

三矢量MPC则是这条路线的集大成者,每个周期内作用两个相邻非零矢量加零矢量,等效合成电压矢量的自由度更高,已经非常接近传统SVPWM的连续调制效果。它的问题也很明显:作用时间的计算复杂了,预测和评估的计算量上去了,而且候选组合需要重新设计。

1.3 四类策略的性能定位表

为了直观看出差异,我这段时间反复对比过这几种方案,把它们放在同一组电机参数和工况下观察,大致表现如下:

方案每周期矢量的作用方式电流THD计算量实现复杂度最典型的使用场景
单矢量1个矢量作用整个周期高低低教学演示、原理验证
占空比1个非零矢量加零矢量按比例分配中低低工程快速改造现有MPC
双矢量2个相邻非零矢量按比例分配中低中中追求动态性能且计算资源有限
三矢量2个相邻非零矢量加零矢量按比例分配低高高波形质量敏感、接近SVPWM效果

这张表只是相对趋势。实际THD的降幅和电机参数、采样频率都有关系,不能指望三矢量在所有工况下都能压掉一半纹波,但它确实是在往这个方向走。

2. 单矢量MPC:Simulink里的基础款是怎么跑起来的

我在搭双矢量、三矢量之前,花了不少时间把单矢量MPC的每一个环节掰开揉碎,因为后面所有改进都建立在同样的预测模型和代价函数上。如果这里符号搞错、离散化搞错,后面改再多矢量都是白搭。

2.1 逆变器提供的8个候选电压矢量和开关表

两电平三相逆变器由三个桥臂组成,每个桥臂要么上管导通,要么下管导通,所以一共有2的3次方等于8种开关组合。定义每一种组合为(Sa, Sb, Sc),取值1表示该相上桥臂导通、下桥臂关断。标准排列如下:

SaSbSc电压矢量编号矢量性质
000V0零矢量
100V1非零矢量
110V2非零矢量
010V3非零矢量
011V4非零矢量
001V5非零矢量
101V6非零矢量
111V7零矢量

6个非零矢量在α-β平面上相隔60度,正好把平面分成6个扇区。如果按等幅值变换的Clarke公式,电压矢量的αβ分量为:

u_alpha = Vdc * (2/3) * (Sa - 0.5Sb - 0.5Sc) u_beta = Vdc * (sqrt(3)/3) * (Sb - Sc)

这个系数特别容易踩坑。Simulink自带PMSM模块内部的坐标变换有些用的是等幅值,有些用的是等功率,系数差一个sqrt(2/3)的比例。如果你的预测模型和电机模块的变换系数不一致,跑出来的电流会整体偏小或偏大,PI都不需要,预测控制自己就把系统带偏了。

2.2 电流预测方程的离散化与代价函数设计

PMSM在d-q旋转坐标系下的定子电压方程,按电机惯例写法可以整理成:

ud = Rid + Ld(did/dt) - weLqiq uq = Riq + Lq(diq/dt) + weLdid + we*flux

其中we是电角速度,flux是永磁体磁链。用一阶前向欧拉离散化,采样周期为Ts,可以得到下一拍电流的预测值:

id_pred = id + Ts * (ud - Rid + weLqiq) / Ld iq_pred = iq + Ts * (uq - Riq - weLdid - we*flux) / Lq

这里注意:每个开关状态都会算出不同的ud和uq,所以id_pred和iq_pred也会不同。代价函数最常用的是电流误差平方和,也就是:

g = (id_ref - id_pred)^2 + (iq_ref - iq_pred)^2

选择让g最小的那个开关状态作为当前周期的输出。电机控制最终目标是电磁转矩,而转矩和iq强相关,所以iq的权重实际上隐含在里面;如果后续要加入转矩控制或者磁链控制,就需要改成带权重系数的多目标代价函数。

2.3 MATLAB Function函数实现骨架

在Simulink里,我习惯把整个MPC控制算法写进一个MATLAB Function模块,输入是id_ref、iq_ref、id、iq、theta和we,输出是三相开关信号。核心代码如下:

function [Sa,Sb,Sc] = mpc_single(id_ref, iq_ref, id, iq, theta, we, Vdc) R = 0.958; Ld = 5.25e-3; Lq = 12.0e-3; flux = 0.1827; Ts = 1e-5; table = [0 0 0; 1 0 0; 1 1 0; 0 1 0; 0 1 1; 0 0 1; 1 0 1; 1 1 1]; g_best = inf; Sa = 0; Sb = 0; Sc = 0; for i = 1:8 Sa_t = table(i,1); Sb_t = table(i,2); Sc_t = table(i,3); u_alpha = Vdc * (2/3) * (Sa_t - 0.5*Sb_t - 0.5*Sc_t); u_beta = Vdc * (sqrt(3)/3) * (Sb_t - Sc_t); ud = u_alpha*cos(theta) + u_beta*sin(theta); uq = -u_alpha*sin(theta) + u_beta*cos(theta); id_pred = id + Ts * (ud - R*id + we*Lq*iq) / Ld; iq_pred = iq + Ts * (uq - R*iq - we*Ld*id - we*flux) / Lq; g = (id_ref - id_pred)^2 + (iq_ref - iq_pred)^2; if g < g_best g_best = g; Sa = Sa_t; Sb = Sb_t; Sc = Sc_t; end end end

这段代码执行完后,输出Sa、Sb、Sc直接送到逆变器门极驱动。如果模型报代数环,可以在MATLAB Function后面加一个Memory模块,让输出延迟一拍,通常就能解决。MS注意好的,这部分先跑通,再把后面的占空比、双矢量、三矢量逐级替换控制模块。

3. 占空比MPC:不换矢量,只换“停留时间”的巧妙改进

很多人跑完单矢量MPC,看到电流波形第一反应是“这也太糙了”。我当时也一样,然后很自然地想到:能不能在一个控制周期里让非零矢量只作用一部分时间,剩下时间用零矢量?这就是占空比MPC的出发点。它在不改变“选矢量”逻辑的前提下,给每个周期增加了一个时间分配的维度,效果立竿见影。

3.1 单矢量“要么全有要么全无”的本质缺陷

单矢量MPC的问题在于量化粒度太粗。想想看,你本来需要的是一杯温水,但系统只给你“热水”“冰水”两个按钮,不管怎么选,最后温度都有偏差。控制周期越短,这种偏差越小,但受限于开关频率和硬件能力,Ts不可能无限小,所以只能靠算法层面的优化。

占空比方案相当于给每个周期增加了一个混合比例旋钮:这个周期先让优选出来的非零矢量作用d*T时间,再让零矢量作用(1-d)*T时间。等效出来的电压矢量,在这两个矢量之间的连线上滑动,很大程度上弥补了“离散电压矢量和实际需求电压”之间的落差。

3.2 最优占空比推导:从代价函数二次函数求导说起

既然占空比是一个连续变量,那就可以用解析方法找最优值。先定义两种情况下的预测电流:

  • x1:最优非零矢量作用整个周期时的预测电流
  • x0:零矢量作用整个周期时的预测电流

如果占空比为d,则等效预测电流可以近似为:

x_pred = x0 + d * (x1 - x0)

这里的x可以理解成(id, iq)组成的二维状态向量。代价函数:

J(d) = (id_ref - id_pred)^2 + (iq_ref - iq_pred)^2

把x_pred代入并展开,J(d)是d的二次函数,对d求导并令导数为0,就能得到最优占空比:

d* = ((x_ref - x0)^T * (x1 - x0)) / ((x1 - x0)^T * (x1 - x0))

最后把d*夹在0到1之间。这个推导在Simulink里实现起来很简单,多写几行向量运算就行。

提示:如果想让公式更贴近工程习惯,可以把x换成电流误差向量e,也就是e0 = x_ref - x0,e1 = x_ref - x1,然后用误差投影的几何意义理解同样成立。

3.3 改成占空比后,仿真模型里要改哪里

在Simulink模型里,占空比MPC的输出不再是简单三路开关信号,而是“三相占空比信号”。实现方法是先把选中的非零矢量和零矢量按d*的时间拼成一个完整周期,然后生成PWM脉冲送给逆变器。这里要注意PWM载波频率和MPC采样频率的关系:载波频率通常等于Ts的倒数,扇区内每个载波周期内对齐一个开关动作点,否则占空比信号和实际逆变器输出之间会有相位误差。

还有一个容易忽略的地方:占空比MPC计算最优d*时,默认电流变化轨迹在“非零矢量预测点”和“零矢量预测点”之间近似线性。实际电流轨迹是带反电动势和电阻项的指数曲线,但在Ts足够小的情况下线性近似误差很小。如果你把Ts拉到50微秒以上,这个近似就开始明显失真,所以这类方案对采样周期比较敏感。

4. 双矢量MPC:为什么选相邻非零矢量,以及作用时间怎么算

占空比MPC虽然比单矢量好,但它的剩余时间都用零矢量填充,等效电压矢量的轨迹只能在“非零矢量到零矢量”这条直线上走。双矢量MPC换了一种思路:不找零矢量,而是让两个非零矢量在一个周期里按比例分配时间。这样等效电压矢量的可到达区域变大,动态响应也更好。

4.1 双矢量候选集:6个相邻非零矢量对的组合逻辑

两电平逆变器有6个非零电压矢量,按扇区顺序编号V1到V6。为什么要选相邻矢量组合,而不是任意两个组合?因为任意两个不相邻的矢量之间,等效电压矢量需要穿越很大区域,合成出来的电压矢量指向可能偏差很大,而且会带来不必要的高频开关动作。相邻矢量的组合只在60度扇区内变化,每次切换最多让一个桥臂翻转,开关损耗和电流谐波都能接受。

所以候选集就是6个相邻矢量对:(V1,V2)、(V2,V3)、(V3,V4)、(V4,V5)、(V5,V6)、(V6,V1)。每一对矢量对应一个扇区。控制器的任务变成两件事:先确定当前时刻使用哪个矢量对,再确定这对矢量之间的时间比例。

4.2 伏秒平衡与等效电压矢量下的作用时间求解

双矢量MPC的作用时间计算和占空比MPC非常像,区别只是把“零矢量”换成了第二个非零矢量。假设一对候选矢量为v1和v2,v1的作用比例为d,v2的作用比例为1-d,那么等效电压矢量为:

u_eq = d * v1 + (1-d) * v2

把这等效电压矢量代入离散预测方程,得到预测电流x_pred(d),再构造代价函数并求导,得到的d*公式和占空比那一节几乎一样:

d* = ((x_ref - x2_pred)^T * (x1_pred - x2_pred)) / ((x1_pred - x2_pred)^T * (x1_pred - x2_pred))

其中x1_pred是v1作用整个周期时的预测电流,x2_pred是v2作用整个周期时的预测电流。最后把d*限制在0到1之间。这样每个候选矢量对都能算出一组最优时间和对应的最小代价,最后在所有矢量对里选代价最小的那组作为输出。

代码结构上,双矢量MPC只需要把单矢量的8次枚举改成6次“矢量对评估”,每次评估内部还要算一次d*。计算量比单矢量翻了约一倍,但远没到三矢量那种程度。如果在单片机上实现,这个计算量完全可控。

4.3 时间分配和扇区判断在模型中的联动

在Simulink里,双矢量方案建议不要用“纯开关信号输出”的方式,而是输出三相占空比信号给PWM发生器。这样最方便:先根据选中的矢量对和作用时间,生成一个周期内的开关动作序列,再转换成三相占空比。比如选中V1和V2,V1作用0.3T、V2作用0.7T,那么在这一个周期内,三相的开关状态会先保持一段(100),再切换到(110),最后视情况回到零矢量。

扇区判断在这类算法里通常不难。你只需要看当前合成电压矢量落在哪个60度区间。但要注意,这里说的合成电压矢量不是实际测量出来的,而是根据预测方程反推的参考电压矢量。在双矢量方案里,我一般会先用单矢量MPC的思路确定一个目标方向,再判断它落在哪个扇区,然后把该扇区对应的两个边界矢量作为候选。这样比直接枚举6个矢量对更能减少无效计算。

5. 三矢量MPC:从穷举矢量退化成选扇区的质变

三矢量MPC是目前这几个方案里控制精度最高的一档,也是我在Simulink里调得最久的一版。它的核心变化不是“三个矢量比两个矢量多一点”,而是算法结构彻底变了:不再是逐个枚举开关组合,而是先算出参考电压矢量,然后按SVPWM的思路在固定扇区里做时间分配。

5.1 三矢量的候选组合生成:两个相邻非零矢量加零矢量

三矢量的候选不是任意三个开关状态的组合,而是每个60度扇区内的两个边界非零矢量,再加上零矢量。比如扇区1,候选组合就是V1、V2、V0;扇区2就是V2、V3、V0,以此类推。所以整个三矢量算法的候选集合是6个扇区组合,每个组合内包含3个电压矢量。

为什么还要加零矢量?因为两个非零矢量的时间比例虽然能合成出扇区内任意方向的电压矢量,但合成矢量的长度被限定在由两个非零矢量端点连成的线段上,不能太短。加入零矢量之后,可以额外调整等效矢量的“平均长度”,让合成范围变成整个扇区内部。直观来说,就像先把两个方向向量混合成向量a,再加一个可以任意拉低平均幅值的零向量,这样就能覆盖扇区里的几乎所有目标点。

5.2 无差拍参考电压与SVPWM式时间分配

三矢量MPC的第一步,是先根据电流预测方程反解出一个“无差拍”参考电压。这个参考电压的含义是:如果这个周期能完美输出这么一组ud、uq,那么下一拍电流就能精确等于参考电流。反解公式来源就是把离散化方程中的id_pred替换成id_ref:

ud_ref = Ld * (id_ref - id) / Ts + Rid - weLqiq uq_ref = Lq * (iq_ref - iq) / Ts + Riq + weLdid + we*flux

然后反Park变换得到αβ轴分量,判断参考电压所在扇区。比如它落在扇区1,那么本周期就用V1、V2、V0三个矢量。作用时间按下式分配:

t1 = K * sin(π/3 - theta_sector) * T t2 = K * sin(theta_sector) * T t0 = T - t1 - t2

其中K等于sqrt(3)*|u_ref|/Vdc再乘一个系数,系数取决于你的Clark变换方式。theta_sector是参考电压矢量在当前扇区内相对起始边的角度,范围0到60度。这个公式其实就是SVPWM的经典时间计算公式,很多人没意识到它可以直接移植到MPC里用,因为它本质是伏秒平衡。

5.3 三矢量相对双矢量在谐波、开关频率、计算量上的实际权衡

三矢量方案的电流THD通常是最低的,这点在很多仿真对比里都能看到。因为等效电压矢量的合成自由度更高,电流轨迹更贴近理想正弦包络,谐波自然被压下去。代价是计算量明显上升:每个控制周期要做扇区判断、三角函数求解、时间分配和预测评估,MATLAB Function里的代码量也会大不少。

另一个实际问题是开关频率漂移。三矢量方案虽然在一个周期内使用了三个矢量,但开关动作点仍然取决于参考电压矢量的变化,不是严格的固定频率PWM。如果你后续想做硬件实验,这个特征要注意。很多半实物平台会对MPC输出再做一层周期化处理,否则逆变器发热和谐波都会超出预期。

我用三矢量方案跑下来,最大的感受是:它和传统SVPWM的效果越来越接近,但保留了MPC快速响应和直接处理约束的优势。如果你是在做课题研究,三矢量方案提供的对比数据会非常扎实;如果只是工程应用且计算资源有限,双矢量加合理占空比其实性价比更高。

6. 这套仿真模型里最容易翻车的几个细节

最后这部分是纯粹的踩坑记录。我调这套Simulink模型时,遇到的很多问题不是算法本身,而是工程实现层面的细节。有时候波形乱七八糟,不是算法错了,是Simulink模型里某个环节没对齐。

6.1 坐标变换的角基准不统一,电流预测全乱

最坑的是坐标变换的角基准。Simulink自带PMSM模块输出电角度theta,你用它做Park变换时,必须和你自己的电机方程、反电动势方向统一。如果电机模块用的是某个参考方向,你的控制代码里却用了相反的Park矩阵,结果是id和iq整反,预测控制会一直往错的方向推,电流直接发散。我的排查经验是:先断开MPC,用一个简单的开环电压给定跑一下,看电机的dq电流方向是否和自己方程一致,确认无误再接入预测算法。

6.2 采样周期和预测周期不一致,控制效果失真

这是比坐标变换更隐蔽的问题。Simulink模型里的求解器步长、控制器模块的采样步长、预测方程中的Ts,这三个时间参数如果没设成一致,仿真结果会非常具有迷惑性。比如预测方程里写的Ts是1e-5,但MATLAB Function模块的采样周期设成了1e-4,那控制器实际每10个仿真步才更新一次,但预测公式假设每个步长都在预测,电流预测值和实际自然就对不上。

建议把Ts定义成一个工作区变量,Simulink的固定步长和预测方程的Ts都引用同一个变量,这样改参数时不会漏改。

6.3 权重系数设置的由果推因法

如果你用纯电流MPC,代价函数里两项误差的权重天然是1,不需要调。但很多人把目标改成转矩和磁链误差时,就必须面对权重系数lambda。这个系数没有解析公式,常规做法是看仿真波形倒推:如果转矩响应太慢,说明转矩项的权重偏低;如果磁链波形过冲,说明磁链项权重太高。我习惯先让lambda取一个中间值,然后只调一两个数量级,观察稳态和动态的取舍。

6.4 代数环处理:MATLAB Function要不要加单位延迟

MPC模块的输出直接送逆变器,逆变器电流又作为模块输入,Simulink经常会报代数环错误。最简单的解决办法是在MATLAB Function的输出端加一个零阶保持器或者Memory模块。但要注意,加延迟会让当前周期的控制动作晚一个周期生效,这在预测控制里其实可以接受,因为预测模型本身就是基于当前周期状态外推下一拍。不要试图用Transport Delay去解决代数环,那样只会引入额外相位滞后。

6.5 死区与开关频率漂移的观察

仿真模型里如果不加死区,单矢量MPC和三矢量MPC的对比会很干净,但实际硬件会多出死区时间、管压降等非理想因素。在Simulink里模拟死区,可以在门极信号和桥臂之间串联一个Dead Time模块。加了死区之后,三矢量方案的低THD优势更明显,因为它的开关动作次数相对均匀,死区造成的畸变更容易被平均掉。

最后再分享一个小技巧:不管你要做单矢量、占空比、还是双矢量、三矢量,我建议先把单矢量的模型完整保存一份,后续所有版本都复制改,不要在一个文件里反复覆盖。多矢量方案的对比结果需要统一工况、统一参数,如果每个方案的文件里电机参数或采样时间悄悄变了,出来的对比图说服力就大打折扣。我自己保留了一套“基础电机模型”和一套“控制算法库”,换方案只换库里的控制模块,这样整个调试周期会短很多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询