4. 速度计算与测速方法:基于霍尔脉冲的M法/T法/M-T法测速、低速与高速下的精度权衡
速度计算,说白了就是回答一个问题:电机转得有多快?
霍尔传感器每转一圈给你三个脉冲(或者更多,取决于极对数)。我们得从这些脉冲里把转速“算”出来。听起来简单,但实际做起来,你会发现低速和高速完全是两个世界。
我个人习惯把测速方法分成三类:M法、T法、M-T法。每种方法都有自己的脾气,选错了,你的控制系统就会“抖”给你看。
4.1 先搞清楚:霍尔脉冲与转速的关系
在讲方法之前,我们先统一一下基础概念。
一个霍尔传感器,每转过一个磁极,就输出一个跳变沿。对于一对极的电机,三个霍尔传感器,一圈总共产生 6 个跳变沿(上升沿+下降沿)。
所以,每个跳变沿对应的机械角度是:
Δθ = 360° / (3 × 2) = 60°
如果你用的是多对极电机,比如 4 对极,那每个跳变沿对应的电角度还是 60°,但机械角度变成了 60°/4 = 15°。
4.2 M法测速:高速时的好兄弟
M法,全称是“在规定时间内数脉冲”。
做法很简单:开一个固定时间窗口(比如 10ms),数一下这个窗口内来了多少个霍尔跳变沿。
速度 = (脉冲数 × 60) / (极对数 × 3 × 2 × 时间窗口)
举个例子,1 对极电机,10ms 内数到 30 个跳变沿:
速度 = (30 × 60) / (1 × 6 × 0.01) = 30000 RPM
优点很明显: 高速时脉冲多,计数准确,分辨率高。
缺点也很致命: 低速时,一个时间窗口可能只抓到 1 个甚至 0 个脉冲。你想想看,如果只抓到 1 个脉冲,速度就是 1000 RPM;抓到 2 个,就是 2000 RPM。这跳变太大了,控制根本稳不住。
4.3 T法测速:低速时的救星
T法,思路反过来——不数脉冲,而是测量两个脉冲之间的时间。
用定时器捕获两个相邻跳变沿的时间差 ΔT,然后:
速度 = 60 / (极对数 × 3 × 2 × ΔT)
还是 1 对极电机,如果测到两个跳变沿间隔 1ms:
速度 = 60 / (1 × 6 × 0.001) = 10000 RPM
低速时,脉冲间隔很长,定时器能测得很准。比如 10 RPM 时,两个跳变沿间隔 100ms,你用高精度定时器去量,误差很小。
但高速时,T 法就露怯了。10000 RPM 时,两个跳变沿间隔只有 1ms。如果你的定时器分辨率是 1μs,那测量误差就是 0.1%。还行。但如果转速到了 100000 RPM,间隔只有 100μs,误差就变成 1% 了。
- M法: 高速准,低速不准。
- T法: 低速准,高速不准。
4.4 M-T法:我全都要
既然 M 法和 T 法各有短板,那能不能把两者结合起来?
M-T法 就是干这个的。它的思路是:
- 设定一个固定的测速周期 T0(比如 10ms)。
- 在这个周期内,数脉冲个数 M1(M 法的思路)。
- 同时,用定时器测量这个周期内最后一个完整脉冲的时间间隔 T2(T 法的思路)。
- 最终速度 = (M1 × 60) / (极对数 × 3 × 2 × T2)
你看,它用 M1 来保证高速时的计数精度,用 T2 来保证低速时的测量精度。两者一结合,全速域都能获得不错的精度。
实际实现时,我一般这样写:
// 伪代码:M-T法测速
void Speed_MT_Calc(void)
{
static uint32_t last_capture = 0;
static uint32_t pulse_count = 0;
uint32_t current_capture;
uint32_t delta_t;
float speed;
// 霍尔中断服务函数中调用
current_capture = TIM_GetCapture(TIM2);
delta_t = current_capture - last_capture;
last_capture = current_capture;
pulse_count++;
// 每 10ms 计算一次速度
if (TIM_GetFlag(TIM3, TIM_FLAG_UPDATE))
{
if (delta_t > 0)
{
// M-T法核心公式
speed = (float)(pulse_count * 60) / (POLE_PAIRS * 6 * delta_t * TIMER_RESOLUTION);
}
pulse_count = 0;
TIM_ClearFlag(TIM3, TIM_FLAG_UPDATE);
}
}
4.5 三种方法对比:一张表说清楚
| 方法 | 原理 | 低速精度 | 高速精度 | 实现复杂度 | 适用场景 |
|---|---|---|---|---|---|
| M法 | 固定时间数脉冲 | 差 | 好 | 低 | 高速电机、风机、泵 |
| T法 | 测量脉冲间隔 | 好 | 差 | 低 | 低速伺服、位置控制 |
| M-T法 | 两者结合 | 好 | 好 | 中 | 全速域通用、高性能驱动 |
4.6 精度权衡:你到底需要多准?
你可能会问:我是不是无脑选 M-T 法就行了?
不一定。精度是有代价的。
- M法 实现最简单,代码量最少,适合对成本敏感、高速运行的场景(比如吸尘器、电风扇)。
- T法 在低速下精度极高,适合需要低速平稳运行的场景(比如机器人关节、转台)。
- M-T法 精度最好,但需要更多的定时器资源和更复杂的逻辑。如果你的 MCU 资源紧张,可能得不偿失。
我个人的选择原则是:
- 如果电机主要工作在额定转速的 30% 以上,用 M 法就够了。
- 如果电机经常工作在 10% 以下,必须用 T 法或 M-T 法。
- 如果全速域都需要高精度,别犹豫,上 M-T 法。
4.7 一张图看懂三种方法
下面这张图,我画了 M 法、T 法和 M-T 法的核心逻辑对比。你看一眼就能明白它们的区别。
4.8 实际调参中的几个坑
最后,分享几个我在实际项目中踩过的坑,希望能帮你少走弯路。
- 定时器分辨率不够: 有一次我用 72MHz 的定时器做 T 法测速,觉得够用了。结果电机在 100000 RPM 时,两个脉冲间隔只有 100μs,定时器只能数到 7200 个 tick。误差 0.014%,还行。但如果你的定时器只有 1MHz,那误差就大了。所以,高速时一定要用高分辨率定时器。
- 滤波不能少: 霍尔信号本身有抖动,尤其是电机振动大的时候。我一般会在速度计算后面加一个一阶低通滤波器,截止频率设在 10-20Hz。这样速度反馈会平滑很多。
- 启动时的特殊处理: 电机刚启动时,霍尔脉冲还没稳定。这时候用 M 法或 T 法都会算出离谱的速度。我的做法是:启动后的前 3 个脉冲不参与速度计算,等信号稳定了再开始算。
- 注意溢出: T 法测速时,如果电机停了,两个脉冲间隔会无限大。定时器会溢出。一定要做溢出判断,否则速度会突然跳到一个很大的值。
M 法适合高速,T 法适合低速,M-T 法全都要。选哪个,取决于你的电机跑多快、你的 MCU 有多强、你的控制精度要求有多高。没有最好的方法,只有最合适的方法。