news 2026/11/4 5:18:43

SVPWM扇区判断与七段式、五段式实现取舍

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SVPWM扇区判断与七段式、五段式实现取舍

调三相永磁同步电机或者异步电机,只要涉及矢量控制,SVPWM 就是那道绕不过去的坎。很多人第一次上手的时候会觉得 FOC 的电流环、Park 变换才是"核心技术",SVPWM 无非就是把 Uα、Uβ 变成三路占空比,调通了就行。真在台架上跑起来才发现,电机啸叫、低速转矩脉动、电流采样毛刺、轻载时效率上不去,追到最后往往都落在 SVPWM 这一层——扇区判错了半个边、七段式排布不对称、五段式用错场合、最小脉宽没设,问题一个接一个。

这篇就把SVPWM 的扇区判断法和七段式与五段式的实现取舍这两个点掰开讲清楚。核心关键词是 SVPWM、扇区判断、七段式、五段式、作用时间计算、死区与最小脉宽。内容会从六个基本矢量的物理含义一路讲到可直接抄的 C 代码,中间穿插母线电压利用率、开关损耗、电流重构窗口这些实际工程指标的影响分析。适合刚接触电机控制、能看懂基本 C 语言但还没把 SVPWM 写成产品级代码的读者;也适合已经在用但被波形细节困扰、想知道"为什么别人家的波形这么干净"的同行翻一翻。

1. 先搞清楚 SVPWM 到底在算一件什么事

在往代码里填公式之前,得先建立物理图像。SVPWM 不是数学游戏,它的本质是:用 8 个离散的开关状态,在一个 PWM 周期里去"平均"出一个任意方向、任意幅值的电压矢量。理解了这句话,后面所有的扇区判断、时间分配、七段五段之争,都是这句话的推论。

1.1 六个有效矢量与两个零矢量的由来

三相两电平逆变器,每相上桥臂只有开和关两种状态,三相结合一共 8 种组合,也就是 8 个基本电压矢量。把上桥臂导通记作 1、下桥臂导通记作 0,按 A、B、C 的顺序排列,000 和 111 是两个零矢量,输出的线电压全为零;其余 6 个是有效矢量,幅值都等于 2/3 倍的直流母线电压(这是基于三相星形等效、以相电压幅值定义的等幅值变换),方向依次相差 60 度。

这里有一个非常容易踩的坑:矢量编号和空间角度的对应关系,不同的教材、不同的库是不一样的。有的资料把 100 叫 V1 并摆在 0 度位置,有的则把 100 摆在别的位置,还有的用的是"线电压空间矢量"定义,幅值、角度全都差一截。我曾经见过一个项目,代码是从两份不同的开源资料里拼出来的,一份的编号体系是 V1 到 V6 顺时针排布,另一份是逆时针排布,单独看都自洽,拼在一起电机转起来像得了帕金森。所以第一件事:选定一套定义,然后在整个工程里贯彻到底,包括扇区编号、作用时间的公式、占空比赋值给哪一相。

本文统一采用最常见的定义:100 对应 0 度(V1)、110 对应 60 度(V2)、010 对应 120 度(V3)、011 对应 180 度(V4)、001 对应 240 度(V5)、101 对应 300 度(V6)。扇区 I 到 VI 分别是 0 到 60 度、60 到 120 度,依此类推。机械地记住这张表没意义,画一张六边形,把 6 个顶点标上 100、110 这些编码,看一眼就忘不掉。

8 个状态里,为什么只有 6 个能干活?因为零矢量合成的电压为 0,它不提供方向,只提供"时间填充"。在伏秒平衡的框架下,零矢量的作用是消耗掉剩余的时间,让总时间严格等于 PWM 周期。这也解释了后面七段式和五段式的根本差异——它们对零矢量的使用方式不同。

1.2 伏秒平衡:占空比公式的唯一来源

伏秒平衡说人话就是:一个 PWM 周期内,合成矢量的积分效果,必须等于参考矢量在该周期内的积分。写成式子:

Uref × Ts = U1 × T1 + U2 × T2 + U0 × T0

其中 Uref 是期望输出的参考电压矢量,Ts 是 PWM 周期,T1、T2 是两个相邻有效矢量的作用时间,T0 是零矢量时间,且 T1 + T2 + T0 = Ts。因为零矢量对积分的贡献为零,所以 T0 只是凑数用的。

把参考矢量投影到两个相邻有效矢量构成的 60 度扇区里,用正弦定理一通推导,就能得到那个著名的形式:

