简介:SVPWM分析、各个扇区详细计算以及Matlab仿真资料包,面向电力电子、电机驱动领域的工程师和中高级学习者,重点讲解空间矢量脉宽调制技术中扇区判断、矢量合成与作用时间计算等核心难点,可帮助读者掌握七段式和五段式发波策略及其谐波与损耗特性。压缩包内共1个文件,为PDF文档,大小1.38MB,包含大量公式推导、扇区划分图示及Matlab仿真说明,适合对照阅读与反复研习。资源深入梳理两电平逆变器八种电压矢量、扇区编号规律以及矢量切换顺序,同时针对SVPWM发波路径选择、零矢量插入方式对开关损耗和散热影响等常见问题作出说明,内容较教材更加细致。目前已有1297人学习下载,对于想深入理解SVPWM并开展仿真的工程师和学生来说,这是一份值得收藏的参考笔记。
1. SVPWM 扇区判断:为什么所有 FOC 工程都绕不开这张六边形地图
做电机控制或者三相逆变器的人,迟早会撞上 SVPWM。它的核心就一句话:把期望的电压矢量,拆成六个固定方向上的有效矢量加两个零矢量,让三相桥臂在一个开关周期里轮流输出。而这一切的第一步,是判断当前电压矢量落在六个扇区里的哪一个。很多人在这里翻车:明明变换、计算都对,波形上却出现相位错位的畸形波,甚至三相电流一条正一条负,最后查下来,竟然是扇区判断的符号定义和后续查表对不上。
这篇文章会把扇区判断的原理、六个扇区的矢量作用时间推导、Matlab/Simulink 里的可复现模型一次讲透。新手能照着代码把仿真跑起来,熟手能在这里对表对齐符号约定。它解决的是 FOC 落地中最容易出玄学问题的环节:为什么同一个公式,别人跑出来是对的,你跑出来就是错的。
2. 扇区判断为什么是 SVPWM 的第一道坎:从八种开关状态到六扇区
2.1 六个有效矢量和两个零矢量:扇区划分的几何来源
三相桥臂一共六个开关管,每一相上下桥臂互补导通,所以状态只有八种:000、001、010、011、100、101、110、111。把这八种状态对应的相电压合成矢量画在 αβ 平面上,会发现 000 和 111 合成结果都是零矢量,落在原点;剩下六个状态均匀分布在圆周上,每两个之间相差正好 60 度。
这六个有效矢量把平面切成六个 60 度的扇形区域,这就是扇区编号的来源。有一个关键结论需要先说清楚:SVPWM 能合成的最大线性电压矢量,是矢量六边形内切圆的半径,也就是 Udc/√3,而不是 Udc。这意味着在同样的母线电压下,SVPWM 的电压利用率比正弦 SPWM 高出约 15%。这个优势正是电机控制里普遍采用 SVPWM 的根本原因。
六边形内切圆的概念也决定了过调制的边界:当目标矢量模长超过内切圆时,T1 加 T2 会大于开关周期 Ts,必须做等比例缩放。这个细节很多人等到仿真出来波形顶部被削平才想起来处理。从几何上看,扇区判断本身并不复杂:只需要知道目标电压矢量的方向落在哪个 60 度区间里。难点在于工程实现时,用什么样的量去判断,以及边界条件怎么处理。
2.2 扇区判断的正负号判据:N 值法与三相电压查表法
常见的扇区判断有两种思路。第一种是解析几何法,直接看 Uα 和 Uβ 之间的关系,比如第二扇区的边界条件是 β 轴分量大于某个 α 轴函数;第二种是三相电压符号查表法,把三相参考相电压的正负组合编码成一个 N 值,再用 switch 映射到扇区号。实际工程中第二种用得多,因为实现简单,而且天然避开了特殊角度的数值比较问题。
三相参考相电压可以由 Uα、Uβ 反变换得到:令 ua = u_alpha,ub = -0.5 * u_alpha + sqrt(3)/2 * u_beta,uc = -0.5 * u_alpha - sqrt(3)/2 * u_beta。注意这里用的是等幅值 Clarke 变换的反变换,如果前级用的是等功率变换,u_alpha 和 u_beta 会整体差一个 0.816 的系数,扇区判断在边界处会错乱,具体排查方法放到第 4 章。
function [sector] = svpwm_sector(u_alpha, u_beta) % 输入: u_alpha, u_beta 目标电压矢量在静止坐标系下的分量 % 输出: sector = 1~6,对应空间矢量图中的六个扇区 % 由等幅值 Clarke 反变换得到三相参考相电压 ua = u_alpha; ub = -0.5 * u_alpha + sqrt(3)/2 * u_beta; uc = -0.5 * u_alpha - sqrt(3)/2 * u_beta; % 正负号编码为 N 值,bit0 对应 ua,bit1 对应 ub,bit2 对应 uc N = (ua > 0) + 2 * (ub > 0) + 4 * (uc > 0); switch N case 1, sector = 1; % 符号组合 (+, -, -) case 3, sector = 2; % (+, +, -) case 2, sector = 3; % (-, +, -) case 6, sector = 4; % (-, +, +) case 4, sector = 5; % (-, -, +) case 5, sector = 6; % (+, -, +) otherwise, sector = 0; % 理论上不会进来,保留兜底 end end这段代码里 N 值的映射需要特别记住:如果把它改成 1、3、2、6、4、5 之外的顺序,后面所有扇区都错位。符号组合和扇区号的对应关系,取决于你定义的扇区是逆时针还是顺时针编号。我这里按数学正方向逆时针编号:第一扇区从 0 度到 60 度,中心角 30 度处 a 相电压最大,所以符号是正、负、负。这是一个很隐蔽的约定,网上不同代码风格差异很大,抄的时候务必先对着单位圆验证一轮。
2.3 扇区判断用什么量:参考电压、重构电压还是实际相电压
这是很多做驱动的人忽略的问题。扇区判断到底拿什么电压来算?在纯软件仿真里,拿的当然是目标电压矢量,也就是电流环或者速度环输出的电压指令。但在实际逆变器里,你并没有一个「真实」的 Uα 和 Uβ 可以直接读,通常是拿母线电压乘以当前占空比做重构,估算出逆变器实际输出的相电压。
这里有个重要区别:电压指令是前馈量,重构电压是反馈量。扇区判断如果用电压指令,那么它只代表「你希望输出什么方向」,控制器会严格按这个方向去分配矢量;如果用重构电压,它反映的是「实际输出过什么方向」,会包含死区、管压降、母线波动带来的误差。两种做法都能工作,但调试含义完全不同。
我一般会建议在软件里用电压指令做扇区判断,因为它是平滑连续的量,扇区边界不会因为测量噪声而反复跳变;重构电压只用于观测和死区补偿。有人贪图省事,直接拿 ADC 采回来的重构电压算扇区,结果在扇区边界处开关噪声耦合进来,N 值在一个 PWM 周期内来回跳,这就是典型的「判断量选错」引发的玄学问题。
3. 各个扇区矢量作用时间的详细计算:X/Y/Z 中间量与查表实现
3.1 单个扇区的时间反解:以扇区 1 为例
扇区判断只解决问题的一半,另一半是:在这个扇区里,相邻两个有效矢量各作用多长时间。以第一扇区为例,目标电压矢量夹在 V1(100)和 V2(110)之间,V1 方向是 a 轴正方向,V2 方向是 60 度方向。设 T1 是 V1 的作用时间,T2 是 V2 的作用时间,T0 是零矢量补充时间,那么 T1 + T2 + T0 = Ts。
把矢量方程拆到 αβ 轴。V1 的 αβ 分量为 (2/3 * Udc, 0),V2 的分量为 (1/3 * Udc, sqrt(3)/3 * Udc)。平均电压等于 T1/Ts * V1 加 T2/Ts * V2,与目标 (u_alpha, u_beta) 相等。解这个二元一次方程组,得到 T2 = sqrt(3) * u_beta * Ts / Udc,T1 = (1.5 * u_alpha - sqrt(3)/2 * u_beta) * Ts / Udc。
这个推导过程值得亲手做一遍,因为它能解释为什么所有教材里都会定义 X、Y、Z 三个中间变量——每个扇区解出来的 T1、T2 无非是那三个代数式的正负组合。你自己推完第一扇区,后面五个扇区可以不查表,直接按相邻矢量的几何关系推出来,这样就算某天换了扇区编号约定,你也不会被别人的表带偏。
3.2 六个扇区的 X/Y/Z 映射表与 Matlab 代码
有了第一扇区的基础,我把六个扇区全部反解一遍,得到下面这张表。这里统一采用逆时针扇区编号,T1 是扇区起始边那个有效矢量的作用时间,T2 是扇区结束边那个有效矢量的作用时间。定义 X、Y、Z 如下:X = sqrt(3) * u_beta * Ts / Udc,Y = (sqrt(3)/2 * u_beta + 1.5 * u_alpha) * Ts / Udc,Z = (sqrt(3)/2 * u_beta - 1.5 * u_alpha) * Ts / Udc。
| 扇区 | T1 | T2 |
|---|---|---|
| 1 | -Z | X |
| 2 | Y | Z |
| 3 | X | -Y |
| 4 | Z | -X |
| 5 | -Y | -Z |
| 6 | -X | Y |
需要强调,这张表是和我的 X/Y/Z 定义绑定的。如果你在网上找到另一张看起来「差不多」的表,但它的 Z 定义是 1.5 * u_alpha - sqrt(3)/2 * u_beta,也就是两边差一个负号,那你直接抄过来,扇区 1 和扇区 4 的 T1、T2 会整个反掉。我见过不止一个项目出现这种问题:电流波形在某个扇区交界处突然劣化,查半天是表抄串了。
function [T1, T2] = svpwm_time(u_alpha, u_beta, Ts, Udc) % 输入: u_alpha, u_beta 目标电压矢量分量,Ts PWM 周期,Udc 直流母线电压 % 输出: T1、T2 相邻有效矢量的作用时间,单位与 Ts 一致 % 先算扇区,再算三个中间量 sector = svpwm_sector(u_alpha, u_beta); sqrt3 = sqrt(3); X = sqrt3 * u_beta * Ts / Udc; Y = (sqrt3/2 * u_beta + 1.5 * u_alpha) * Ts / Udc; Z = (sqrt3/2 * u_beta - 1.5 * u_alpha) * Ts / Udc; switch sector case 1, T1 = -Z; T2 = X; case 2, T1 = Y; T2 = Z; case 3, T1 = X; T2 = -Y; case 4, T1 = Z; T2 = -X; case 5, T1 = -Y; T2 = -Z; case 6, T1 = -X; T2 = Y; end end这段代码的逻辑很简单,但参数单位容易出错。u_alpha、u_beta 和 Udc 必须同单位,比如都是伏特;Ts 单位无所谓,只要 T1、T2 的结果跟你要写入的比较寄存器单位一致即可。很多人喜欢把所有量都标幺化,母线电压 Udc 归一化成 1,这时扇区判断和 X/Y/Z 计算公式都不变,只是物理意义变成相对值。我习惯把 Udc 留在公式里,因为查过调制条件 T1 + T2 > Ts 时,用绝对值判断更直观。
3.3 七段式与五段式:切换点计算和 PWM 生成
算出 T1、T2、T0 之后,还要把三个时间变成三相桥臂的切换时刻。七段式是主流的默认选择:每周期内零矢量分成四段,首尾各 T0/4,中间 T0/2,有效矢量对称分布在两侧。它的好处是每次开关瞬间只有一相桥臂动作,开关损耗相对可控,纹波也小。
切换点的计算是固定的套路:ta = T0/4,tb = ta + T1/2,tc = tb + T2/2。注意这里 ta、tb、tc 只是三个中间变量,不是 a 相、b 相、c 相的实际比较值。三相比较寄存器 Tcm1、Tcm2、Tcm3 的对应关系随扇区变化。第一扇区里,A 相在 V1 段先开通,B 相在 V2 段开通,C 相最后到 111 才开通,所以比较值按从小到大分配给 A、B、C。
function [Tcm1, Tcm2, Tcm3] = svpwm_switch(T1, T2, Ts, sector) % 输入: T1、T2 有效矢量时间,Ts 周期,sector 扇区号 % 输出: Tcm1~Tcm3 三相比较值,直接与三角载波比较 % 过调制判断与缩放 if T1 + T2 > Ts scale = Ts / (T1 + T2); T1 = T1 * scale; T2 = T2 * scale; end T0 = Ts - T1 - T2; ta = T0 / 4; tb = ta + T1 / 2; tc = tb + T2 / 2; switch sector case 1, Tcm1 = ta; Tcm2 = tb; Tcm3 = tc; case 2, Tcm1 = tb; Tcm2 = ta; Tcm3 = tc; case 3, Tcm1 = tc; Tcm2 = ta; Tcm3 = tb; case 4, Tcm1 = tc; Tcm2 = tb; Tcm3 = ta; case 5, Tcm1 = tb; Tcm2 = tc; Tcm3 = ta; case 6, Tcm1 = ta; Tcm2 = tc; Tcm3 = tb; end end过调制缩放这一行值得展开。T1 加 T2 超过 Ts 时,如果不缩放,直接让 T0 变成负数,实际 PWM 波形就会被截断,输出的基波电压反而低于目标值,这就是电压利用率下降的直接原因。正确做法是按比例把 T1、T2 缩回 Ts 内,保留矢量方向不变。这个处理在电流环大动态响应时一定会触发,不做缩放,高速弱磁区域波形会明显畸变。
五段式与七段式的区别在于,每周期只插入一个零矢量,或者插在开头或者插在中间。每个扇区只用一个零矢量,开关次数减少三分之一,但电流纹波变大,某些扇区边界会出现一次开关状态跳变两位的情况。我的建议是:通用驱动器用七段式,追求效率且对噪声不敏感的场景再考虑五段式。
4. SVPWM 常见问题与排查:波形异常的 5 个真实原因
4.1 扇区号连续跳变但输出矢量不对:坐标系系数惹的祸
现象:示波器上看相电流,波形有点像样但相位整体偏移,或者六个扇区里有两个扇区的电流畸变特别明显。排查第一步是看扇区号:在 simulink 里把 sector 信号拉出来,应该是在 1 到 6 之间线性循环。如果扇区号确实在正常循环,但 PWM 波形不对,问题多半不在判断逻辑,而在坐标系变换的幅值系数。
原因:前级使用的是等功率 Clarke 变换,得到 Uα、Uβ 比等幅值变换小一个系数。扇区判断对幅值不敏感,因为正负号不变;但作用时间公式里 Uα、Uβ 直接参与乘除,幅值不对算出来的 T1、T2 全错。这是「判断对、计算错」的典型场景。
解决:统一变换方式,要么都按等幅值,要么把系数补回来。我一般会在 Clarke 变换函数注释里写明「等幅值,系数 2/3」,这样两个月之后自己回来看也能立刻对上。另一个快速验证法是给定 u_alpha = 0, u_beta = 0.5 * Udc,理论输出矢量应完全落在 theta 轴方向,此时 T1、T2 应该满足扇区 1 和扇区 2 的边界关系,数值可验。
4.2 扇区边界处抖动与开关噪声:为什么要在判断加滞环
现象:电流波形整体没问题,但在扇区交界处有高频毛刺,开关频率的整数倍噪声明显变大。把 sector 信号展开看,扇区号在边界附近不是稳定跳变,而是在两个值之间来回抖。
原因:实际系统里 u_alpha、u_beta 带有测量噪声或重构误差,尤其在某一相电压过零附近,符号正负不稳定,N 值在一个 PWM 周期内反复变化。扇区判断本身没有记忆性,噪声一来就跳。
解决:在扇区判断前加一个低通滤波,或者对 N 值做边沿锁存:只有连续两个周期判断结果一致才更新扇区号。还有更工程化的做法是直接对角度用锁相环,但那样会引入额外延迟,小系统没必要。我常用的手段是把边界角往两边各推 1 度做成滞环带,代价是边界处的矢量方向有微小偏差,对电流环来说完全可接受。
4.3 过调制时电压利用率下降:T1+T2>Ts 的缩放处理
现象:转速环给定一个大阶跃,母线电压没变,但电流峰值上不去,波形顶部出现平顶。很多初学者怀疑是电流环饱和,实际上可能是过调制处理缺失。
原因:期望电压矢量超出六边形内切圆,T1 加 T2 大于 Ts。如果没有缩放,PWM 比较值会出现 ta、tb、tc 顺序颠倒,输出波形严重畸变,基波分量反而小于预期。
解决:在计算 T0 之前先判断 T1 + T2 > Ts,满足则按比例缩放。缩放的物理意义是保持电压矢量方向不变,只把模长拉回内切圆边缘。这个处理对电流环来说相当于输出限幅,配合抗积分饱和一起用。注意缩放要放在扇区判断之后、切换点计算之前,顺序错了结果就不对。
4.4 低调制比下脉冲丢失:死区与最小脉宽冲突
现象:母线电压很高,电机在低速运行时,相电流过零附近出现一段明显的缺口,电机噪声变大,甚至转速有小幅波动。
原因:低速时输出电压很小,T1、T2 可能只有几百纳秒,比死区时间还短。桥臂插入死区后,有效脉冲被完全吃掉,这一拍实际上没有输出电压,相电流被迫续流,波形出现台阶。
解决:工程上做一个最小脉宽钳位,当 T1 或 T2 小于某个阈值(通常是两倍死区时间)时,把这段时间强制归零或者并入相邻矢量段。还有一种思路是低速段切换到五段式,减小开关次数,给有效矢量留出更多余量。这个阈值必须结合你实际用的功率管开关特性来定,不能照抄别人的数。
4.5 查表抄错与旋转方向相反:用单位圆验证法兜底
现象:仿真模型和参考代码长得几乎一样,但电流波形就是不对,扇区号顺序可能是 1、2、5、6、3、4 这种奇怪的循环。
原因:扇区编号约定不同。有人按逆时针编号,有人按顺时针编号,还有人以 30 度为扇区边界而非 0 度。X/Y/Z 的定义也存在正负号差异,这些都导致查表项不一致。
解决:不要盲目改公式,先用单位圆验证法兜底。设 u_alpha = cos(theta),u_beta = sin(theta),theta 从 0 到 2π 连续扫描,打印扇区号。如果推导正确,扇区号应该是 1、2、3、4、5、6 依次出现各 60 度。如果出现 1、2、5、6 这样的序列,说明符号定义或者表的某一项反了。这个验证方法简单到令人忽略,但真能解决网上代码互相抄造成的表项混乱问题。
5. 用 Matlab/Simulink 跑通最小 SVPWM 模型:扇区判断的三种验证方法
5.1 最小模型:两个 Fcn 模块加三角载波比较器
在 Simulink 里搭一个最小验证模型,不需要搭完整的电机模型。用一个 Ramp 模块生成从 0 到 2π 的斜波作为电角度 theta,周期设 0.02 秒对应 50Hz;再用两个 Fcn 模块分别生成 u_alpha = cos(theta)、u_beta = sin(theta),幅值可以缩放到 0.5 * Udc 以内避免过调制。把这两个量接进 svpwm_sector 函数对应的 MATLAB Function 模块,输出接到 Scope,就能看到扇区号随时间从 1 变到 6 再回 1。
第二步把 svpwm_time 和 svpwm_switch 也接进去,得到三个比较值 Tcm1、Tcm2、Tcm3。用一个 Repeating Sequence 生成幅值 0 到 Ts 的三角载波,频率就是 PWM 开关频率。三个比较值和载波分别进 Relational Operator,输出就是三相桥臂的开关信号。到这一步,你就有了一个完整的开环 SVPWM 波形发生器,可以做任何后续验证。
5.2 扇区判断的三板斧验证法
第一板斧是静态点验证:取 theta = 30 度,此时目标矢量落在扇区 1 和扇区 2 的边界上,T1 和 T2 应该相等。取 Udc = 300,Ts = 0.0001,模长 0.5 * Udc,代入计算,如果 T1 不等于 T2,说明查表有问题。第二板斧是斜坡验证:theta 连续扫描,记录一个完整周期的扇区序列,必须是 1、2、3、4、5、6 按顺序出现,每个扇区持续时间为载波周期乘以 16667,也就是 60 度对应的时长。第三板斧是反向验证:把最终生成的 PWM 开关序列做周期平均,还原出三相平均电压,再反变换到 αβ 轴,应该和输入的 u_alpha、u_beta 重合,误差只来自离散化步长。
这个模型跑通之后,就可以往里面加死区、加母线电压波动、加电流环,一步步逼近真实系统。我个人的习惯是,每改一次扇区判断相关的代码,就回到这个最小模型上跑一遍斜坡验证,花不了一分钟,但能避免把错误带到后面复杂的闭环模型里去。希望这些推导、代码和踩坑记录能帮你在 SVPWM 这条路上少走几个弯路。
本文还有配套的精品资源,点击获取