用STM32F103和L298N做个蓝牙遥控小车:从编码器测速到PI闭环调参全流程

张开发
2026/4/12 13:12:14 15 分钟阅读

分享文章

用STM32F103和L298N做个蓝牙遥控小车:从编码器测速到PI闭环调参全流程
STM32F103与L298N打造智能蓝牙遥控小车从硬件搭建到闭环调参实战去年夏天我在实验室里折腾第一个自制小车时电机总是要么转得太猛要么干脆不动编码器读数跳得跟心电图似的。直到真正理解了闭环控制中那些微妙的参数调整技巧才让这个小家伙变得服服帖帖。本文将带你完整走一遍这个充满成就感的创造过程——从零开始搭建硬件平台到解决动态环境中的测速难题最后实现用手机APP实时调参的智能控制。1. 硬件选型与系统架构设计1.1 核心部件选型要点选择STM32F103C8T6作为主控是因为它兼具性价比和丰富的外设资源特别适合初学者上手。这颗芯片有72MHz主频的Cortex-M3内核16个定时器通道我们至少需要3个丰富的GPIO和通信接口电机驱动模块的选择往往让新手纠结这里对比L298N和TB6612的关键参数参数L298NTB6612驱动电流2A(峰值)1.2A(连续)工作电压5-35V2.5-13.5V效率较低(需散热片)高(低发热)价格约¥15约¥25虽然TB6612效率更高但L298N的宽电压范围和更强的驱动能力更适合负载变化大的小车项目。记得要给L298N加装散热片我在第一次测试时就因为过热触发了保护。1.2 电路连接实战技巧电源部分是最容易出问题的地方正确的供电方案应该是7-12V锂电池直接接入L298N的电源输入端L298N的5V输出接STM32的VCC需共地蓝牙模块接3.3V电源编码器接线有个坑要注意——必须使用中断引脚如PB6、PB7才能准确捕获高速脉冲。我曾尝试用普通GPIO结果转速超过100RPM时计数就完全不准了。关键提示所有数字地必须单点共地否则电机噪声会导致单片机复位。我的解决方案是在电源入口处加一个100μF电解电容并联0.1μF陶瓷电容。2. 编码器测速的稳定性优化2.1 硬件级抗干扰措施带编码器的直流电机工作时会产生大量电气噪声这些干扰会导致计数器异常跳变转速计算波动大甚至引发单片机死机通过示波器观察原始信号发现两个典型问题边沿存在振铃约200ns空闲电平不稳定解决方法// 在编码器初始化时增加滤波器配置 TIM_ICInitStructure.TIM_ICFilter 0xF; // 设置最大滤波系数 TIM_ICInit(TIM4, TIM_ICInitStructure);同时在硬件上为每根信号线加10K上拉电阻平行走线间铺地线隔离电机电源线套磁环2.2 软件滤波算法实现即使硬件处理得当实际转速计算仍需要软件滤波。我开发了一套自适应滑动窗口算法#define FILTER_WINDOW 5 int16_t speed_buffer[FILTER_WINDOW]; uint8_t buffer_index 0; int16_t Get_FilteredSpeed() { static int32_t sum 0; sum - speed_buffer[buffer_index]; speed_buffer[buffer_index] Get_Encoder(); sum speed_buffer[buffer_index]; buffer_index (buffer_index 1) % FILTER_WINDOW; return sum / FILTER_WINDOW; }这套方案将转速波动从±15RPM降到了±3RPM以内。对于不同减速比的电机需要调整FILTER_WINDOW大小——我的经验值是每100ms采样周期对应3-5个窗口。3. PI控制器的现场调参技巧3.1 参数整定经验法则调试PI控制器时记住这个实用口诀先比例后积分从小到大逐步加超调大了减Kp静差久了加Ki具体操作步骤将Ki设为0Kp从0.01开始每次增加0.02直到出现明显振荡取振荡前值的50%作为基准Kp以Kp/10为初始Ki值逐步增加Ki直到消除静差我的小车最终参数float Kp 0.07; // 比例系数 float Ki 0.1; // 积分系数 float Integral_max 1000; // 积分限幅3.2 动态负载下的自适应策略当小车爬坡或载重变化时固定参数可能失效。我实现了简单的在线调参逻辑if(fabs(ek) 50) { // 大误差时增强比例作用 Kp_temp Kp * 1.5; Ki_temp Ki * 0.8; } else { Kp_temp Kp; Ki_temp Ki; } PWM Kp_temp*ek Ki_temp*Integral;这套策略使小车在突然加载500g重量时速度恢复时间从3秒缩短到1秒内。通过OLED可以实时观察参数变化Speed: 256 RPM Demand: 300 RPM Kp: 0.07 Ki: 0.104. 蓝牙交互与手机控制端开发4.1 自定义通信协议设计为方便手机APP控制我设计了一套简单高效的协议字节功能取值范围0x01速度10-100~1000x02速度-10-100~1000x03Kp0.010.01~1.00x04Kp-0.010.01~1.00x05Ki0.010.01~0.50x06Ki-0.010.01~0.5在STM32端的解析逻辑if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE)) { RxData USART_ReceiveData(USART1); switch(RxData) { case 1: Demand 10; break; case 2: Demand - 10; break; case 3: Kp 0.01; break; // 其他命令处理... } }4.2 安卓APP开发要点使用MIT App Inventor可以快速搭建控制界面关键组件包括BluetoothClient连接HC-05模块Slider调节目标转速Button参数调整按钮Label显示当前状态一个常见问题是安卓设备与蓝牙模块的配对问题解决方法是在APP初始化时执行if (!BluetoothAdapter.getDefaultAdapter().isEnabled()) { // 提示用户开启蓝牙 }我在实际测试中发现当通信间隔小于100ms时容易出现数据丢失。解决方案是在STM32端设置接收超时约150ms手机APP每次发送命令后延迟80ms重要参数采用应答重传机制经过这些优化即使在10米距离内移动控制系统也能保持可靠通信。现在我可以拿着手机在实验室里遛这个小家伙了看着它精准地按照指令加速、减速那种成就感比玩任何遥控车都强烈——毕竟这是从零开始亲手创造的智能机器。

更多文章