4. 基本矢量作用时间:计算相邻非零矢量与零矢量的作用时间
好,我们继续往下走。上一章我们把扇区判断搞定了,知道了参考电压矢量落在哪个60°扇区里。那接下来要解决的核心问题就是:在这个扇区里,两个相邻的非零矢量和零矢量,各自要作用多长时间?
说白了,就是怎么用时间配比来合成我们想要的电压矢量。这步算不对,后面的PWM波形全是错的。我记得刚入行那会儿,有次调试电机抖得跟筛糠似的,查了半天,就是作用时间算错了小数点。
4.1 伏秒平衡原理:时间计算的基石
在讲具体公式之前,得先理解一个基本原则——伏秒平衡。
什么意思?你想想看,在一个PWM周期 \( T_s \) 内,我们想让逆变器输出的平均电压等于参考电压 \( V_{ref} \)。但实际逆变器只能输出那几个基本矢量(比如 \( V_1 \)、\( V_2 \) 和零矢量 \( V_0/V_7 \))。
所以,我们让这几个矢量分别作用一段时间,只要它们产生的总效果(伏秒积)跟参考矢量连续作用一个周期一样,那就等效了。公式长这样:
\[ V_{ref} \cdot T_s = V_x \cdot T_x + V_y \cdot T_y + V_0 \cdot T_0 \]其中:
- \( V_x \)、\( V_y \) 是扇区边界的两个相邻非零矢量
- \( T_x \)、\( T_y \) 是它们的作用时间
- \( V_0 \) 是零矢量,\( T_0 \) 是零矢量作用时间
而且时间必须满足:\( T_x + T_y + T_0 = T_s \)。
核心思想: 用有限个离散的开关状态,在时间上平均出连续的电压效果。这就是SVPWM能输出正弦波的根本原因。
4.2 第一扇区(I扇区)的作用时间推导
我们拿第一扇区来举例。假设参考矢量 \( V_{ref} \) 落在 \( V_1(100) \) 和 \( V_2(110) \) 之间,夹角为 \( \theta \)。
根据伏秒平衡,在 \( \alpha\beta \) 坐标系下分解:
- \( \alpha \) 轴: \( |V_{ref}| \cdot \cos\theta \cdot T_s = |V_1| \cdot T_1 + |V_2| \cdot \cos 60^\circ \cdot T_2 \)
- \( \beta \) 轴: \( |V_{ref}| \cdot \sin\theta \cdot T_s = |V_2| \cdot \sin 60^\circ \cdot T_2 \)
这里 \( |V_1| = |V_2| = \frac{2}{3}V_{dc} \)(这是基本矢量的幅值,我们之前讲过)。
解这个方程组,得到:
\[ T_1 = \frac{\sqrt{3} \cdot |V_{ref}| \cdot T_s}{V_{dc}} \cdot \sin(60^\circ - \theta) \] \[ T_2 = \frac{\sqrt{3} \cdot |V_{ref}| \cdot T_s}{V_{dc}} \cdot \sin(\theta) \]看着有点复杂?别急,我们一般会引入调制比 \( m \)**的概念:
\[ m = \frac{\sqrt{3} \cdot |V_{ref}|}{V_{dc}} \]这样公式就清爽多了:
\[ T_1 = m \cdot T_s \cdot \sin(60^\circ - \theta) \] \[ T_2 = m \cdot T_s \cdot \sin(\theta) \]我的习惯: 在实际代码里,我不会每次都算sin函数。我会提前算好一个正弦表,查表加线性插值,速度快很多。特别是对于低成本MCU,这能省下不少CPU周期。
4.3 扩展到所有扇区:通用计算公式
其他扇区的推导思路完全一样。我总结了一个通用方法,你直接套用就行:
- 确定当前扇区号 \( N \)(上一章我们讲过怎么算)
- 找到扇区对应的两个相邻矢量 \( V_x \)、\( V_y \)
- 计算参考矢量相对于扇区起始边的角度 \( \theta_{rel} \)
- 代入上面的公式,把 \( \theta \) 换成 \( \theta_{rel} \)
为了方便查,我整理了一张表:
| 扇区号 | 相邻矢量 | \( T_x \)(第一个矢量) | \( T_y \)(第二个矢量) |
|---|---|---|---|
| I | \( V_1(100) \)、\( V_2(110) \) | \( m \cdot T_s \cdot \sin(60^\circ - \theta) \) | \( m \cdot T_s \cdot \sin(\theta) \) |
| II | \( V_3(010) \)、\( V_2(110) \) | \( m \cdot T_s \cdot \sin(120^\circ - \theta) \) | \( m \cdot T_s \cdot \sin(\theta - 60^\circ) \) |
| III | \( V_3(010) \)、\( V_4(011) \) | \( m \cdot T_s \cdot \sin(180^\circ - \theta) \) | \( m \cdot T_s \cdot \sin(\theta - 120^\circ) \) |
| IV | \( V_5(001) \)、\( V_4(011) \) | \( m \cdot T_s \cdot \sin(240^\circ - \theta) \) | \( m \cdot T_s \cdot \sin(\theta - 180^\circ) \) |
| V | \( V_5(001) \)、\( V_6(101) \) | \( m \cdot T_s \cdot \sin(300^\circ - \theta) \) | \( m \cdot T_s \cdot \sin(\theta - 240^\circ) \) |
| VI | \( V_1(100) \)、\( V_6(101) \) | \( m \cdot T_s \cdot \sin(360^\circ - \theta) \) | \( m \cdot T_s \cdot \sin(\theta - 300^\circ) \) |
注意: 这里的 \( \theta \) 是参考矢量在静止坐标系下的绝对角度(0°~360°)。计算时注意角度范围,别搞混了。我曾经在扇区边界上因为角度跳变没处理好,导致电流波形出现毛刺,查了好久才找到原因。
4.4 零矢量作用时间与过调制处理
两个非零矢量的时间算出来了,零矢量的时间就简单了:
\[ T_0 = T_s - T_x - T_y \]但这里有个坑——过调制。
如果 \( T_x + T_y > T_s \),说明参考电压矢量超出了六边形的内切圆范围(也就是调制比 \( m > 1 \))。这时候你算出来的 \( T_0 \) 是负数,物理上不可能实现。
怎么办?我一般这样处理:
- 先判断:如果 \( T_x + T_y \leq T_s \),正常计算
- 如果超了,按比例压缩:
这样虽然输出电压的幅值和相位会有点失真,但至少系统不会崩溃。实际项目中,我一般会把调制比限制在0.95左右,留点余量。
4.5 整体计算流程图
下面这张图把整个计算流程串起来了,你可以对照着看:
4.6 代码实现示例
最后,给出一段C代码,把上面的逻辑落地。这是我个人比较喜欢的写法,清晰且高效:
// 计算基本矢量作用时间
// 输入: V_alpha, V_beta, Ts, Vdc
// 输出: T1, T2, T0
void calc_vector_times(float V_alpha, float V_beta, float Ts, float Vdc,
float *T1, float *T2, float *T0) {
// 1. 计算扇区号 (假设已有函数)
int sector = get_sector(V_alpha, V_beta);
// 2. 计算中间变量 X, Y, Z (基于 Clarke 变换结果)
float X = V_beta;
float Y = (sqrtf(3)/2) * V_alpha - 0.5 * V_beta;
float Z = (-sqrtf(3)/2) * V_alpha - 0.5 * V_beta;
// 3. 根据扇区查表赋值
switch(sector) {
case 1: *T1 = Z; *T2 = Y; break;
case 2: *T1 = Y; *T2 = -X; break;
case 3: *T1 = -Z; *T2 = X; break;
case 4: *T1 = -X; *T2 = Z; break;
case 5: *T1 = X; *T2 = -Y; break;
case 6: *T1 = -Y; *T2 = -Z; break;
default: *T1 = 0; *T2 = 0; break;
}
// 4. 归一化到 Ts
float t_factor = Ts / Vdc;
*T1 *= t_factor;
*T2 *= t_factor;
// 5. 过调制处理
float sum = *T1 + *T2;
if (sum > Ts) {
*T1 = (*T1 / sum) * Ts;
*T2 = (*T2 / sum) * Ts;
*T0 = 0;
} else {
*T0 = Ts - sum;
}
}
避坑指南: 注意浮点运算的精度。在定点MCU上,我建议把所有计算都转成Q15或Q24格式,避免除法带来的性能开销。另外,sqrtf(3) 可以预编译成常量,别每次都算。
嗯,到这里,基本矢量的作用时间计算就讲完了。你只要把扇区判断和这套时间计算公式吃透,SVPWM的核心算法就算拿下了。下一块内容,我们会把这些时间值映射到实际的PWM比较寄存器上,生成真正的开关波形。