T1 = √3 × Ts × |Uref| × sin(π/3 - θ) / Vdc T2 = √3 × Ts × |Uref| × sin(θ) / Vdc T0 = Ts - T1 - T2

θ 是参考矢量在本扇区内相对起始边的角度,范围 0 到 π/3。看一眼这个式子就能读出几个关键信息。第一,T1、T2 与 |Uref| 成正比,与母线电压 Vdc 成反比,母线电压波动会直接改变占空比,所以电压环必须采样母线电压做前馈补偿,否则电池从满电掉到欠压的过程中,输出转矩会飘得厉害。第二,当 |Uref| 达到线性区上限 Vdc/√3 时,sin 项最大取到 1,T1 + T2 = Ts,零矢量时间被压到零,此时就是六阶梯波的门槛。第三,超过这个幅值就进入过调制,公式算出来的 T1 + T2 大于 Ts,必须做饱和处理。

很多人抄代码时把 √3 和 1/2 这些系数抄错了,或者把 Vdc 写成 Vdc/2,结果表现为"电机能转,但同样的 Ud/Uq 指令出力明显偏小"。这种情况不要急着怀疑电流环,先把 T1、T2 打出来,对照推导手算一组数据核对。

1.3 为什么扇区判断是整个算法的地基

扇区判断错了,或者判断出现抖动,后果不是"输出略有偏差",而是灾难性的。因为不同扇区对应的作用时间公式、矢量组合、占空比赋值顺序全都不一样。扇区从 I 跳到 II 的瞬间,如果公式没跟着切,等于把一个本该在 60 到 120 度合成的矢量,用 0 到 60 度的公式算了一遍,输出矢量会瞬间跳到镜像位置——反映到电机上就是一顿一顿的抖动、电流出现尖峰、严重时直接过流保护。

所以扇区判断有两个硬性要求:绝对准确和绝对连续。准确性靠公式和标定保证,连续性则依赖于边界处理。在扇区边界上,Uβ 恰好等于 √3|Uα| 这类临界条件,浮点噪声会让判断结果在相邻两个扇区之间反复横跳。因为两侧公式在边界上算出来的结果是连续的(理论上极限相等),所以偶尔跳一次不会造成大的输出偏差,但如果每个 PWM 周期都跳,等效于在一个频率很高的扰动,频谱上会看到明显的杂散。

实操心得:不要试图通过加 0.001 的偏置来"解决"边界抖动,那只是把抖动点挪到了别处。正确做法是让扇区判断公式本身连续,或者用后文提到的统一 N 值查表法,把六种情况化成代数式,从根上消除跳变。

2. 扇区判断的三种写法与实际工程选型

扇区判断在教科书上有好几种写法,有的用反正切求角度,有的做符号比较,有的用投影后的三个分量组合出 N 值。这三种方法在数学上等价,但在定点运算、执行时间、边界行为上差别不小,选错了在低速轻载时能明显看出区别。

2.1 角度法:直观、好调试,但别放进中断里

最直观的做法是先算 θ = atan2(Uβ, Uα),再除以 60 度取整得到扇区号。写测试脚本、做离线数据分析的时候这招很好用,几行 Python 就能把整个扇区轨迹画出来。但放进 PWM 中断里就跑不动了,原因有几个。

一是 atan2 的开销。在没有硬件三角函数单元的 MCU 上,一次双精度 atan2 可能几百个时钟周期,放在 10 kHz 或者 20 kHz 的 PWM 中断里,直接把 CPU 吃满。二是精度问题。浮点 atan2 在接近零点的时候精度会下降,而低速运行时 Uα、Uβ 本来就很小,角度误差会被放大。三是 π 和 -π 的接缝。atan2 的值域是 (-π, π],跨越这个边界的时候角度会突跳,如果直接拿来做差值、做滤波,会出现一个 2π 的野值。

如果确实想在固件里用角度法(有些算法需要电角度信息),建议做成查表插值,把 0 到 2π 分成 1024 份,用 Uα、Uβ 的比值去索引,或者干脆用后文的符号法算出扇区,再由扇区反推粗略角度。省下来的周期留给电流环更划算。

2.2 符号判断法:把六边形切成六个"象限"

这是工程里最常用的写法,思路是把六个扇区看成平面上的区域划分,用比较器和符号位来做判定。设参考矢量的分量为 Uα、Uβ,利用边界线 Uβ = ±√3·Uα 把平面切开,六个扇区的判定逻辑可以写成:

