ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

第 5 章 SVPWM 空间矢量调制:FOC 的最后一块拼图

2026/8/16 22:58:47 拓冰建站 浏览量
第 5 章 SVPWM 空间矢量调制:FOC 的最后一块拼图

前言

前面四章,我们已经完成了:

  • 六步换相实战
  • Clark 变换:三相 → 两相静止 αβ
  • Park 变换:交流 → 直流 dq
  • 电流 PI 闭环:得到 Vd​,Vq​
  • 反 Park 变换:得到控制电压 Vα​,Vβ​

现在我们手里有了α-β 坐标系下的电压矢量,但单片机最终要输出的是U、V、W 三相 PWM 占空比

把电压矢量翻译成三相 PWM 的过程,就是SVPWM(Space Vector Pulse Width Modulation)

它是 FOC 控制的最后、最工程化的一步,也是决定电机:

  • 力矩平滑度
  • 低速噪音
  • 电流谐波
  • 电压利用率

的关键环节。

1. 什么是电压矢量?(极简理解)

三相逆变器一共 6 个开关管,只有 8 种有效开关组合:

  • 6 个非零电压矢量(形成磁场旋转)
  • 2 个零矢量(电压为 0,电机不产生力矩)

SVPWM 的核心思想一句话:

用 8 个基本矢量,按不同时间长短组合,合成出我们想要的任意电压矢量 Vref​(α,β)

就像用红、绿、蓝三原色混合出任意颜色一样。

2. 六个扇区与基本电压矢量

把 360° 电角度平分为6 个扇区,每个 60°:

  • 扇区 1:0° ~ 60°
  • 扇区 2:60° ~ 120°
  • 扇区 3:120° ~ 180°
  • 扇区 4:180° ~ 240°
  • 扇区 5:240° ~ 300°
  • 扇区 6:300° ~ 360°

每个扇区使用相邻两个有效矢量 + 零矢量来合成目标电压。

电压利用率对比:

  • 普通 SPWM:≈ 86.6%
  • SVPWM:≈ 105%(同等母线电压下,电机能输出更高力矩)

这就是 FOC 电机高速更有劲的原因。

3. SVPWM 标准工程实现流程(固定 7 步)

工程上 SVPWM 永远按这 7 步走,一步都不能乱:

  1. 输入:Vα​,Vβ​
  2. 计算三个中间变量:Uref1​,Uref2​,Uref3​
  3. 判断当前矢量在哪个扇区(1~6)
  4. 计算两个有效矢量的作用时间 T1​,T2​
  5. 限幅处理,防止过调制
  6. 根据扇区计算三相比较值 CMRV、CMRV、CMRW
  7. 装入 TIM1 捕获比较寄存器,输出 PWM

下面直接给出每一步的工程公式与代码。

4. 扇区判断公式(最常用标准形式)

定义:

根据三者符号判断扇区:

  • 若 A>0 → 记为 1
  • 若 B>0 → 记为 2
  • 若 C>0 → 记为 4

相加得到sector = 1~6

这是工业电机库最通用的扇区判断法,没有之一。

5. 作用时间 T1、T2 计算

其中:

  • Udc​:母线电压
  • PWM_PERIOD:定时器重装载值(ARR)

然后必须做饱和限制

防止过调制导致波形畸变。

6. 三相占空比计算(核心)

根据不同扇区,三相中点对称 PWM 比较值如下:

  • 扇区 1

扇区 2

扇区 3:

扇区 4

扇区 5

扇区 6

最终:

直接写入定时器寄存器即可输出 SVPWM。

7. 完整工程代码(浮点版)

