3. 位置与速度获取:基于编码器的位置解算、M法/T法测速原理、低速与高速下的测速策略

编码器装上了,线也接好了,信号也能看到了。接下来最关键的一步:怎么从这些方波里算出位置和速度?

说实话,我刚入行那会儿,觉得这事特简单——数脉冲不就行了?结果第一次做低速测试,速度跳得像心电图,电机抖得跟筛糠似的。后来才明白,编码器数据融合这件事,远不止“数数”那么简单。

3.1 位置解算:从脉冲到角度

位置解算是基础。你拿到A、B两路正交方波,第一步就是判断方向,第二步才是算位置。

3.1.1 方向判断

A相领先B相90°,正转;B相领先A相90°,反转。这个逻辑用硬件或软件都能做。我习惯在定时器捕获中断里同时读两相电平,用状态机判断。

核心逻辑:

  • A上升沿 && B=低 → 正转
  • A上升沿 && B=高 → 反转
  • 同理,A下降沿、B上升沿、B下降沿都能判断

3.1.2 位置累加

方向定了,剩下的就是累加或累减脉冲数。假设编码器每转1000线,4倍频后就是4000个脉冲/圈。

// 伪代码:位置解算
int32_t pulse_count = 0;

void encoder_irq_handler(uint8_t dir) {
    if (dir == CW) {
        pulse_count++;
    } else {
        pulse_count--;
    }
}

float get_angle_deg(void) {
    return (float)pulse_count / 4000.0f * 360.0f;
}

嗯,这里要注意:pulse_count 必须用32位有符号整型。我曾经见过有人用16位,结果电机转了几圈就溢出了,位置直接飞掉。

3.1.3 零点校准

绝对位置怎么来?靠Z信号。每转一圈,Z相给一个脉冲,这时候把 pulse_count 清零或置为预设值。这样每次上电后,只要转一圈找到Z,位置就绝对了。

我的习惯:上电后先执行一次“寻零”动作——低速转动直到捕获到Z信号。如果应用不允许转动,那就得用绝对值编码器了。

3.2 M法测速:高频脉冲下的精准测量

M法,说白了就是“数脉冲”。在固定时间窗口 T 内,数编码器产生了多少个脉冲 M,然后算速度。

公式很简单:

速度 = (M / (编码器线数 × 4)) / T × 60  (单位:RPM)

举个例子:编码器1000线,4倍频,时间窗口10ms,数到200个脉冲。

速度 = (200 / 4000) / 0.01 × 60 = 300 RPM

3.2.1 M法的优缺点

项目 说明
优点 高速时精度高,计算简单,适合中高速场景
缺点 低速时脉冲少,量化误差大,速度更新慢

你想想看,如果电机只转1 RPM,10ms窗口里可能只抓到1个脉冲甚至0个。那算出来的速度不是0就是15 RPM,跳得没法用。

3.3 T法测速:低速时的救命稻草

T法和M法正好反过来。它不数脉冲,而是测量两个相邻脉冲之间的时间间隔 T_pulse。

速度 = 1 / (T_pulse × 编码器线数 × 4) × 60  (单位:RPM)

时间间隔用高频定时器来量。比如定时器时钟1 MHz,测到两个脉冲间隔5000个时钟周期:

T_pulse = 5000 / 1e6 = 0.005 秒
速度 = 1 / (0.005 × 4000) × 60 = 3 RPM

3.3.1 T法的优缺点

项目 说明
优点 低速时精度高,响应快
缺点 高速时脉冲间隔太短,定时器分辨率不够,误差变大

注意:T法在高速时可能遇到“定时器溢出”的问题。如果两个脉冲间隔小于定时器的最小分辨率,那就测不准了。我曾经在3000 RPM的电机上试过,1000线编码器,两个脉冲间隔只有5微秒,普通定时器根本扛不住。

3.4 M/T法:高低速通吃

既然M法适合高速,T法适合低速,那把它们结合起来不就行了?这就是M/T法。

M/T法的思路:同时测量固定时间窗口内的脉冲数 M,以及这个窗口内最后一个完整脉冲的时间间隔 T_pulse。

速度 = (M × f_timer) / (N × T_pulse)

其中 f_timer 是定时器频率,N 是编码器每转总脉冲数。

这样做的好处:低速时 T_pulse 大,T法主导;高速时 M 大,M法主导。两者自动平滑过渡。

实际效果:我在一个伺服项目里用过M/T法,速度范围从1 RPM到5000 RPM,测速误差控制在±0.1%以内。比单独用M法或T法稳定太多了。

3.5 低速与高速下的测速策略选择

实际工程里,你不会只用一种方法。我一般这样选:

  • 低于 10 RPM: 纯T法,或者用高线数编码器(比如5000线)配合T法
  • 10 ~ 100 RPM: M/T法,过渡区
  • 高于 100 RPM: 纯M法,简单高效

但这里有个坑:切换阈值附近容易跳变。我习惯加一个滞回区间,比如10~15 RPM用T法,15~20 RPM用M/T法,20以上用M法。这样不会来回切换。

3.6 知识体系总览

下面这张图把位置解算和测速方法的整体逻辑串起来了,你可以对照着看。

编码器数据融合:位置与速度获取知识体系 编码器 A/B/Z 信号 位置解算 核心步骤 1. 方向判断(A/B 相位差) 2. 脉冲累加(32位计数器) 3. Z信号零点校准 速度获取 M法 高速高精度 T法 低速高精度 M/T法 全速域平滑过渡 测速策略选择(按转速区间) < 10 RPM 纯T法 / 高线数编码器 10 ~ 100 RPM M/T法(滞回切换) > 100 RPM 纯M法(简单高效)

3.7 实际工程中的避坑指南

最后分享几个我踩过的坑,希望能帮你省点时间。

我曾经犯过的错:

  • 中断优先级没设好:编码器中断优先级太低,被其他任务打断,导致丢脉冲。后来我把编码器中断提到最高,问题解决。
  • 滤波器没加:编码器信号有毛刺,直接进计数器,位置乱跳。加个RC滤波或者软件去抖就好了。
  • Z信号没做防抖:Z信号只在特定位置出现,但如果有干扰,可能误触发。我习惯在Z中断里连续读两次确认。
  • 速度计算周期太长:用M法时,如果计算周期设成100ms,低速下速度更新慢得像蜗牛。我一般设10ms,够用。

好了,位置和速度获取这部分就聊到这儿。记住一句话:没有万能的方法,只有合适的策略。根据你的转速范围、精度要求和硬件资源,选对方法,比什么都重要。