/* 简化示意:先判上下半平面,再判左右 */ if (Ubeta >= 0.0f) { if (Ualpha >= 0.0f) { sector = (Ubeta < sqrt3 * Ualpha) ? 1 : 2; } else { sector = (Ubeta < -sqrt3 * Ualpha) ? 3 : 2; } } else { if (Ualpha >= 0.0f) { sector = (-Ubeta < sqrt3 * Ualpha) ? 6 : 5; } else { sector = (-Ubeta < -sqrt3 * Ualpha) ? 4 : 5; } }

这段代码的逻辑是:Uβ 非负说明在上半平面,如果 Uα 也非负,那么参考矢量在右上半区,此时比较 Uβ 和 √3·Uα——小于则靠 0 度边(扇区 I),大于则靠 60 到 120 度一侧(扇区 II);Uα 为负时镜像处理,判断它靠 180 度边还是 120 度边。下半平面完全对称。

这种写法的优点是只需要比较和乘法,没有除法,没有三角函数,定点完全能跑。缺点是有条件分支,在流水线比较深的核上有分支预测失败的开销,而且六条路径写起来容易漏掉边界条件。我见过一份代码把下半平面的扇区 4 和 5 的比较方向写反了,现象是电机正转正常、反转时电流突然大了 40%,查了大半天才发现是这一行。

注意:使用这种写法时,√3 的精度直接影响扇区边界的位置。若用1.732f这种四位近似,在 Uβ 恰好等于 √3·Uα 附近的判定会和理论值有微小偏差。这和 αβ 的标幺化方式有关,如果 αβ 是标幺值(以 Vdc/√3 为基值),那么 √3 因子可以被吸收进基值定义,边界退化成 0.5774 之类的常数,反而更干净。

2.3 统一 N 值法:无分支、无除法,我最推荐的写法

这套写法在业界的电机控制资料里流传很广,核心思想是:构造三个中间量,分别看它们的符号,再把三个符号位拼成一个 0 到 7 的数字 N,最后用一张映射表把 N 翻译成扇区号。前三个中间量是:

Vref1 = Ubeta Vref2 = (√3 × Ualpha - Ubeta) / 2 Vref3 = (-√3 × Ualpha - Ubeta) / 2

这三个式子的几何含义是:把参考矢量分别投影到三条与扇区边界垂直的方向上,投影为正说明矢量落在该边界的某一侧。三个符号位组合起来,就能唯一确定六个扇区中的一个。

/* 扇区判断:N 值法,无分支 */ float vref1 = ubeta; float vref2 = (SQRT3 * ualpha - ubeta) * 0.5f; float vref3 = (-SQRT3 * ualpha - ubeta) * 0.5f; uint8_t N = 0; if (vref1 > 0.0f) N += 1; if (vref2 > 0.0f) N += 2; if (vref3 > 0.0f) N += 4; /* N 到扇区的映射 */ static const uint8_t sector_map[8] = {0, 2, 6, 1, 4, 3, 5, 0}; uint8_t sector = sector_map[N];

映射表这里展开写一下,方便对照检查:

N315462
扇区IIIIIIIVVVI

N 取 0 和 7 的情况在实际运行中不该出现(三个投影同时为负或同时为正,对应矢量幅值为零的退化情形),映射表里填 0 占位即可,也可以在调试阶段加一个断言来抓。我自己的习惯是在开发板上把 N 值通过 DAC 或者串口打出来,与理论波形对一遍再上线,这个步骤花十分钟,能省掉后面两天的怀疑。

N 值法的最大好处是逻辑连续。因为三个投影是 Uα、Uβ 的连续函数,投影过零时符号翻转,扇区自然切换,不存在一个扇区"跳过"另一个扇区的情况,也不会有 atan2 那种 ±π 接缝。代价是三次乘法和三次比较,在现代 MCU 上几乎可以忽略。还有一个隐藏优势:这套结构天然适配定点化,把 Uα、Uβ 表示成 Q15,√3/2 表示成 Q15 常数,三次乘法可以用移位加饱和实现,整个扇区判断能压到几十个周期。

2.4 过零点附近的抖动与迟滞处理

即便用了 N 值法,在参考矢量幅值极小(比如电机零速、输出电压接近零)的时候,Uα、Uβ 本身就是噪声级别的数,扇区会随噪声乱跳。虽然此时占空比都接近 50%,乱跳的影响有限,但如果后端接了电流采样时序、或者做了最小脉宽限制,反而可能出现异常脉冲。

处理办法是在输出端做钳位:当 |Uref| 小于某个阈值(例如线性区上限的 1%),直接把三个占空比都设成 50%,不做扇区判断。这个阈值怎么定?我的经验是按电流环输出的实际噪声水平来,一般取额定输出的 0.5% 到 1%。太大会影响低速性能,太小起不到作用。还有一种做法是对 Uα、Uβ 做一阶低通,但会引入相位滞后,电流环带宽高的时候要慎用。

