3. 角度偏差对扇区判断的影响

好,咱们接着聊。上一节我们讲了角度偏差怎么来的,这一节我们看看它到底会造成什么后果。我个人觉得,扇区误判是角度偏差最直接、也最容易被忽视的问题。

你想想看,SVPWM 的第一步是什么?是判断当前电压矢量落在哪个扇区。这个判断完全依赖电角度 θ。如果 θ 本身就有误差,那扇区边界就会“漂移”。说白了,你以为是扇区 I,实际上已经跑到扇区 II 去了。

3.1 扇区划分与边界

标准的 SVPWM 把空间电压矢量平面分成 6 个扇区,每个扇区 60°。边界分别在 0°、60°、120°、180°、240°、300°。判断逻辑很简单:

  • 扇区 I:0° ~ 60°
  • 扇区 II:60° ~ 120°
  • 扇区 III:120° ~ 180°
  • 扇区 IV:180° ~ 240°
  • 扇区 V:240° ~ 300°
  • 扇区 VI:300° ~ 360°

判断方法一般是用 Clarke 变换后的 Uα、Uβ 来计算角度,或者直接用 θ 查表。不管哪种方式,核心都是 θ。

关键点: 扇区边界是固定的,但实际使用的 θ 是有误差的。这就导致边界在“真实坐标系”里发生了偏移。

3.2 边界偏移的数学分析

假设真实电角度是 θreal,我们测量/估算到的角度是 θest = θreal + Δθ。那么,当我们用 θest 判断扇区时,相当于把整个扇区边界旋转了 Δθ。

举个例子。真实角度在 59°,属于扇区 I。如果 Δθ = +3°,那么 θest = 62°,系统会误判为扇区 II。这就是边界误判。

我整理了一个表格,方便你直观理解:

真实角度范围 Δθ = +5° 时的误判区域 Δθ = -5° 时的误判区域
0° ~ 5° 扇区 VI → 扇区 I 扇区 I → 扇区 VI
55° ~ 65° 扇区 I → 扇区 II 扇区 II → 扇区 I
115° ~ 125° 扇区 II → 扇区 III 扇区 III → 扇区 II
175° ~ 185° 扇区 III → 扇区 IV 扇区 IV → 扇区 III
235° ~ 245° 扇区 IV → 扇区 V 扇区 V → 扇区 IV
295° ~ 305° 扇区 V → 扇区 VI 扇区 VI → 扇区 V

你看,每个扇区边界附近都有 ±|Δθ| 的“模糊带”。在这个区域内,扇区判断是不确定的。

3.3 误判的后果

扇区一旦判错,后面所有计算都跟着错。具体来说:

  • 基本矢量选择错误: 扇区决定了用哪两个相邻基本矢量来合成目标矢量。判错扇区,基本矢量就选错了。
  • 作用时间计算错误: 每个扇区的作用时间公式不同。用错公式,T1、T2 全错。
  • 电流波形畸变: 最终导致相电流出现毛刺、谐波增大,严重时电机抖动、噪声变大。
我曾经踩过的坑: 有一次调试高速电机,转速一上去电流波形就出现“台阶”。查了两天,最后发现是角度估算延迟导致 Δθ 在边界附近来回跳,扇区频繁误判。后来加了滞回比较才解决。

3.4 扇区误判的 SVG 示意图

下面这张图展示了 Δθ 为正时,扇区边界如何偏移:

扇区边界偏移示意图(Δθ > 0) I II III IV V VI I' II' III' IV' V' VI' 真实边界 偏移后边界 (Δθ=15°) 阴影区域为误判区 真实扇区 I → 误判为扇区 II 真实扇区 VI → 误判为扇区 I

图中蓝色实线是真实扇区边界,红色虚线是偏移后的边界。你可以看到,在边界附近,真实扇区和误判扇区重叠了。这就是误判发生的区域。

3.5 如何避免扇区误判

嗯,这里要注意。扇区误判不能完全消除,但可以抑制。我个人习惯用以下几种方法:

  1. 滞回比较: 在边界附近设置一个滞回区间。比如 0° 边界,设置滞回区间为 [-2°, +2°]。角度在这个区间内时,保持上一次的扇区判断结果不变。这样可以避免边界来回跳变。
  2. 角度补偿: 如果知道 Δθ 的大致规律(比如固定延迟导致的固定偏移),可以在软件里做反向补偿。
  3. 提高角度估算精度: 用更好的观测器(比如滑模观测器、龙伯格观测器),或者用更高精度的编码器。
小技巧: 我在做低速大扭矩项目时,发现用滞回比较特别管用。滞回宽度一般取 Δθ 最大值的 1.5~2 倍。比如你的角度误差最大 ±3°,滞回宽度设 ±5° 就够用了。

3.6 代码实现示例

下面是一段扇区判断的 C 代码,加了滞回处理。你可以参考一下:

// 扇区判断函数,带滞回
// theta_est: 当前估算角度(度)
// last_sector: 上一次的扇区编号
// return: 当前扇区编号(1~6)
int sector_judge_with_hysteresis(float theta_est, int last_sector) {
    // 将角度归一化到 0~360
    theta_est = fmodf(theta_est, 360.0f);
    if (theta_est < 0) theta_est += 360.0f;
    
    // 滞回宽度(度),根据实际误差调整
    const float HYST = 5.0f;
    
    // 计算边界,带滞回
    float bound_low, bound_high;
    
    // 根据上一次扇区,调整当前扇区的判断边界
    switch (last_sector) {
        case 1: // 扇区 I: 0~60
            bound_low = 0.0f - HYST;   // -5°
            bound_high = 60.0f + HYST; // 65°
            break;
        case 2: // 扇区 II: 60~120
            bound_low = 60.0f - HYST;  // 55°
            bound_high = 120.0f + HYST; // 125°
            break;
        // ... 其他扇区类似
        default:
            bound_low = 0.0f;
            bound_high = 60.0f;
            break;
    }
    
    // 判断当前角度是否在滞回区间内
    if (theta_est >= bound_low && theta_est < bound_high) {
        return last_sector; // 保持上一次扇区
    }
    
    // 否则,重新判断扇区(标准逻辑)
    if (theta_est < 60.0f) return 1;
    else if (theta_est < 120.0f) return 2;
    else if (theta_est < 180.0f) return 3;
    else if (theta_est < 240.0f) return 4;
    else if (theta_est < 300.0f) return 5;
    else return 6;
}

这段代码的核心思想是:在边界附近,不轻易切换扇区。只有角度明显离开边界区域后,才重新判断。这样能有效抑制因角度抖动导致的扇区频繁切换。

好了,这一节就到这里。扇区误判是角度偏差的“第一波攻击”,理解了它,后面再看作用时间误差、电流畸变就顺理成章了。