从玩具车到平衡小车手把手教你用STM32F103的编码器实现直流电机精准测速与PI稳速周末整理房间时翻出一台旧玩具车拆开外壳发现核心部件竟是两个普通的直流电机。这让我萌生了一个想法能否用STM32F103这颗性价比极高的MCU配合编码器将其改造成能精确控制转速的智能驱动模块经过三周的反复调试最终实现了在1-1000RPM范围内误差小于±2%的稳速控制甚至为后续平衡小车项目打下了基础。本文将完整分享从硬件选型到算法调参的全过程实战经验。1. 硬件架构设计与关键器件选型1.1 电机与编码器的黄金组合市面常见的直流电机主要分两种带编码器的伺服电机和普通碳刷电机。前者集成度高但价格昂贵约50-200元后者成本低廉5-20元却需要外接编码器。基于DIY的灵活性考虑我选择了JGA25-370电机600线增量式编码器的方案整套成本控制在30元以内。编码器接线时需特别注意A/B相输出建议使用带屏蔽的双绞线电源端并联0.1μF陶瓷电容消除高频干扰信号线串联100Ω电阻可抑制振铃现象实际测试中发现未加滤波的编码器信号在电机启动时会出现毛刺导致速度计算异常1.2 STM32最小系统搭建使用STM32F103C8T6核心板时需要特别关注TIM定时器的编码器接口资源分配。以下是各外设的推荐配置外设功能引脚分配备注电机PWM驱动PA8(TIM1_CH1)需配置互补输出编码器接口A相PB6(TIM4_CH1)必须支持编码器模式编码器接口B相PB7(TIM4_CH2)需配置上拉电阻调试串口PA9/PA10(USART1)建议波特率设为1152002. 编码器信号处理与速度计算2.1 四倍频计数实现原理600线编码器理论上每转产生2400个脉冲四倍频计数STM32的TIM4配置代码如下void Encoder_Init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_ICInitTypeDef TIM_ICInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); TIM_TimeBaseStructInit(TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Period 0xFFFF; // 16位最大值 TIM_TimeBaseStructure.TIM_Prescaler 0; TIM_TimeBaseStructure.TIM_ClockDivision 0; TIM_TimeBaseInit(TIM4, TIM_TimeBaseStructure); TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising); TIM_ICStructInit(TIM_ICInitStructure); TIM_ICInitStructure.TIM_ICFilter 6; // 设置输入滤波器 TIM_ICInit(TIM4, TIM_ICInitStructure); TIM_Cmd(TIM4, ENABLE); }2.2 动态频率测量法固定周期读取计数器值会导致低速时精度下降。我采用动态测量脉冲间隔时间的方法在100RPM以下精度提升明显配置TIM2为外部时钟模式时钟源选择编码器A相开启输入捕获中断测量相邻上升沿间隔速度计算公式RPM (60*1e6)/(脉冲间隔(μs)*2400)实测数据对比方法100RPM误差10RPM误差固定周期法±1.2%±15%动态测量法±0.8%±3.5%3. PI控制器设计与参数整定3.1 离散化PI算法实现为避免浮点运算消耗资源采用Q15格式定点数实现#define Kp_Q15 (int16_t)(0.6 * 32768) // Q15格式的Kp #define Ki_Q15 (int16_t)(0.03 * 32768) // Q15格式的Ki int32_t PI_Controller(int16_t target, int16_t feedback) { static int32_t integral 0; int16_t error target - feedback; integral Ki_Q15 * error; integral (integral 3276700) ? 3276700 : integral; // 抗积分饱和 integral (integral -3276700) ? -3276700 : integral; return (Kp_Q15 * error integral) 15; }3.2 参数调试实战技巧通过阶跃响应法调试参数时发现几个关键现象仅P控制转速会出现稳态误差约5-8%I值过大启动时电机明显抖动最佳响应曲线约3个振荡周期后达到稳定推荐调试步骤先将Ki设为0逐步增大Kp直到出现等幅振荡取振荡时Kp值的60%作为最终P参数缓慢增加Ki直到消除静差且无明显超调4. 抗干扰优化与系统集成4.1 软件滤波方案对比测试了三种滤波算法对速度突变的响应滤波方式延迟时间(ms)抗干扰能力滑动平均35★★☆☆☆一阶低通20★★★☆☆卡尔曼滤波15★★★★☆最终选择改进型滑动平均滤波动态调整窗口大小5-20个点自动剔除异常值±3σ原则4.2 完整系统工作流程上电初始化PWM(20kHz)和编码器接口每10ms执行一次读取编码器值计算实时转速运行PI控制器更新PWM占空比通过串口发送调试数据紧急制动检测if(current_rpm target_rpm * 1.5) { PWM_SetDuty(0); // 过速保护 fault_flag 1; }在最终测试中这套系统成功实现了空载到满载500g转速波动±2%斜坡行驶时自动补偿负载变化急停后1.5秒内恢复设定速度移植到平衡小车底盘时发现电机一致性对控制效果影响很大。后来通过参数自动标定功能解决了这个问题让两个电机分别以不同占空比运行记录达到相同转速时的PWM值后续控制时进行动态补偿。