1. 编码器基础与换相原理

各位同学好,我是老周。做电机控制这些年,我踩过最多的坑,就是编码器换相这块。今天咱们就从最基础的东西聊起。

编码器是什么?说白了,它就是电机的「眼睛」。没有它,你的控制器就是个瞎子,不知道转子转到哪了,也不知道该给哪相通电。我刚开始做无刷电机驱动时,就吃过这个亏——编码器信号没处理好,电机抖得像筛糠一样。

1.1 增量式与绝对式编码器

先搞清楚两种编码器的区别。这俩东西,选错了后面全白干。

特性 增量式编码器 绝对式编码器
输出信号 A、B、Z 三路脉冲 多路并行或串行二进制码
断电记忆 不记忆位置 记忆绝对位置
分辨率 取决于线数(如 1024 线) 取决于位数(如 12 位 = 4096 位置)
抗干扰 脉冲易受干扰 格雷码抗干扰强
成本 低 高
典型应用 伺服电机、步进电机 机器人关节、数控机床

增量式编码器,它只告诉你「我动了多少」,不告诉你「我在哪」。上电后必须找零位(Z 信号),否则位置是未知的。我在做 AGV 小车驱动时遇到过一个问题——每次断电重启,电机都要先转一圈找 Z 信号,那个过程特别慢,客户投诉了好几次。

绝对式编码器就省心多了。上电就知道转子在哪个角度,直接就能换相。我建议,如果你的项目对启动速度有要求,或者断电后位置不能丢,直接上绝对式。多花点钱,省很多调试时间。

我的经验:增量式编码器做换相,一定要在初始化阶段做「找零」流程。我习惯在电机上电后先低速转动,等 Z 信号出现后记录位置,再切换到正常控制。这个流程虽然简单,但很多人忘了做,结果电机一启动就乱跳。

1.2 霍尔传感器与换相逻辑

霍尔传感器,是另一种「眼睛」。它不像编码器那么精细,但胜在简单、便宜、可靠。

霍尔元件怎么工作的?它检测磁场极性。转子上的磁铁转过霍尔时,输出高或低电平。三个霍尔(H1、H2、H3)组合起来,就能判断转子在哪个 60° 扇区。

我画了一张图,帮你理解霍尔信号和转子位置的关系:

霍尔传感器与转子扇区对应关系 N S1 S2 S3 S4 S5 S6 H1 H2 H3 三个霍尔相隔 120° 安装,每个扇区 60°,霍尔组合唯一确定转子位置

霍尔信号组合与换相的关系,我整理了一个表。这个表你最好背下来,写代码时直接查表就行:

扇区 H1 H2 H3 通电相(A-B-C)
S1 1 0 1 A+ / B-
S2 1 0 0 A+ / C-
S3 1 1 0 B+ / C-
S4 0 1 0 B+ / A-
S5 0 1 1 C+ / A-
S6 0 0 1 C+ / B-
注意:霍尔信号组合中,不会出现 000 和 111 这两种状态。如果你在代码里读到了这两个值,说明霍尔传感器坏了或者接线有问题。我曾经在产线上遇到过一批霍尔焊反的板子,排查了整整两天才找到原因。

1.3 六步换相法原理

六步换相,也叫「梯形波控制」。为什么叫六步?因为一个电周期内,你要切换六次通电状态。

你想想看,无刷电机有三相绕组(A、B、C)。每一时刻,只有两相通电,第三相悬空。每 60° 电角度换一次相,转一圈(360°)正好换六次。

换相的核心逻辑是这样的:

  1. 读霍尔:获取当前 H1、H2、H3 的状态
  2. 查表:根据霍尔组合找到对应的扇区
  3. 通电:按扇区对应的方式给两相绕组通电
  4. 等待:转子转动,霍尔信号变化
  5. 重复:回到第 1 步

代码实现其实不复杂。我写了一个简单的示例,这是六步换相的核心逻辑:

// 霍尔状态到通电相位的映射表
// 索引:霍尔值(H3 H2 H1 组合)
const uint8_t hall_to_phase[8] = {
    0xFF,       // 000 - 无效
    0b001001,   // 001 - C+ B-
    0b000110,   // 010 - B+ A-
    0b010010,   // 011 - C+ A-
    0b100100,   // 100 - A+ C-
    0b011000,   // 101 - A+ B-
    0b100001,   // 110 - B+ C-
    0xFF        // 111 - 无效
};

void six_step_commutation(void) {
    uint8_t hall_state;
    uint8_t phase_pattern;
    
    // 1. 读取三个霍尔的状态
    hall_state = (H3_PIN << 2) | (H2_PIN << 1) | H1_PIN;
    
    // 2. 查表获取通电模式
    phase_pattern = hall_to_phase[hall_state];
    
    // 3. 检查有效性
    if (phase_pattern == 0xFF) {
        // 霍尔错误,进入保护
        motor_stop();
        return;
    }
    
    // 4. 写入 PWM 寄存器,控制三相桥
    PWM_A = (phase_pattern >> 5) & 0x01;
    PWM_B = (phase_pattern >> 4) & 0x01;
    PWM_C = (phase_pattern >> 3) & 0x01;
    // 下桥臂控制类似...
}

这段代码看起来简单,但实际工程中坑很多。我遇到过最典型的问题:霍尔信号抖动导致换相错误。电机高速转的时候,霍尔信号边沿会有毛刺,换相时机稍微偏一点,电流就爆了。

关键点:六步换相的性能瓶颈不在算法本身,而在霍尔信号的采样时机和滤波处理。我建议在霍尔输入引脚上加硬件 RC 滤波(1kΩ + 100nF),同时在软件里做 3-5 次连续采样确认,能有效避免误触发。

还有一个容易被忽略的问题:换相延时。从读到霍尔变化到实际切换 PWM,这个时间差决定了换相是否准确。我习惯用定时器捕获霍尔边沿,在中断里直接更新 PWM 寄存器,延迟能控制在 1-2μs 以内。

嗯,今天就先聊这么多。编码器基础、霍尔换相逻辑、六步换相法,这三块是后面所有内容的地基。你把这些吃透了,后面讲 FOC、讲高频注入,才能跟得上。