
那台无人机调试到深夜客户反复说“电机转速和上位机对不上”我盯着示波器里的霍尔波形看了十分钟最后发现根因特别低级——极对数设错了。三相无刷直流电机的转速计算本身不复杂真正麻烦的是它牵扯到电气频率、机械转速、极对数、换相频率这一串概念任何一个环节理解偏了算出来的数都会差得离谱。这篇内容主要写给正在做无刷电机驱动、电调、机器人关节模组或者只是想把电机转速测准的工程师。我会从最底层的换算逻辑讲起把有感方案和无感方案分别怎么算转速讲清楚再结合我实际踩过的坑把滤波相移、测量滞后、PWM非线性这些容易翻车的地方一次说透。最后给出一段可以直接移植的STM32计算代码和一张问题排查表。1. 无刷直流电机转速计算的底层逻辑1.1 电转速与机械转速极对数才是关键很多第一次接触无刷电机的人都会犯一个直觉错误以为电机转一圈霍尔信号就输出一个完整周期或者以为控制器换相六次就是转一圈。实际上这两者对不上原因是转子和定子磁场之间存在“极对数”这个比例关系。无刷直流电机转子上的永磁体按N-S交替排列最少一对极也就是一个N一个S常见的有2对极、4对极、甚至7对极、14对极。所谓极对数就是转子磁极对的数量通常用p表示。电机的三相绕组通入电流后定子产生旋转磁场这个磁场要跟着转子磁极“对位”转子每转过一对磁极电角度正好走完360度也就是一个完整的电气周期。所以转子机械转一圈电气周期数等于极对数p。这句话是整个转速计算的基石。举个例子一个电机是4对极也就是转子表面有8颗磁钢转子每转一圈任意一相的反电动势波形会输出4个完整周期任意一个霍尔传感器也会输出4个完整脉冲周期。你用示波器看到霍尔波形频率是200Hz那只能说明电气频率是200Hz机械转速还要除以极对数。这还不算完六步换相法里一个电气周期包含6个换相状态每个状态持续60度电角度。所以换相频率反推转速时还要在极对数的基础上再除一次6。我见过不少人在示波器上数换相频率然后直接除以极对数算转速结果差了6倍排查半天找不到原因。1.2 电气频率从哪来反电动势与霍尔信号既然知道了极对数下一步就是获得电气频率。工程上通常有两个来源一个是位置传感器最常见的是霍尔传感器另一个是反电动势。有传感器的方案里霍尔元件安装在定子上三个霍尔传感器间隔120度电角度分布。转子永磁体转过霍尔元件时霍尔输出高低电平三个霍尔信号组合出6种状态正好对应六步换相的6个扇区。任何一路霍尔信号的一个完整周期就是转子转过一对磁极的时间也就是一个电气周期。无感方案里电气频率从反电动势提取。电机运转时没有通电的那一相绕组会因为转子磁场切割而感应出反电动势这个反电动势的频率就是电气频率过零检测法就是利用这个信号来锁定换相时机同时也顺带得到转速信息。这里有一个容易混淆的概念反电动势的“过零”和霍尔信号跳变不是同一个时刻。过零发生在反电动势波形从正到负或从负到正的零点位置而换相时刻通常在过零之后延迟30度电角度。两者差着30度如果拿过零时刻直接当换相时刻电机会废掉一部分扭矩。这个话题后面讲无感方案时再展开。1.3 统一的转速换算公式把上面的逻辑压缩成公式最能说明问题n 60 × f_e / p这里n是机械转速单位rpmf_e是电气频率单位Hzp是极对数。这个公式适用于所有通过电气信号测转速的场景唯一要做的是保证f_e确实代表电气频率。如果是用霍尔信号测一路霍尔的频率就是这个f_e如果是检测到换相频率f_commutation由于一个电气周期内有6次换相则f_e f_commutation / 6转速公式变为n 60 × f_commutation / (6 × p) 10 × f_commutation / p为什么是60而不是别的数因为转速单位是“每分钟转动次数”而频率单位是“每秒的周期数”每秒变成每分钟要乘60。搞懂这个因次关系公式就不容易记混。还有一个很多人忽略的点极对数p要从电机铭牌或实际极数确认不能靠猜。有些国产电机标称功率相同但内部极数可以有2对极和3对极两种版本极对数设错是转速数值成比例偏差的最大原因。2. 有感方案霍尔传感器频率算转速2.1 霍尔信号频率的测量方法有传感器方案里霍尔信号就是最直接的转速信息来源。工程上测量一路霍尔信号的频率常用的方法大概有三种测周期法、测频率法、以及两者的混合M/T法。测周期法原理是捕获相邻两个上升沿或下降沿的时间间隔记作T_e那么电气频率f_e 1/T_e转速n 60 / (T_e × p)。这种方法的优势是低转速下精度高因为转速低时周期长计时分辨率损失小缺点是转速高时周期短如果定时器时钟不够快量化误差会非常明显。比如定时器时钟1MHz测一个20000rpm、2对极的电机电气周期是1.5ms1MHz时钟下量化误差占比不到0.1%没问题但如果转速到60000rpm电气周期只剩0.5ms误差占比就上来了。测频率法是在固定时间窗口内对霍尔脉冲计数。比如每10ms统计一路霍尔的上升沿数量M那么f_e M / 0.01转速n 60M / (0.01 × p)。这个方法的优势是高转速下计数多、精度高缺点是低转速时一个窗口内可能只有几个脉冲甚至一个都没有一个脉冲的误差就能导致转速值跳变。比如电机的极对数比较多低速时霍尔频率本来就低固定窗口测频法几乎没法用。实际产品里我用得最多的是M/T法高速时以计数为主低速时以测周期为主两者自动切换。M/T法在商用变频器和伺服驱动器里非常常见STM32的定时器输入捕获加外部时钟计数一套配置就能实现。2.2 一个完整的实测换算过程拿我之前做过的一个C型无刷直流风机控制器来说电机铭牌标注是8颗磁钢那就是4对极p4。霍尔传感器A的波形送到STM32定时器的输入捕获通道用两个上升沿间的差值算出周期。一个关键配置确保定时器时钟足够快。我当时用TIM2内部时钟72MHz预分频设为72也就是实际计数时钟1MHz一个计数单位1微秒。捕获到两次上升沿的计数值差假设是4500那电气周期就是4500微秒也就是4.5ms电频率f_e 1 / 0.0045 ≈ 222.22Hz。代入公式转速n 60 × 222.22 / 4 3333.33rpm。用霍尔信号的另一路做交叉验证也可以。三路霍尔信号彼此相差120度电角度频率相同只是相位不同用哪一路算结果都一样。但需要注意如果霍尔传感器安装不对称或者霍尔板焊接有偏差三路的占空比可能不是标准的50%这时候用上升沿到上升沿比用固定电平滤波后的平均值更可靠。我还会额外算一个换相频率来核对。六步换相下每60度电角度换相一次电频率222.22Hz时换相周期4500微秒/6750微秒即换相频率约1.333kHz。如果软件里统计的是换相次数转速n 10 × 1333.33 / 4 3333.33rpm结果一致。2.3 三种测频方法怎么选选测速方法前先明确转速范围。低速为主的项目优先测周期法高速为主的项目优先测频率法宽调速范围用M/T法。我在实践中总结了一个简单的经验公式来确定切换阈值。设定时器计数时钟频率为F_clk低速时最小可接受脉冲计数为N_min比如N_min3则测频法适合电气频率大于f_low N_min / ΔT的情况ΔT是固定窗口时间。如果ΔT10msN_min3则f_low300Hz对应4对极电机转速n60×300/44500rpm。低于4500rpm就应该切到测周期法。还要注意霍尔信号往往不是完美方波。电机低速转时霍尔边缘抖动会带来周期测量的随机误差我通常会在软件里对周期做一阶低通滤波或者连续采5次去掉最大最小取平均。过度滤波会让转速响应变慢后面闭环会很难调所以滤波系数要跟控制周期一起考虑。3. 无感方案从反电动势计算转速的实战细节3.1 无感转速的来源与还原思路无感方案没有霍尔传感器电气频率只能从反电动势提取。反电动势幅度与转速成正比转速太低时反电动势信号淹没在噪声里因此无感方案普遍要处理启动阶段。启动时用强制换相或开环加速等反电动势足够大再切入闭环。转速计算的反电动势来源有两种做法。一种是用电压比较器直接产生方波比较器一端接悬空相反电动势另一端接虚拟中点电压输出方波频率就是电气频率另一种是采用ADC采样悬空相电压在软件里做过零检测通过过零事件之间的时间间隔计算电气周期。ADC采样方式的转速计算逻辑和霍尔测周期法几乎一样检测到两次反电动势过零记录时间差Δt_zc这个时间差对应180度电角度电气周期T_e 2 × Δt_zc所以转速n 60 / (2 × Δt_zc × p)。这个公式在启动切入闭环后特别好用因为过零检测本来就是闭环换相的一部分等于是顺带测转速。3.2 过零检测的滤波相移陷阱无感方案最大的坑是滤波相移。反电动势叠加PWM开关噪声通常需要RC低通滤波但任何滤波器都会让信号产生相位延迟。过零检测不只有电气频率信息过零时刻还直接决定换相点。如果滤波相移过大换相延迟会让电流和反电动势错开效率下降转速测量值也会系统性偏移。我踩过一次典型的坑。某次项目里RC低通滤波器时间常数取大了结果反电动势过零检测到的周期比真实周期略长转速显示值比实际低大概2%。起初以为是机械负载变大排查了很久才发现是滤波电容导致的相移。解决思路有两个方向。一是在软件里补偿相移提前一个固定角度触发中断二是在过零检测后使用独立的中断时间戳不做滤波处理只有转速计算用的周期数据才做平滑。后者更干净因为它把换相实时性和转速计算平滑分开了。如果一定要在硬件上游滤波就必须精确计算RC的相频特性在软件里做角度补偿而不是拍脑袋给个固定提前量。还有一点PWM-ON窗口和PWM-OFF窗口的反电动势采样效果完全不同。PWM导通期间母线电压加在绕组上反电动势被母线电压覆盖很多控制器选择在PWM-OFF期间采样。这意味着采样窗口本身受占空比影响占空比很小时可利用的采样时间极短过零检测位置会不稳定转速计算值也会随之抖动。所以无感方案里稳定转速计算的一个重要前提是PWM调制策略设计得足够好。3.3 启动开环与闭环切换时的转速处理无感BLDC的启动通常分三段预定位、强制换相加速、闭环切换。预定位阶段电机不转没有转速强制换相阶段转速由换相频率决定实际上是开环控制器按既定加速曲线逐步提高换相频率当转速上升到反电动势足够可靠再切换到过零检测闭环。但切换到闭环的瞬间开环设定的转速和闭环检测到的实际转速往往不匹配。如果开环换相频率给高了闭环切入后电流会瞬间反向出现顿挫给低了电机又可能失步。我通常的做法是在开环阶段软件记录当前换相频率闭环切换的初始电气周期直接采用开环最后几次换相的平均周期等过零检测稳定后再逐渐让转速计算接管。这样转速值在切换时刻不会跳变后面PI调节器也不会因为突变而震荡。这个阶段还有个小技巧就是不要把过零检测的周期数据直接送进转速控制器而是先做3到5次的中值滤波。切换瞬间的反电动势波形毛刺很多中值滤波比平均值滤波更能耐受异常尖峰。4. 转速闭环控制里的几个关键坑4.1 KV值只能做估算不能当真理很多工程师拿到电机先看KV值然后用KV值乘电压估算转速。这在无刷电机选型和粗略估算时没问题但放进闭环控制里就太天真了。KV值定义是空载转速除以供电电压单位通常写作RPM/V。它本质上由反电动势常数决定反电动势常数Ke的物理单位是V/(rad/s)两者换算关系是KV_rpm/V 60 / (2π × Ke)。但KV值不包含负载影响带载后由于绕组电阻和电流产生的压降实际转速会明显低于KV值估算。更麻烦的是同一颗电机在不同电压下由于PWM占空比、死区效应和续流方式不同KV值对应的空载转速也不完全线性。所以KV值只适合算候选电机的最大转速是否满足需求不能作为闭环里的精确转速模型。真要闭环就得在系统里实时测量霍尔或反电动势频率用它作为转速反馈。4.2 PWM调压带来的转速非线性无刷电机的PWM调速本质上是调节平均电压进而调节反电动势平衡点最终实现调速。但PWM占空比和转速之间不是简单的线性对应原因有两个。第一绕组电阻上的压降与电流成正比负载越大占空比增加的效果越被电阻压降吃掉。同一个占空比空载和满载转速可能差很多。第二死区和续流二极管的导通压降在小占空比时占比很大造成低速段转速和占空比关系明显弯曲。表现在转速计算上就是如果你用“占空比×电压→KV值→转速”这种前馈方式去预测转速误差会非常大。所以真正可靠的转速闭环都必须有反馈基于霍尔或反电动势频率把实际转速拉回来。前馈只用来做初值。4.3 测量滞后与PI参数的匹配转速计算天然存在滞后。测周期法至少需要一个电气周期才更新一次转速转速升高时周期变短一次更新的滞后反而小但低速时一次更新可能要好几十毫秒。如果控制周期比转速更新周期快很多PI调节器看到的转速信号就像是阶梯状的。这会引发一个典型问题PI参数调快了低速时转速反馈跟不上输出抖动PI调慢了高速时又觉得响应迟钝。我建议的做法是让转速控制器的执行周期和转速更新的周期一致或者在更新间隙用上一个有效值保持不要让控制程序按固定频率去采样一个还没有更新的变量。另外一个容易被忽略的点测周期法在低速时单次测量的量化误差在比例上很大如果直接喂给PI电流会跟着抖动。一块低转速下把霍尔周期连续采集4次取平均值再更新转速能显著减少抖动但代价是滞后变大。滞后和噪声的取舍没有标准答案取决于负载的转动惯量大小。5. 用STM32实现转速计算的参考实践5.1 测速模块的完整流程下面这套流程我在STM32F103和F407上都跑过核心思路是用定时器输入捕获测量霍尔周期同时用另一路定时器做1ms周期任务来更新转速和控制参数。霍尔A相接到定时器的CH1通道配置为上升沿捕获同时打开定时器更新中断溢出时记录溢出次数防止捕获值翻转。收到捕获中断后计算本次捕获值加溢出补偿再减去上次捕获值得到电气周期。这个差值乘以定时器计数周期就是电气周期时间再代入转速公式。对于无感方案只需要把“捕获中断”换成“过零检测中断”中断里记录的时间戳用于计算180度电角度周期逻辑完全一致。#define TIM_CLK_HZ 1000000 // 1MHz计数时钟预分频72 #define POLE_PAIRS 4 // 电机极对数 volatile uint32_t g_last_edge 0; volatile uint32_t g_pulse_ticks 0; void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim-Instance TIM2) { uint32_t now __HAL_TIM_GET_COUNTER(htim2); g_pulse_ticks now - g_last_edge; g_last_edge now; } } float calc_rpm_from_ticks(uint32_t ticks_us) { if (ticks_us 0) return 0.0f; float f_elec_hz 1000000.0f / (float)ticks_us; return 60.0f * f_elec_hz / (float)POLE_PAIRS; }这个例子里如果计算得到的g_pulse_ticks是4500那么calc_rpm_from_ticks返回约3333.3rpm和前面推算的值一致。需要注意的是捕获差值可能出现定时器溢出翻转正式工程里必须处理溢出简单做法是在更新中断里累加一个溢出计数计算差值时把溢出补偿进去。5.2 转速计算参数标定代码写完后第一件事不是上电机而是用信号发生器模拟霍尔信号做标定。给定时器输入一个频率已知的方波比如200Hz看软件输出的转速是否正确。4对极电机200Hz电气频率对应3000rpm如果显示不对先查极对数宏再查定时器时钟配置。这个步骤能帮你把软件和硬件问题分开。如果信号发生器下测出来准确上电机后转速依然偏差那就是霍尔安装位置、机械极数确认或者反电动势相移的问题。我还会在标定时做一组对比数据用光电转速计测实际机械转速和软件显示的转速比较。偏差在1%以内算正常超过2%就要怀疑极对数设错、滤波器相移或者霍尔边缘毛刺导致的周期抖动。5.3 常见问题速查表下面是我这几年来做无刷电机转速模块碰到的高频问题直接整理成表方便排查时对着看。问题现象可能原因解决思路转速显示是实际值的2倍或一半极对数设置错误确认电机磁钢数极对数磁钢数/2转速显示是实际值的6倍或六分之一误把换相频率当电气频率换相频率要除以6再代入公式低速转速值跳动很大测频法窗口内脉冲太少切换到测周期法或增加窗口时间高速转速偏小定时器溢出未补偿捕获中断里补上定时器溢出计数无感方案转速有固定比例偏差反电动势滤波相移软件补偿角度或改用未滤波的时间戳切换闭环瞬间转速突变开环与闭环周期不衔接用开环最后几次换相平均值做初值转速反馈恒为零捕获引脚没配置或霍尔电源问题先用示波器确认霍尔信号有无占空比不变但转速变动霍尔写盘不对称、占空比抖动用上升沿周期算转速软件做中值滤波最后再分享一个小技巧无论有感还是无感方案转速计算模块都要独立于换相逻辑之外单独用时间戳记录事件间隔不要在主控制循环里临时读取计数器算周期。把测速做成一个完全由中断驱动的“黑盒”只对外输出更新后的转速值后续调试会省非常多的时间。