1. 霍尔编码器基础认知第一次接触霍尔编码器时我盯着那个带磁环的小玩意儿琢磨了半天——这货怎么就能把电机转速变成电信号呢后来拆了个报废的JGB37-520电机才恍然大悟。这种磁式编码器核心就两部分固定在电机轴上的多极磁环码盘以及检测磁场变化的霍尔元件。当电机旋转时霍尔元件会输出脉冲信号就像用电子眼数轮胎转了几圈。线数这个概念特别容易搞混。以常见的11线编码器为例不是指有11根电线而是码盘转一圈会产生11个脉冲信号。但实际使用时要考虑减速比比如1:30的减速电机电机输出轴转一圈码盘其实转了30圈最终每转实际脉冲数11×30330PPRPulse Per Revolution。这里有个坑A、B相各输出330个脉冲不是两相合计330个新手常在这里栽跟头。判断旋转方向靠的是A、B相的相位差。正转时A相上升沿对应B相高电平反转时则是低电平。用示波器看波形特别直观两个方波就像跳交谊舞一样正转时A相领舞反转时B相主动。这个特性在做小车差速转向时特别有用后面PID控制就靠它分辨左右轮转向。2. 三种测速算法原理拆解2.1 M法测速高频采样法去年调赛车项目时就吃过亏——低速时速度显示像抽风一样乱跳。M法原理简单粗暴在固定时间窗口比如100ms内数脉冲个数。假设100ms内捕获到66个脉冲编码器总分辨率330PPR那么转速66/(330×0.1)2转/秒。就像用秒表数汽车轮胎转过的辐条数。但这个方法在低速时精度暴跌。当转速低于10RPM时100ms内可能只捕获到1-2个脉冲±1的计数误差会导致速度显示50%-100%的波动。实测发现对于JGB37-520电机M法在200RPM以上时误差3%但低于50RPM时误差可能超过20%。2.2 T法测速周期测量法后来做机械臂项目时换了思路。T法不关心固定时间内的脉冲数而是测量两个脉冲之间的时间间隔。用1MHz的高频时钟作为时间尺子假设测得两个脉冲间隔为5000个时钟周期那么转速1MHz/(5000×330)≈0.606转/秒。这就像用高倍速摄像机记录辐条经过的时间。但问题来了电机转速越高脉冲间隔越短能记录的高频时钟数越少。当转速超过1000RPM时1MHz时钟可能只记录到几十个周期±1的误差就变得不可忽视。实测数据显示T法在50RPM以下精度惊人误差1%但超过500RPM后误差曲线就开始飙升。2.3 M/T法测速混合测量法现在做平衡小车终于找到了终极方案。M/T法就像智能手表测心率既数脉搏次数又记录持续时间。具体实现要开两个定时器一个用于脉冲计数M另一个用于高频时钟计时T。当检测到第M0个脉冲时记录此时的高频时钟计数M1。转速公式为n (M0×F0)/(M1×C)其中F0是高频时钟频率C是编码器分辨率。实测在10-1000RPM范围内误差能控制在2%以内。不过要注意中断响应时间的影响我在STM32上测试时把高频时钟配置在72MHz脉冲计数用硬件编码器模式这样即使1万转/分的高速也能hold住。3. 硬件实现关键细节3.1 信号调理电路被电机噪声坑过好几次后现在我的PCB上必加这些防护10kΩ上拉电阻编码器输出一般是开漏100nF去耦电容贴片陶瓷电容最靠谱74HC14施密特触发器整形波形效果拔群TVS二极管防反接和浪涌特别提醒长距离传输时要用双绞线曾经因为用了普通杜邦线脉冲计数莫名其妙丢数调试到怀疑人生。3.2 定时器配置技巧以STM32F4为例要榨干硬件性能得这么玩// 编码器接口模式配置 TIM_Encoder_InitTypeDef encoder_config { .EncoderMode TIM_ENCODERMODE_TI12, // 4倍频模式 .IC1Polarity TIM_ICPOLARITY_RISING, .IC2Polarity TIM_ICPOLARITY_RISING, .IC1Filter 10, // 抗抖动滤波 .IC2Filter 10 }; TIM_EncoderInterfaceConfig(TIM3, encoder_config); // 高频时钟定时器配置 TIM_TimeBaseInitTypeDef timer_config { .Prescaler 0, .CounterMode TIM_COUNTERMODE_UP, .Period 0xFFFF, .ClockDivision TIM_CLOCKDIVISION_DIV1 }; TIM_TimeBaseInit(TIM4, timer_config); TIM_SetClockSource(TIM4, TIM_CLOCKSOURCE_INTERNAL);3.3 速度计算优化直接浮点运算会拖慢系统我用Q15定点数优化int32_t Calc_Speed(uint16_t M0, uint16_t M1) { const int32_t K (int32_t)((1.0f * F0 / C) * 32768); // Q15格式系数 return (M0 * K) / M1; // 返回RPM值 }对于低速工况还会加一阶滞后滤波speed_filtered 0.9 * speed_filtered 0.1 * speed_raw;4. 实测数据对比用三种方法测试JGB37-520电机的数据转速(RPM)M法误差T法误差M/T法误差20±18%±0.8%±1.2%100±5%±1.5%±1.8%500±2%±6%±1.5%1000±1.5%±15%±2%特别要注意的是当电机启停瞬间M/T法的抗干扰能力最强。上周测试时故意用手骤停电机M法显示有200ms的异常波动T法直接溢出而M/T法只产生约8%的瞬时偏差。5. PID闭环控制实战拿到精准的速度反馈后电机控制就像开了天眼。我的PID参数整定心得先调速度环PI控制// Kp0.12, Ki0.003 适用于12V供电的520电机 error target_speed - actual_speed; integral error * dt; output Kp * error Ki * integral;再加入位置环P控制position_error target_position - encoder_count; speed_target Kp_position * position_error;最后加前馈补偿对付负载突变output 0.3 * target_speed; // 前馈系数调参时一定要用阶跃响应观察好的曲线像缓坡上山超调10%糟糕的曲线像过山车来回震荡。最近发现粒子群算法自动整定PID参数效果不错准备下期专门讲讲这个黑科技。