3. 七段式实现:对称、干净、开关次数最多

七段式是 SVPWM 的"标准姿势",绝大多数教材和文献讲的都是它。它的核心特征是:在一个 PWM 周期内,开关状态按对称顺序切换,零矢量被拆成 V0 和 V7 两部分,分别放在周期的两端和中间,使得每相桥臂在每个周期内只动作一次。

3.1 时序排布:为什么必须是这个顺序

以扇区 I(0 到 60 度,用 V1=100 和 V2=110)为例,七段式的开关序列是:

V0(000) → V1(100) → V2(110) → V7(111) → V2(110) → V1(100) → V0(000)

这个顺序不是随便排的,它遵循一条铁律:相邻两个状态之间只能有一相桥臂状态改变。000 到 100 只有 A 相从 0 变 1;100 到 110 只有 B 相变;110 到 111 只有 C 相变。这样每一次状态切换的开关损耗只落在一相上,而且整个周期内三相的开关次数总计是 6 次(每相各 2 次边沿,即开一次关一次)。

为什么把 V7 放在正中间?因为中心对称的排布让三相的开关动作在时间上均匀分布,线电压和相电流的谐波频谱更干净,奇次谐波集中,偶次谐波被对称性抵消,总谐波畸变率(THD)比不对称排布低一截。这也是"七段式"这个名字的由来——一共有 7 个时间段落。

时间分配上,设两个有效矢量总时间 T1、T2,零矢量被平均分给 V0 和 V7:

T0_total = Ts - T1 - T2 V0 两端各占 T0_total / 4 V7 中间占 T0_total / 2

七段各自的时长依次是:T0/4、T1/2、T2/2、T0/2、T2/2、T1/2、T0/4,加起来正好是 Ts。这个"两头各四分之一、中间一半"的分配是等分零矢量的结果,也可以按其他比例分(比如为了让 V7 时间更长以利于高边自举充电,或者反之以利于下桥臂电流采样),但比例一变,对称性就被破坏,要重新评估谐波和采样窗口。

提示:有些实现把零矢量全部给 V7 或全部给 V0,那已经不是七段式了,而是下文要讲的五段式。判断依据很简单——数一段周期内出现了几个不同的开关状态。

3.2 作用时间的分扇区计算与过调制处理

前面给的是通用形式(用 θ 表示),实际代码里不会去算 θ,而是用 X、Y、Z 三个中间变量把六个扇区的公式统一起来:

X = √3 × Ts × Ubeta / Vdc Y = Ts × (√3/2 × Ubeta + 3/2 × Ualpha) / Vdc Z = Ts × (√3/2 × Ubeta - 3/2 × Ualpha) / Vdc

六个扇区的作用时间分别是:

扇区T1T2
I-ZX
IIZY
IIIX-Y
IV-XZ
V-Y-Z
VIY-X

这套对应关系我建议手推一遍验证,方法是取 θ=30 度(扇区 I 中心)代入,看能不能还原出 T1=T2=0.866·Ts·|Uref|/Vdc 这个解析值。推一遍之后就不用死记了,因为你知道每个式子为什么这么写。

过调制的判断很简单:如果 T1 + T2 > Ts,说明参考矢量超出了六边形内切圆,此时按比例压缩:

if (T1 + T2 > Ts) { float k = Ts / (T1 + T2); T1 *= k; T2 *= k; }

这是最朴素的等比例缩放,也叫最小幅值误差法,实现简单,但输出矢量的相位会偏移,在深过调制时会引起转矩脉动。更好的做法是保持相位、只削幅值,或者使用最小相位误差法——把参考矢量投影到六边形的边上,保证方向不变。六阶梯波模式则是另一套逻辑,直接把矢量吸附到六个顶点上。具体选哪种,取决于你的应用是否需要进入过调制区;风机水泵这类场合通常在调制比 0.9 以下运行,等比例缩放够用了,电动汽车牵引这种需要深度弱磁的场合就得认真做。

3.3 从作用时间到比较寄存器:小心那一步换算

算完 T1、T2、T0,接下来要把它们变成三个比较寄存器的值。这一步是新手最容易翻车的地方,因为它牵扯到计数器的计数方式(增减计数还是单向计数)、有效电平定义(高有效还是低有效)、装载时刻(周期中断还是零中断)。稍有偏差,波形看起来"差不多",但实际相位反了。

