第 5 章 SVPWM 空间矢量调制:FOC 的最后一块拼图
前言前面四章我们已经完成了六步换相实战Clark 变换三相 → 两相静止 αβPark 变换交流 → 直流 dq电流 PI 闭环得到 Vd,Vq反 Park 变换得到控制电压 Vα,Vβ现在我们手里有了α-β 坐标系下的电压矢量但单片机最终要输出的是U、V、W 三相 PWM 占空比。把电压矢量翻译成三相 PWM 的过程就是SVPWMSpace Vector Pulse Width Modulation。它是 FOC 控制的最后、最工程化的一步也是决定电机力矩平滑度低速噪音电流谐波电压利用率的关键环节。1. 什么是电压矢量极简理解三相逆变器一共 6 个开关管只有 8 种有效开关组合6 个非零电压矢量形成磁场旋转2 个零矢量电压为 0电机不产生力矩SVPWM 的核心思想一句话用 8 个基本矢量按不同时间长短组合合成出我们想要的任意电压矢量 Vref(α,β)就像用红、绿、蓝三原色混合出任意颜色一样。2. 六个扇区与基本电压矢量把 360° 电角度平分为6 个扇区每个 60°扇区 10° ~ 60°扇区 260° ~ 120°扇区 3120° ~ 180°扇区 4180° ~ 240°扇区 5240° ~ 300°扇区 6300° ~ 360°每个扇区使用相邻两个有效矢量 零矢量来合成目标电压。电压利用率对比普通 SPWM≈ 86.6%SVPWM≈ 105%同等母线电压下电机能输出更高力矩这就是 FOC 电机高速更有劲的原因。3. SVPWM 标准工程实现流程固定 7 步工程上 SVPWM 永远按这 7 步走一步都不能乱输入Vα,Vβ计算三个中间变量Uref1,Uref2,Uref3判断当前矢量在哪个扇区1~6计算两个有效矢量的作用时间 T1,T2限幅处理防止过调制根据扇区计算三相比较值 CMRV、CMRV、CMRW装入 TIM1 捕获比较寄存器输出 PWM下面直接给出每一步的工程公式与代码。4. 扇区判断公式最常用标准形式定义根据三者符号判断扇区若 A0 → 记为 1若 B0 → 记为 2若 C0 → 记为 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 点8 个基本矢量合成任意电压矢量工程流程固定扇区判断 → 时间计算 → 三相占空比代码直接套用即可重点是坐标系统一、角度同步、限幅保护到本章为止FOC 全套核心算法已经全部讲完坐标变换电流闭环空间矢量调制你已经具备写出完整 FOC 电机驱动的全部理论与代码基础。