#include "math.h" #define PWM_PERIOD 7200 // 10kHz, 72MHz #define U_DC 24.0f // 母线电压24V typedef struct { float Valpha; float Vbeta; uint16_t CCRU; uint16_t CCRV; uint16_t CCRW; }SVPWM_Struct; SVPWM_Struct svpwm; /** * @brief SVPWM 工程实现完整版 * @param Valpha,Vbeta: 反Park输出电压 */ void SVPWM_Calc(float Valpha, float Vbeta) { float Uref1, Uref2, Uref3; float T1, T2, T; float Ta, Tb, Tc; uint8_t sector = 0; // 1. 计算扇区判断变量 Uref1 = Vbeta; Uref2 = (sqrtf(3.0f)*0.5f)*Valpha - 0.5f*Vbeta; Uref3 = (-sqrtf(3.0f)*0.5f)*Valpha - 0.5f*Vbeta; // 2. 扇区判断 sector = 0; if(Uref1 > 0) sector += 1; if(Uref2 > 0) sector += 2; if(Uref3 > 0) sector += 4; // 3. 计算作用时间 T = (sqrtf(3.0f) * PWM_PERIOD) / U_DC; T1 = T * Uref3 * (sqrtf(3.0f)/3.0f); T2 = T * Uref2 * (sqrtf(3.0f)/3.0f); // 4. 过调制限制 if(T1 + T2 > PWM_PERIOD) { float k = PWM_PERIOD / (T1 + T2); T1 *= k; T2 *= k; } // 5. 根据扇区计算三相占空比 switch(sector) { case 1: Ta = (PWM_PERIOD - T1 - T2)/4.0f; Tb = Ta + T1/2.0f; Tc = Tb + T2/2.0f; break; case 2: Ta = (PWM_PERIOD - T1 - T2)/4.0f; Tc = Ta + T1/2.0f; Tb = Tc + T2/2.0f; break; case 3: Tb = (PWM_PERIOD - T1 - T2)/4.0f; Tc = Tb + T1/2.0f; Ta = Tc + T2/2.0f; break; case 4: Tb = (PWM_PERIOD - T1 - T2)/4.0f; Ta = Tb + T1/2.0f; Tc = Ta + T2/2.0f; break; case 5: Tc = (PWM_PERIOD - T1 - T2)/4.0f; Ta = Tc + T1/2.0f; Tb = Ta + T2/2.0f; break; case 6: Tc = (PWM_PERIOD - T1 - T2)/4.0f; Tb = Tc + T1/2.0f; Ta = Tb + T2/2.0f; break; default: Ta = Tb = Tc = PWM_PERIOD/2; break; } // 输出限幅 & 赋值 if(Ta < 0) Ta = 0; if(Ta > PWM_PERIOD) Ta = PWM_PERIOD; if(Tb < 0) Tb = 0; if(Tb > PWM_PERIOD) Tb = PWM_PERIOD; if(Tc < 0) Tc = 0; if(Tc > PWM_PERIOD) Tc = PWM_PERIOD; svpwm.CCRU = (uint16_t)Ta; svpwm.CCRV = (uint16_t)Tb; svpwm.CCRW = (uint16_t)Tc; // 直接更新PWM占空比 TIM1->CCR1 = svpwm.CCRU; TIM1->CCR2 = svpwm.CCRV; TIM1->CCR3 = svpwm.CCRW; }

8. 如何在完整 FOC 中调用 SVPWM?

完整调用链:

// 1. 采样电流 Iu = Get_ADC_CurrentU() - OFFSET; Iv = Get_ADC_CurrentV() - OFFSET; Iw = -Iu - Iv; // 2. Clark Clark_Transform(Iu, Iv, Iw, &Ialpha, &Ibeta); // 3. Park Park_Transform(Ialpha, Ibeta, theta, &Id, &Iq); // 4. PI电流环 Vd = PI_Calc(&PID_Id, 0.0f, Id); Vq = PI_Calc(&PID_Iq, Iq_ref, Iq); // 5. 反Park Inv_Park(Vd, Vq, theta, &Valpha, &Vbeta); // 6. SVPWM 输出 SVPWM_Calc(Valpha, Vbeta);

一个周期走完,电机就进入真正的 FOC 闭环运行


9. SVPWM 工程常见坑(必看)

9.1 母线电压未实时采样

如果电池电压波动,SVPWM 会过调制或欠调制,电机抖动。解决:实时采样 Udc​ 带入计算。

9.2 PWM 中心对齐模式没开

SVPWM 必须用中心对齐 PWM,否则波形不对称、噪音大。

9.3 扇区判断符号错误

只要有一个符号取反,整个 6 个扇区全乱,电机直接啸叫。

9.4 死区设置不合理

死区太小炸管,太大力矩弱、低速抖。建议:1~3μs。

9.5 角度 θ 不同步

ADC 采样、运算、PWM 更新之间有延迟,角度必须做相位补偿,否则低速抖动明显。


10. 本章总结

SVPWM 是 FOC 的最终输出环节,核心就 3 点:

  1. 8 个基本矢量合成任意电压矢量
  2. 工程流程固定:扇区判断 → 时间计算 → 三相占空比
  3. 代码直接套用即可,重点是坐标系统一、角度同步、限幅保护

到本章为止,FOC 全套核心算法已经全部讲完

  • 坐标变换
  • 电流闭环
  • 空间矢量调制

你已经具备写出完整 FOC 电机驱动的全部理论与代码基础。