以最常见的增减计数为例:计数器从 0 增到 PRD(对应 Ts/2 的时间),再减回 0,一个来回构成完整的 Ts 周期。假设上桥臂在计数值大于比较值时导通(低有效配置下相反,这里按高有效说明),那么每相在一个周期内的导通时间 = 2 × (PRD - CMP) × Tclk,其中 Tclk 是计数时钟周期。

以扇区 I 为例推一遍:A 相在 V1 和 V2 段都导通,中间 V7 也导通,所以 A 相一个周期内的导通时间 = T1 + T2 + T0_total/2。令它等于 2 × (PRD - CMPA) × Tclk,且 PRD × Tclk = Ts/2,解出 CMPA = (Ts - T1 - T2) / 4。同理可得 B 相 CMPB = CMPA + T1/2,C 相 CMPC = CMPB + T2/2。

这个结果非常漂亮:三个比较值恰好构成等差递增序列,扇区 I 里 CMPA < CMPB < CMPC,对应 A 相占空比最大、C 相最小,符合直觉(V1 是 A 相单独导通)。其他五个扇区只是把这三个值分配给不同的相,分配规则如下表:

扇区比较值小中大
IABC
IIBAC
IIICAB
IVCBA
VBCA
VIACB

实操心得:这张表别硬背,画一个六边形,在每条边上标出"哪一相占空比最大"就行。扇区 I 在 0 到 60 度,最靠近 A 相轴,所以 A 相占空比最大;扇区 II 在 60 到 120 度,最靠近 B 相轴(120 度),所以 B 相最大。以此类推,画一遍就记住了。我在带新人的时候都是让他们自己画一遍,比讲十遍强。

3.4 一份可用的七段式 C 代码

把上面的推导落成代码,结构大概是这个样子:

typedef struct { float Ts; /* PWM 周期,单位与时间一致 */ float Vdc; /* 母线电压 */ float ualpha; float ubeta; float duty_a; /* 输出:三相占空比,0~1 */ float duty_b; float duty_c; } svpwm_t; void svpwm_seven_segment(svpwm_t *s) { const float SQRT3 = 1.7320508f; float T1, T2, T0, Ta, Tb, Tc; uint8_t N = 0, sector; /* 1. 扇区判断 */ float v1 = s->ubeta; float v2 = (SQRT3 * s->ualpha - s->ubeta) * 0.5f; float v3 = (-SQRT3 * s->ualpha - s->ubeta) * 0.5f; if (v1 > 0.0f) N += 1; if (v2 > 0.0f) N += 2; if (v3 > 0.0f) N += 4; static const uint8_t map[8] = {0, 2, 6, 1, 4, 3, 5, 0}; sector = map[N]; if (sector == 0) { /* 零矢量区,直接输出 50% */ s->duty_a = s->duty_b = s->duty_c = 0.5f; return; } /* 2. 作用时间 */ float X = SQRT3 * s->Ts * s->ubeta / s->Vdc; float Y = s->Ts * (SQRT3 * 0.5f * s->ubeta + 1.5f * s->ualpha) / s->Vdc; float Z = s->Ts * (SQRT3 * 0.5f * s->ubeta - 1.5f * s->ualpha) / s->Vdc; switch (sector) { case 1: T1 = -Z; T2 = X; break; case 2: T1 = Z; T2 = Y; break; case 3: T1 = X; T2 = -Y; break; case 4: T1 = -X; T2 = Z; break; case 5: T1 = -Y; T2 = -Z; break; default:T1 = Y; T2 = -X; break; } /* 3. 过调制限幅 */ if (T1 < 0.0f) T1 = 0.0f; if (T2 < 0.0f) T2 = 0.0f; if (T1 + T2 > s->Ts) { float k = s->Ts / (T1 + T2); T1 *= k; T2 *= k; } /* 4. 比较值(以占空比形式输出,0~1) */ T0 = s->Ts - T1 - T2; Ta = T0 * 0.25f / s->Ts; Tb = Ta + T1 * 0.5f / s->Ts; Tc = Tb + T2 * 0.5f / s->Ts; /* 5. 按扇区映射到三相 */ switch (sector) { case 1: s->duty_a = Ta; s->duty_b = Tb; s->duty_c = Tc; break; case 2: s->duty_b = Ta; s->duty_a = Tb; s->duty_c = Tc; break; case 3: s->duty_c = Ta; s->duty_a = Tb; s->duty_b = Tc; break; case 4: s->duty_c = Ta; s->duty_b = Tb; s->duty_a = Tc; break; case 5: s->duty_b = Ta; s->duty_c = Tb; s->duty_a = Tc; break; default:s->duty_a = Ta; s->duty_c = Tb; s->duty_b = Tc; break; } }

