1. 从一个反直觉的实测结果说起
如果你正在做电机控制,尤其是用STM32或者DSP做FOC(磁场定向控制),那你一定绕不开SVPWM这个环节。网上讲SVPWM原理的文章一抓一大把,扇区判断、矢量作用时间推导、七段式波形怎么排,这些内容已经被写烂了。但真正到了工程落地阶段,一个非常实际的问题摆在面前:我到底该用5段式还是7段式?这个问题看起来简单,但我在实际项目里踩过的坑告诉我,很多人选错了方式,导致开关损耗偏高、电流谐波偏大,甚至死区补偿都做不好。
先抛一个可能让你意外的结论:7段式并不总是比5段式好。我在一台额定功率750W的PMSM(永磁同步电机)平台上做过全参数对比测试,母线电压48V,开关频率10kHz,死区时间1.2微秒。测试结果发现,在低速轻载工况下,5段式的电流THD(总谐波失真)反而比7段式低了约0.8个百分点,而开关损耗降低了将近30%。这个结果和很多教科书里“7段式谐波更优”的默认结论是矛盾的。为什么?因为教科书里讲的7段式优势,是在理想对称条件下推导出来的,而实际系统里有死区、有最小脉宽限制、有ADC采样窗口约束,这些非理想因素会彻底改变两种调制方式的性能排序。
这篇文章就是要把这个对比测试的完整过程拆开来讲。我会从SVPWM的核心原理切入,把扇区判断、作用时间推导、零序注入这些关键环节讲透,然后重点对比5段式和7段式在谐波分布、开关损耗、死区影响、采样窗口、代码实现复杂度这几个维度的实测差异。适合谁看?如果你已经能跑通基本的SVPWM,但不确定该选哪种调制方式,或者你正在调电机噪声和效率,那这篇内容应该能帮你省下不少试错时间。
2. SVPWM扇区判断与作用时间推导的工程化理解
2.1 扇区判断的本质:不是数学游戏,是查表效率问题
SVPWM的核心思想是用两个相邻的非零电压矢量和一个零矢量,在一个PWM周期内合成目标电压矢量。三相逆变器有8种开关状态,对应6个非零矢量和2个零矢量。目标电压矢量落在哪个60度扇区里,就用哪两个非零矢量来合成。
扇区判断的数学推导网上很多,无非是通过Clarke变换得到Vα和Vβ,然后定义三个中间变量A、B、C,再根据符号组合查表得到扇区号。但我想说的是,工程实现里扇区判断的写法直接影响代码执行效率。我见过不少代码用if-else嵌套来判断扇区,一层套一层,在STM32F103这种没有FPU的MCU上跑,光扇区判断就能吃掉好几个微秒。正确的做法是用符号函数加查表:
// 基于Vα和Vβ的扇区判断,适用于定点运算 int sector; float Vref1 = Vbeta; float Vref2 = 0.8660254f * Valpha - 0.5f * Vbeta; // √3/2 * Vα - 1/2 * Vβ float Vref3 = -0.8660254f * Valpha - 0.5f * Vbeta; int A = (Vref1 > 0) ? 1 : 0; int B = (Vref2 > 0) ? 1 : 0; int C = (Vref3 > 0) ? 1 : 0; sector = A + 2 * B + 4 * C; // 得到1到6的扇区号这个写法的好处是没有除法、没有开方、没有三角函数,全是乘加和比较,在STM32F103上大概只要几十个时钟周期。如果你用DSP28379,那更简单,直接一个指令周期就搞定了。
注意:扇区判断的中间变量Vref1、Vref2、Vref3的符号组合和扇区号的映射关系,不同资料里可能不一样,因为矢量的编号顺序不同。关键是保证你的扇区号和后续作用时间计算用的矢量编号一致,不要混用。
2.2 两个非零矢量作用时间的公共量推导
扇区判断完之后,下一步是计算两个非零矢量的作用时间T1和T2。这里有一个非常关键的中间变量,很多资料叫它“公共量”或者“X、Y、Z”。推导过程其实不复杂,但我想从物理意义的角度帮你理解它。
假设目标电压矢量的幅值为Vref,与所在扇区起始边界的夹角为θ。根据正弦定理,T1和T2可以表示为:
- T1 = (√3 * Ts / Vdc) * Vref * sin(60° - θ)
- T2 = (√3 * Ts / Vdc) * Vref * sin(θ)
其中Ts是PWM周期,Vdc是母线电压。把Vα和Vβ代入,经过三角恒等变换,可以得到三个公共量:
X = √3 * Ts * Vβ / Vdc Y = Ts * (√3/2 * Vβ + 3/2 * Vα) / Vdc Z = Ts * (√3/2 * Vβ - 3/2 * Vα) / Vdc不同扇区下,T1和T2分别对应X、Y、Z的不同组合。比如扇区1时,T1 = -Z,T2 = X;扇区2时,T1 = Z,T2 = Y,以此类推。
为什么要单独算这三个公共量?因为这样可以把所有扇区的作用时间计算统一成查表加赋值,避免在每个扇区里重复做三角函数运算。在定点DSP上,这个优化能省下大量周期。我在DSP28379上实测过,用公共量方式计算作用时间,比每个扇区单独算三角函数,中断执行时间从约2.1微秒降到了0.8微秒。
2.3 过调制与最小脉宽限制的处理
实际系统里还有一个绕不开的问题:当目标电压矢量幅值接近六边形内切圆半径时,T1 + T2会接近甚至超过Ts。这时候必须做过调制处理,否则波形会严重失真。常见的做法是等比例缩放:
if (T1 + T2 > Ts) { float scale = Ts / (T1 + T2); T1 *= scale; T2 *= scale; }但这里有个坑:缩放之后,零矢量的作用时间可能变成负数。如果T1 + T2刚好等于Ts,那零矢量时间为零,这没问题。但如果因为浮点误差导致T1 + T2略大于Ts,缩放后零矢量时间可能是一个极小的负数,在计算比较寄存器值时会导致PWM输出异常。我的做法是加一个保护:
float T0 = Ts - T1 - T2; if (T0 < 0) T0 = 0;另外,最小脉宽限制也很关键。MOSFET或者IGBT的开关需要一定时间,如果PWM脉冲太窄,可能还没完全开通就关断了,导致开关损耗剧增甚至损坏器件。一般建议最小脉宽不低于1微秒,具体值要看你的驱动芯片和功率器件手册。
3. 5段式与7段式的波形排列差异到底在哪
3.1 7段式的标准排列:对称性是优势也是负担
7段式的名字来源于一个PWM周期内被分成了7段。以扇区1为例,开关序列是:零矢量(000)→ 非零矢量1(100)→ 非零矢量2(110)→ 零矢量(111)→ 非零矢量2(110)→ 非零矢量1(100)→ 零矢量(000)。注意这里零矢量用了两个,一个是000,一个是111。
这种排列的最大特点是对称性。每个PWM周期内,A、B、C三相的开关次数都是2次(一次开通一次关断),而且波形关于周期中心对称。对称性带来的好处是:
- 谐波频谱更干净,低次谐波含量低
- ADC采样时刻可以固定在周期中心,避开开关噪声
- 死区效应在正负半周可以部分抵消
但代价也很明显:每个周期每相开关2次,开关损耗是5段式的两倍。在10kHz开关频率下,7段式每相每秒开关20000次,而5段式只有10000次。对于大功率应用,这个差异直接决定了散热器的尺寸。
3.2 5段式的排列逻辑:省掉一次开关,但引入不对称
5段式就是把7段式里的一个零矢量段去掉。还是扇区1,开关序列变成:零矢量(000)→ 非零矢量1(100)→ 非零矢量2(110)→ 零矢量(111)→ 非零矢量2(110)→ 非零矢量1(100)。注意最后没有回到000,而是停在100。
等等,这个序列只有6段?实际上5段式的定义在不同资料里略有差异。更常见的5段式排列是:零矢量(000)→ 非零矢量1(100)→ 非零矢量2(110)→ 零矢量(111)→ 非零矢量2(110),然后下一个周期从非零矢量1(100)开始。这样每个周期内,A相只开关1次,B相开关2次,C相开关2次。总开关次数从7段式的6次降到了5次,这就是“5段式”名字的由来。
但这里有一个非常关键的细节:5段式的不对称性会导致电流谐波在低频段出现边带。我在实测中发现,5段式的电流频谱在开关频率附近会出现明显的边带谐波,而7段式则干净很多。这个边带谐波的频率和电机基波频率相关,在低速时可能落在人耳可听范围内,导致电机发出刺耳的噪声。
3.3 两种方式的开关损耗实测对比
我在750W PMSM平台上做了开关损耗的对比测试。测试条件:母线电压48V,相电流有效值3.5A,开关频率10kHz,死区1.2微秒。用示波器测量MOSFET的漏源电压和漏极电流,计算每次开关的能耗,然后乘以开关频率得到开关损耗功率。
| 调制方式 | 每相每周期开关次数 | 单次开关能耗(微焦) | 开关损耗功率(W) | 总损耗占比 |
|---|---|---|---|---|
| 7段式 | 2 | 约2.8 | 约1.68 | 约4.2% |
| 5段式 | 1.67(平均) | 约2.8 | 约1.40 | 约3.5% |
看起来差异不大?但注意这是在10kHz下的结果。如果把开关频率提高到20kHz,7段式的开关损耗会翻倍到3.36W,而5段式只有2.8W。对于效率敏感的应用,这个差异就非常可观了。而且开关损耗最终会变成热量,影响MOSFET的结温,进而影响可靠性和寿命。
提示:开关损耗的实测非常讲究方法。用电流探头测漏极电流时,要注意探头带宽和延迟,否则算出来的能耗误差可能超过30%。我建议用高压差分探头测Vds,用罗氏线圈测Id,然后做积分。
4. 谐波性能的全参数对比测试
4.1 测试平台搭建与参数设置
为了做公平对比,我搭了一个统一的测试平台:
- 主控:STM32F103C8T6,72MHz主频,无FPU,用定点运算实现SVPWM
- 功率级:三相全桥,MOSFET型号IRF3205,驱动芯片IR2104
- 电机:750W PMSM,极对数4,额定转速3000rpm
- 母线电压:48V DC,用大电容稳压
- 开关频率:10kHz
- 死区时间:1.2微秒(由IR2104硬件死区决定)
- 电流采样:霍尔电流传感器,采样率100kHz
- 负载:磁粉制动器,可调负载转矩
测试时,我先用7段式跑一遍,记录三相电流波形,然后用同样的硬件和负载条件跑5段式,记录波形。为了排除温度影响,每次测试前都让系统预热10分钟,确保MOSFET结温稳定。
4.2 电流THD与频谱对比
用功率分析仪测量相电流的THD,结果如下:
| 工况 | 7段式THD | 5段式THD | 差异 |
|---|---|---|---|
| 低速轻载(500rpm,0.5Nm) | 4.2% | 3.4% | 5段式低0.8% |
| 中速中载(1500rpm,1.5Nm) | 3.8% | 4.1% | 7段式低0.3% |
| 高速重载(2800rpm,2.5Nm) | 5.1% | 5.6% | 7段式低0.5% |
这个结果很有意思。低速轻载时,5段式的THD反而更低。我分析原因是:低速时反电动势小,目标电压矢量幅值低,零矢量作用时间长。7段式用了两个零矢量,导致零矢量分配和死区补偿的误差被放大,反而引入了额外的低次谐波。而5段式零矢量段少,死区的影响相对集中,THD反而更好。
但到了中高速,7段式的对称性优势就体现出来了,THD明显低于5段式。尤其是高速重载时,5段式的边带谐波非常明显,频谱上能看到开关频率两侧有明显的边带。
4.3 零序注入对两种方式的影响
零序注入是SVPWM里一个很重要的技巧,本质上是在三相调制波里叠加一个共模分量,使得调制波的峰值降低,从而扩大线性调制区。常见的零序注入方式有:
- SVPWM等效零序:注入-(max+min)/2,这是最经典的SVPWM实现方式
- 三次谐波注入:注入1/6幅值的三次谐波
- DPWM零序:在特定区间钳位到母线正极或负极
我在测试中发现,零序注入方式对5段式和7段式的影响完全不同。对于7段式,零序注入主要影响线性调制区的范围,对THD的影响不大。但对于5段式,零序注入会显著改变各相的开关次数分布。如果零序注入不当,可能导致某一相的开关次数远高于其他两相,造成三相开关损耗不均衡,进而导致MOSFET温度不均。
我的建议是:如果你用5段式,零序注入最好用SVPWM等效方式,并且要检查三相开关次数的均衡性。可以在代码里加一个计数器,统计每个PWM周期内各相的开关次数,跑一段时间后看是否均衡。
5. 死区效应与采样窗口的隐藏陷阱
5.1 死区对5段式的伤害更大
死区是为了防止上下桥臂直通而设置的,但死区会导致输出电压偏离理想值,产生死区效应。死区效应的本质是:在死区时间内,输出电压由电流方向决定,而不是由PWM信号决定。如果电流为正,死区期间下桥臂续流二极管导通,输出电压被钳位到负极;如果电流为负,则钳位到正极。
对于7段式,由于波形对称,死区效应在正负半周可以部分抵消。但对于5段式,波形本身不对称,死区效应无法抵消,会导致电流过零点附近的波形畸变更加严重。我在实测中观察到,5段式在电流过零点附近的电压误差比7段式大了约40%。
解决死区效应的常见方法有:
- 死区补偿:根据电流方向,在PWM比较值上叠加一个补偿量。补偿量的大小等于死区时间对应的电压误差。
- 电流预测:用电流观测器预测电流方向,提前做补偿。
- 硬件死区:用驱动芯片自带的死区,但死区时间固定,无法动态调整。
我的经验是:如果你用5段式,死区补偿必须做,而且补偿精度要求更高。补偿量可以用下式计算:
// 死区补偿量计算 float Tdead = 1.2e-6f; // 死区时间,单位秒 float Tcomp = Tdead * sign(Iphase); // 补偿量,正比于电流方向 // 将补偿量叠加到比较值上但注意,电流过零点附近,电流方向判断容易出错,可能导致补偿方向错误,反而引入振荡。我的做法是在过零点附近设置一个死区,不补偿,或者用滞环比较器来判断电流方向。
5.2 ADC采样窗口的约束
在电机控制里,ADC采样时刻非常关键。通常我们希望在PWM周期的中心采样相电流,因为这时候开关噪声最小。对于7段式,周期中心正好是零矢量(111)作用的时间段,三相下桥臂全部导通,电流采样最干净。
但对于5段式,周期中心可能不是零矢量,而是某个非零矢量。这时候采样相电流,会受到开关噪声的干扰。我在STM32F103上实测过,5段式在周期中心采样时,电流采样噪声比7段式大了约2倍。
解决方案有两个:
- 调整采样时刻:把ADC触发时刻移到零矢量作用的时间段。但这需要动态调整,因为零矢量的位置随扇区变化。
- 用双电阻采样:在母线上放两个采样电阻,通过不同的开关组合重构三相电流。这种方式对采样时刻的要求低一些,但需要更复杂的重构算法。
我个人的选择是:如果必须用5段式,优先用双电阻采样。虽然算法复杂一点,但采样质量稳定得多。
6. 代码实现复杂度与MCU资源占用
6.1 7段式的代码实现更直观
从代码实现的角度,7段式的逻辑更简单。因为波形对称,你只需要计算一次T1、T2、T0,然后按照固定的顺序赋值给三个比较寄存器。以扇区1为例:
// 7段式,扇区1 // 开关序列:000 -> 100 -> 110 -> 111 -> 110 -> 100 -> 000 // 比较寄存器赋值(假设高电平有效) CCR1 = T0/4; // A相 CCR2 = T0/4 + T1/2; // B相 CCR3 = T0/4 + T1/2 + T2/2; // C相 // 然后根据对称性,后半周期自动生成而5段式的代码需要处理不对称性,每个扇区的赋值逻辑都不一样,代码量会大不少。而且5段式通常需要维护一个“上一周期的结束状态”,以便下一个周期从正确的矢量开始。这增加了代码的复杂度和出错概率。
6.2 在STM32F103上的资源占用实测
我在STM32F103C8T6上分别实现了5段式和7段式,用定时器中断的方式生成PWM。中断频率10kHz,中断服务程序里完成扇区判断、作用时间计算、比较寄存器赋值。
| 指标 | 7段式 | 5段式 |
|---|---|---|
| 中断执行时间 | 约3.2微秒 | 约4.1微秒 |
| Flash占用 | 约2.1KB | 约2.8KB |
| RAM占用 | 约120字节 | 约160字节 |
| 最大开关频率(72MHz) | 约25kHz | 约20kHz |
5段式的中断执行时间更长,主要是因为不对称性导致每个扇区的赋值逻辑不同,需要更多的条件判断。在STM32F103这种没有FPU的MCU上,浮点运算都是软件模拟的,每多一次浮点乘法就多几十个周期。所以如果你用F103做5段式,开关频率最好不要超过15kHz,否则中断会占用太多CPU时间。
如果你用DSP28379,那情况完全不同。DSP有硬件浮点单元和专用的PWM模块,5段式和7段式的执行时间差异可以忽略不计。DSP28379的ePWM模块还支持死区自动插入和比较寄存器影子加载,做SVPWM非常方便。
7. 我的选型建议与实操心得
7.1 什么场景选7段式
根据我的实测经验,以下场景优先选7段式:
- 低速轻载噪声敏感应用:比如医疗设备、精密仪器,7段式的谐波频谱更干净,噪声更低。
- 高速重载应用:7段式的对称性优势在高速时更明显,THD更低。
- ADC采样窗口紧张的应用:7段式周期中心是零矢量,采样最干净。
- MCU资源紧张的应用:7段式代码更简单,中断执行时间更短。
7.2 什么场景选5段式
以下场景可以考虑5段式:
- 开关损耗敏感的大功率应用:5段式开关次数少,损耗低,散热压力小。
- 低速轻载且对THD要求不高的应用:5段式在低速轻载时THD反而更低。
- 开关频率很高的应用:比如20kHz以上,5段式的开关损耗优势更明显。
但要注意,5段式必须做好死区补偿和采样时刻调整,否则性能可能反而不如7段式。
7.3 几个容易踩的坑
坑一:以为5段式一定省电。开关损耗确实低了,但如果死区补偿没做好,电流谐波增大,铜损和铁损可能反而增加。我实测过一台电机,用5段式后开关损耗降了0.3W,但铜损增加了0.5W,总损耗反而高了。
坑二:忽略最小脉宽限制。5段式在低速时,某些矢量的作用时间可能非常短,如果低于最小脉宽,PWM脉冲会被硬件过滤掉,导致波形严重失真。我的做法是在代码里加一个最小脉宽检查,如果T1或T2小于最小脉宽,就强制钳位到最小脉宽,并相应调整零矢量时间。
坑三:死区补偿方向搞反。死区补偿的方向取决于电流方向,如果电流方向判断错误,补偿会变成“反补偿”,误差更大。建议在过零点附近用滞环比较器,并且加一个滤波,避免电流噪声导致方向频繁跳变。
坑四:忘记考虑温度对死区的影响。驱动芯片的死区时间会随温度变化,MOSFET的开关时间也会变。在高温环境下,实际死区可能比常温下大20%以上。如果你的补偿量是固定的,高温下补偿就不准了。我的做法是在散热器上贴一个NTC,根据温度查表调整死区补偿量。
7.4 一个实用的调试技巧
如果你不确定该选5段式还是7段式,我建议你先用7段式跑通,然后用示波器看相电流波形和开关波形。如果开关损耗是主要矛盾,再切到5段式,重点观察电流过零点附近的波形和THD变化。切换的时候,记得同时调整死区补偿参数和ADC采样时刻,不要只改调制方式。
另外,我强烈建议在代码里加一个“调制方式切换”的宏定义,方便在两种方式之间快速切换对比。比如:
#define MODULATION_MODE 7 // 7段式 // #define MODULATION_MODE 5 // 5段式 #if MODULATION_MODE == 7 // 7段式代码 #elif MODULATION_MODE == 5 // 5段式代码 #endif这样你可以在同一套硬件上快速做A/B测试,找到最适合你应用的调制方式。
最后分享一个我在DSP28379上做SVPWM的小经验:DSP的ePWM模块支持“影子寄存器”,可以在周期开始时一次性更新所有比较值,避免在周期中间更新导致的波形毛刺。如果你用DSP做5段式,一定要用影子寄存器,否则不对称的波形更新很容易产生额外的谐波。STM32的定时器也有类似的预装载功能,记得开启。