)
1. 平衡小车电机测速的核心原理做平衡小车的朋友都知道电机测速是整个系统的眼睛。就像我们骑自行车时需要知道车轮转得多快才能保持平衡一样平衡小车也需要实时掌握电机转速。这里我们用STM32F1的编码器模式来实现这个功能实测下来精度可以达到±2转/分钟完全能满足平衡控制的需求。直流减速电机自带霍尔编码器每转会产生固定数量的脉冲。以常见的GM25-370电机为例电机本身转速12000转/分钟经过34:1的减速箱后输出转速约350转/分钟。编码器每转产生15个脉冲经过减速箱后每输出轴转一圈实际产生510个脉冲15×34。STM32的编码器模式还能进行4倍频最终每转能得到2040个脉冲信号。测速原理很简单定时采集脉冲数量比如每0.1秒读取一次计数器值。假设读到的脉冲数是1020那么转速就是1020÷2040÷0.15转/秒即300转/分钟。这个计算过程会在代码部分详细展开。2. 硬件准备与安全接线2.1 必备硬件清单我用的核心硬件包括STM32F103C8T6最小系统板蓝色药丸板DRV8848电机驱动模块比TB6612电流更大带15线霍尔编码器的GM25-370直流减速电机12V锂电池供电系统0.96寸OLED显示屏I2C接口HC-08蓝牙模块用于无线调试特别要注意电机选择。市面上常见的有光电编码器和霍尔编码器两种霍尔编码器抗干扰能力更强更适合电机应用。编码器线数也不是越多越好15线在减速后已经能提供足够的分辨率。2.2 生死攸关的接线技巧这里我踩过坑曾经因为接线错误烧了三块单片机。关键注意事项电机驱动板的电源GND和信号GND要分开处理。建议只将信号GND与单片机共地大电流的电源GND单独走线。STM32绝对不能直接给电机驱动板供电电机驱动需要单独电源。编码器信号线建议加10K上拉电阻避免信号抖动。电机电源线上一定要加0.1μF的消噪电容。具体接线图示编码器A相接TIM3_CH1PA6编码器B相接TIM3_CH2PA7电机PWM接TIM4_CH1PB6电机方向控制接任意GPIO3. CubeMX关键配置详解3.1 时钟树配置先配置HSE为8MHz外部晶振PLL倍频到72MHz系统时钟。这是STM32F1的黄金频率所有外设都基于这个时钟工作。特别注意APB1总线时钟要设为36MHz因为定时器挂载在这个总线上。3.2 PWM配置TIM4选择TIM4Clock Source选Internal ClockChannel1配置为PWM Generation CH1参数设置Prescaler: 71得到1MHz计数频率Counter Period: 199生成10kHz PWMPulse: 初始值设为0PWM频率建议设置在8-16kHz之间超出这个范围要么会有可闻噪音要么电机响应变慢。3.3 编码器模式配置TIM4这是最关键的配置选择TIM3Combined Channels设为Encoder Mode参数设置Encoder Mode: TI1 and TI24倍频模式Counter Period: 6553516位计数器最大值Polarity: Rising Edge常规配置特别注意Polarity设置不影响计数方向只影响触发边沿。计数方向由编码器相位差决定。3.4 定时器中断配置TIM1配置TIM1产生100ms中断Prescaler: 7199Counter Period: 999 这样得到的定时器频率是72MHz/(71991)/(9991)10Hz4. 代码实现与优化技巧4.1 编码器数据处理// encoder.c void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim htim1) { short counter (short)__HAL_TIM_GET_COUNTER(htim3); __HAL_TIM_SET_COUNTER(htim3, 0); // 计算转速转/秒 float speed (float)counter / 2040.0f / 0.1f; // OLED显示 OLED_ShowDecimal(0, 4, speed, 2, 2, 12, 0); } }这段代码有三个优化点使用short类型强制转换处理计数器溢出2040是4倍频后的每转脉冲数510×40.1是定时器中断周期4.2 电机控制实现// motor.c void Motor_SetSpeed(uint8_t percentage) { uint16_t pulse 7200 * percentage / 100; // ARR7200 __HAL_TIM_SET_COMPARE(htim4, TIM_CHANNEL_1, pulse); }建议做成开环速度曲线不同电压下电机特性不同可以实测后建立速度-占空比对照表。4.3 抗干扰处理实际测试中发现编码器会受到电机干扰加入以下滤波代码// 在定时器中断中加入移动平均滤波 #define FILTER_SIZE 5 static float speed_buffer[FILTER_SIZE] {0}; static uint8_t filter_index 0; speed_buffer[filter_index] (float)counter / 2040.0f / 0.1f; filter_index (filter_index 1) % FILTER_SIZE; float filtered_speed 0; for(int i0; iFILTER_SIZE; i) { filtered_speed speed_buffer[i]; } filtered_speed / FILTER_SIZE;5. 实测数据与常见问题5.1 性能测试结果在不同PWM占空比下测得转速占空比实测转速(rpm)理论值(rpm)误差20%6870-2.8%40%1421401.4%60%208210-0.9%80%278280-0.7%100%348350-0.5%5.2 常见故障排查计数器值不变化检查编码器供电通常是5V用示波器看PA6/PA7是否有波形确认CubeMX配置了编码器模式转速显示跳动大增加软件滤波检查编码器连接线是否太长在编码器信号线加100Ω电阻和100pF电容滤波电机转动但转速显示为零检查编码器方向是否接反尝试交换A相B相接线6. 进阶应用为PID控制做准备测速最终是为PID控制服务的这里先打好基础。后续PID需要稳定的速度采样本文已实现合适的控制周期建议5-10ms速度-占空比转换关系建议先建立电机特性表记录不同PWM下的空载转速和带载转速这对PID参数整定很有帮助。在我的平衡小车项目中这套测速方案最终实现了±1rpm的稳定控制精度。