这段代码把时间全部归一化到 Ts 的倍数,输出的是 0 到 1 的占空比,方便直接乘以周期寄存器值。注意第 4 步里 Ta 用的是 T0/4,含义是"半个周期内 V0 的时长相对于 Ts 的比例",和第 3 节的推导一致。如果你的 PWM 模块计数方式不同(比如单向计数、或者周期寄存器对应整个 Ts),这一步的系数要相应调整,别直接抄。

4. 五段式实现:少两次开关,多两分谐波

七段式很完美,但它有一个致命缺点:每相桥臂每个周期都要开关一次。在 10 kHz 载波、6 个开关管的系统里,每个管子每秒开关一万次,开关损耗占了总损耗的相当一块。如果能把某一相在半个周期内钳住不动,就能省下这部分损耗。五段式就是这么来的。

4.1 五段式怎么省掉两次开关

五段式的核心改动是:只用一个零矢量。以扇区 I 为例,序列变成:

V0(000) → V1(100) → V2(110) → V1(100) → V0(000)

只有 5 段,零矢量全部是 V0,不使用 V7。C 相在整个周期内始终为 0,桥臂不动作。三相的开关次数从 6 次降到 4 次,开关损耗理论上降低三分之一。

另一种五段式是把零矢量全给 V7,序列变成 111 → 110 → 100 → 110 → 111,此时 A 相始终为 1,不动作。这两种模式的选择不是随便挑的:V0 全给的模式叫"下桥臂钳位",适合高边自举供电需要用低边充电的场合;V7 全给的模式叫"上桥臂钳位"。

作用时间的计算和七段式完全一样,T1、T2、T0 的公式不变,变化只在于 T0 的分配:

V0 总时间 = T0,放在首尾各 T0/2 V7 时间 = 0

所以五段式的比较值只有两个不同的值(因为有一相全程不动作),三相占空比里必有一相是 0 或 1。

注意:五段式实现时,如果钳位的相恰好是电流采样所在的相,采样窗口会被彻底破坏。这一点在做双电阻采样时特别致命——下桥臂必须导通足够长时间才能采到电流,如果那一相整周期被钳在 0(下桥臂导通),那没问题;但如果被钳在 1(下桥臂关断),就完全采不到。所以五段式的钳位相选择必须和采样拓扑一起考虑。

4.2 代价:电流纹波、谐波和转矩脉动

省了开关,代价自然要付。五段式相对七段式的第一个代价是电流纹波变大。七段式因为零矢量均分,电感电流在每个周期内"充电-放电"的节奏更均匀,纹波峰峰值更小。五段式把零矢量集中在一端,电流的上升和下降不对称,纹波峰峰值会明显增大,具体增幅和调制比有关,在低调制比时尤其明显。

第二个代价是谐波频谱变差。七段式的对称性让偶次谐波被抵消,五段式破坏了这种对称,低次谐波会冒出来。反映到实际表现上,就是电机的电磁噪声频谱里多出一些低频成分,听感上比七段式"闷"一点。对于噪声敏感的场合(车载、家电),这个差别是能听出来的。

第三个代价是低速性能。低调制比时有效矢量时间很短,五段式的零矢量时间很长,占空比集中在极端值附近,死区的影响被放大,低速轻载时的转矩脉动会比七段式更明显。

4.3 什么时候该用五段式:一张选型对照表

五段式不是"七段式的简化版",它是一个有明确适用场景的独立方案。下面这张表是我自己做方案时的判断依据:

维度七段式五段式
开关损耗基准约降低 1/3
电流纹波小明显偏大
谐波性能好,偶次谐波抵消较差,低次谐波增加
低速性能好一般
单电阻采样有 V0、V7 两个窗口,友好只有一个窗口,需谨慎
双电阻采样依赖占空比,需留最小窗口钳位相选择影响大
适用场景伺服、精密驱动、低噪声风机水泵、大功率、高载波

我在一个风机项目里做过对比:同一台 2.2 kW 电机,同一载波频率 8 kHz,五段式比七段式的开关管温升低了大约 6 到 8 摄氏度,整机效率提升不到 0.5 个百分点。但噪声从"基本听不见"变成了"能听到轻微的嗡声"。风机装在室外机柜里,噪声无所谓,所以最后选了五段式;如果换成室内机,这个交换可能就不划算了。

5. 从公式到波形:实操落地的几个关键环节

把代码写对只是第一步,真正让波形干净、让系统稳定,还有几个环节必须处理。这部分是文档里通常不会细说、但现场一定会遇到的东西。

5.1 标幺化与定点运算的选择

浮点实现最好写,但在成本敏感的 MCU 上,一次 float 除法能吃掉上百个周期。常见的做法是把 Uα、Uβ 标幺化到 [-1, 1],以 Vdc/√3 为基值,这样线性区的边界就是 ±1,作用时间的公式里的 Vdc 也被吸收掉了:

T1/Ts = -Z', T2/Ts = X' X' = √3 × Ubeta_pu / 2?

严格推导一遍:设 Uα_pu = Uα × √3 / Vdc,Uβ_pu = Uβ × √3 / Vdc,代入原来的 X、Y、Z 公式,Vdc 消掉,√3 也被吸收,得到:

X = Ts × Ubeta_pu Y = Ts × (0.5 × Ubeta_pu + √3/2 × Ualpha_pu) Z = Ts × (0.5 × Ubeta_pu - √3/2 × Ualpha_pu)

形式干净很多,只剩 ±0.5 和 ±√3/2 这两个常数。定点实现时,用 Q15 表示 Uα_pu、Uβ_pu,√3/2 用 Q15 常数 28378(0.866×32768),乘法后右移 15 位,再乘 Ts(也用 Q15 表示),最后右移。整个过程没有除法,全程几百个周期就能跑完,放在 20 kHz 中断里毫无压力。

提示:标幺化的基值必须和电流环输出保持一致。如果电流环输出的是以 Vdc/√3 为基值的标幺电压,那这边直接用;如果输出的是实际电压值(伏特),记得先乘 √3/Vdc 做一次转换,且 Vdc 要用当前实测值,别用额定值。

5.2 死区与最小脉宽:波形畸变的两个主要来源

死区是绕不开的。上下桥臂不能同时导通,必须插入几百纳秒到几微秒的死区时间。死区带来的效果是:在电流方向为正时,实际输出电压比指令值少了 Vdc × Tdead/Ts;电流为负时则多了同样的量。这会导致输出电压在过零点附近出现"平台",反映到电流上就是过零畸变。

补偿方法有很多种,最简单的是按电流方向符号加一个固定的补偿量:

float comp = (Tdead / Ts) * sign(ia); duty_a += comp;

符号的判定必须可靠,在电流过零附近符号会抖动,补偿量跟着抖,反而引入新的畸变。工程上一般设一个电流阈值,|ia| 小于阈值时把补偿量线性衰减到零,形成一个过渡带。阈值取多少?经验值是额定电流的 2% 到 5%,具体看电流传感器的噪声水平。

最小脉宽问题是另一个坑。当 T1 或者 T2 很小(比如小于 1 微秒)时,PWM 模块可能根本发不出这么窄的脉冲,或者发出来的脉冲被死区吃掉,导致输出矢量与指令严重不符。标准的处理是设一个最小脉宽 Tmin,当 T1 < Tmin 时把它钳到 Tmin,同时从 T2 里扣掉相应的时间(保持总时间不变)。如果两个都小于 Tmin,就舍弃小的那个,只发大的。这个逻辑一定要加,否则在低速小电压输出时会出现莫名其妙的电流尖峰。

5.3 上电调试的正确顺序

写完代码不要急着接电机。我的习惯顺序是:

第一步,开环给定 Uα、Uβ,让矢量在圆上慢慢转一圈,用示波器看三相占空比。正常的七段式波形,每相应是中心对称的马鞍形,相位互差 120 度,包络平滑无跳变。如果看到某一相在扇区切换点有突跳,说明扇区映射表错了。

第二步,把三相占空比接 RC 低通滤波,看能不能滤出正弦。滤波器的截止频率取载波的 1/20 左右,滤出来的是基波。如果滤出来的波形有台阶、有断续,说明扇区判断或者时间计算有问题。

第三步,接一个星形电阻负载,测量线电压,用示波器做 FFT 看谐波。七段式在调制比 0.8 左右,线电压的 THD 一般在 5% 以内(不含载波附近的开关频率成分)。如果 THD 明显偏大,先查死区设置,再查最小脉宽。

第四步,才接电机,从小电压、低转速开始,先看电流是不是干净的正弦。这时候要特别注意低速段:100 rpm 以下如果电流有明显的六倍频脉动,八成是死区补偿没做好或者扇区边界抖动。

实操心得:用 DAC 或者 PWM 转模拟的方式把 T1、T2、扇区号实时打出来,比用调试器打断点靠谱得多。打断点会破坏实时性,PWM 中断一旦被拉长,输出直接乱掉。我一般留一路空闲的 PWM 通道,RC 滤波后当 DAC 用,把扇区号打出来,用示波器一看就知道扇区切换是否干净。

6. 常见问题与排查速查

下面这些是我和同事们在台架上真实踩过的,按现象归类,方便对照排查。

现象可能原因排查方法处理
电机不转,电流很大扇区映射表错位,输出矢量方向错误打点看扇区号与 Uα/Uβ 的对应核对 N 值映射表
正转正常,反转电流大 30% 以上符号判断法里下半平面分支写反分别在六个扇区注入固定矢量验证修正比较方向
低速时电流有六倍频脉动死区未补偿或补偿符号抖动关闭死区补偿对比波形加阈值过渡带
扇区切换点有电流尖峰扇区判断抖动,两侧公式不连续把扇区号打到示波器上看改用 N 值法或加零矢量门限
轻载时占空比到头、波形削顶过调制未限幅打印 T1+T2 与 Ts 的比值加等比例限幅
输出正弦但幅值偏小√3 系数或 Vdc 基值错误手算一组与代码对比
五段式噪声明显变大零矢量集中导致低次谐波做 FFT 对比七段式提高载波或改回七段式
单电阻采样时电流失真采样窗口不足测最小相占空比限制最小占空比或切七段式
高温下占空比漂移未做母线电压前馈监测 Vdc 变化实时采样 Vdc 参与计算
高调制比时电机抖动进入过调制但相位失真观察调制比超过 0.95 后的波形改用最小相位误差法

再补充几个文档里不太写、但实际很有用的经验。

关于载波频率的选择。载波越高,电流纹波越小,但开关损耗线性上升,同时

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/4 5:18:42

Oracle SGA调参起不来:pfile与spfile应急恢复指南

简介&#xff1a;这份文档面向 Oracle 数据库运维与开发人员&#xff0c;聚焦 SGA 参数调整后实例无法正常启动的应急排查场景&#xff0c;适合需要快速定位内存参数错误、恢复数据库可启动状态并补强故障处理思路的读者参考。压缩包共 1 个 docx 文件&#xff0c;大小约 14KB&…

作者头像 李华
网站建设 2026/11/4 5:18:32

佳能IR1133 USB打印功能开启全指南

1. 项目概述&#xff1a;这不是U盘坏了&#xff0c;是佳能IR1133“锁住了”USB打印通道你把U盘插进佳能IR1133的侧边USB口&#xff0c;机器屏幕亮了、识别出设备名称、甚至能浏览文件夹——但一进“USB打印”菜单&#xff0c;选项灰掉、提示“未启用”或干脆不显示&#xff1b;…

作者头像 李华
网站建设 2026/11/4 5:16:21

AI原生应用避坑指南:从数据管道到模型服务的全链路实践

前阵子我从后端组转岗到AI平台部门&#xff0c;接手的是一个刚跑完小流量验证的AI原生项目。老板没多解释&#xff0c;丢过来一份内部文档&#xff1a;《AI 原生实践避坑指南》&#xff0c;说“先把这份指南看完&#xff0c;再碰线上代码”。文档不厚&#xff0c;六十多页&…

作者头像 李华
网站建设 2026/11/4 5:12:25

按日期归档的更新日志页面:工程化拆解与实现

1. 一个“今日更新内容”页面背后的工程化拆解“今日更新内容-2025-11-21”这个标题乍一看像是一句随手记的备忘&#xff0c;但在实际项目里&#xff0c;它往往对应着一类非常具体的东西&#xff1a;按日期归档的更新日志页面。做过内容站、工具站、内部知识库或者产品公告页的…

作者头像 李华
网站建设 2026/11/4 5:12:25

GoFullPage全页截图:一键整页留存与智能拼接原理

1. 为什么我把它装进了每一台常用浏览器浏览器截图这件事&#xff0c;说起来简单&#xff0c;做起来烦。你打开一个网页&#xff0c;想把它完整保存下来&#xff0c;按下系统截图键&#xff0c;只能截到当前视口那一屏&#xff1b;想截全页&#xff0c;要么手动滚动拼接&#x…

作者头像 李华
网站建设 2026/11/4 5:12:10

Lambda表达式在大厂规范中的争议与最佳实践

1. 项目概述&#xff1a;Lambda表达式在大厂规范中的争议第一次在团队代码评审中看到"Lambda表达式禁止使用"的规范时&#xff0c;我下意识认为这是技术保守的表现。直到负责维护一个满是Lambda的旧项目后&#xff0c;才真正理解大厂规范背后的深层考量——这本质上是…

作者头像 李华