尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

STM32智能小车三合一实战:遥控避障循迹设计与踩坑记录

STM32智能小车三合一实战:遥控避障循迹设计与踩坑记录 简介基于STM32F103系列单片机的智能小车工程包给出了遥控控制、避障、循迹三种经典控制模式的完整实现适合嵌入式学习者、电子竞赛队伍以及毕业设计参考。压缩包共466个文件约8.94MB除h/c源码工程外还包含Keil工程配置、hex烧录文件以及map/lst等编译调试文件便于直接打开验证和二次开发。已有11770人浏览学习实用性得到较多认可。项目内拆分出三个独立工程分别对应三种控制模式可对照学习不同功能模块的编程思路代码涉及L298N电机驱动、传感器检测、PWM调速等关键环节有助于快速掌握单片机控车的基本方法与调试技巧。 很多初学者拿到STM32最小系统板后的第一个实战项目就是做智能小车。遥控控制、避障、循迹这三个功能拆开看都不算难但把它们放到同一辆车上让三种模式稳定切换、互不干扰才是真正考验基本功的地方。这篇文章我直接以STM32F103ZET6为核心把一套能跑通的智能小车方案完整梳理一遍硬件怎么选、三个功能怎么共存、循迹避障的核心逻辑怎么写、踩过哪些坑尽量把我实际操作中的经验都写出来给正在做课程设计或者想入门嵌入式的朋友一个可复现的参考。1. 整车硬件选型基础版配置与替代方案1.1 主控选型为什么推荐F103ZET6很多人纠结用STM32F103C8T6还是ZET6。我的建议很直接如果是课程设计或者比赛ZET6会更省心。原因不是性能差多少而是引脚数量和调试便利性。C8T6只有48脚做小车要接电机驱动、蓝牙、超声波、五路循迹、OLED屏幕、按键引脚会被占得满满当当走线乱不说后期想加一个功能还得飞线或者改板子。ZET6是144脚Flash有512KBRAM有64KB外设资源非常充裕。多出来的引脚哪怕只当扩展IO用也能减少很多布局上的麻烦。更重要的是ZET6的FSMC接口可以接TFTLCD屏如果后续想做可视化菜单或者显示调试波形这个优势会非常明显。价格上ZET6比C8T6贵十几块钱但省下的折腾时间远超这点成本。1.2 电机驱动与供电电流和电压必须一起算电机驱动我用的是TB6612FNG而不是很多教程里推荐的L298N。TB6612的峰值电流是3.2A额定电流1.2A驱动普通TT马达或者带减速箱的直流电机完全够用。关键是它内部是MOSFET管压降小发热低不需要像L298N那样拖个大散热片。L298N的压降能达到2V以上电池电压稍微低一点电机转速就明显下降这个差距在长时间跑动时特别明显。供电这块是最容易翻车的。我的方案是两节18650锂电池串联标称7.4V接TB6612的VM电机电源引脚同时引一路出来接LM2596降压模块降到5V给STM32、蓝牙模块和循迹传感器供电。注意千万不要把7.4V直接灌进STM32的5V引脚也尽量不要用AMS1117-3.3线性降压因为从7.4V降到3.3V时压差太大电流一上来芯片会烫得厉害。提示电池电压在满电时能到8.4V不要用7.4V这个参数去算所有器件的耐压最好预留1V左右的余量。1.3 传感器选型循迹、避障、遥控各自用啥循迹我选的是五路红外反射传感器型号一般是TCRT5000的模组。五路相比三路的优势很明显检测范围更宽直线跑的时候有中间三路做稳定参考过十字路口和大角度弯道时五路能提供更完整的黑线位置信息程序判断的时候容错空间大很多。避障选的是HC-SR04超声波模块加三个红外避障传感器。超声波负责远距离探测测距范围2cm到400cm用于判断前方障碍物距离红外避障传感器负责近距离的左右两侧检测防止超声波盲区里已经贴近侧面的障碍物撞上去。遥控方面用HC-05蓝牙模块手机APP通过串口发指令成本低、协议简单入门阶段够用了。如果有比赛需求后面可以换成2.4G无线模块或者NRF24L01但调试思路是一样的。2. 三种功能如何共存状态机与优先级设计2.1 为什么不建议用“三个if叠一起”的方案很多第一次做小车的朋友会这样写先检测蓝牙有没有数据有就去执行遥控没有数据就检测避障避障没触发就去循迹。这样确实能跑但问题非常明显。蓝牙遥控的时候如果前面有障碍物程序会跳到避障逻辑里遥控就失灵了小车会因为无法后退而卡在墙角。循迹跑到一半蓝牙发一个转弯指令如果两个功能同时抢占电机控制电机PWM会被反复修改小车会出现明显抖动。根源在于三个功能没有明确的主次关系也没有说清楚“什么时候该听谁的”。智能小车本质上是一个多输入、单输出的控制系统所有传感器输入最终要汇聚成“电机怎么转”这一个输出所以必须有一个仲裁机制。2.2 状态机框架与切换规则我采用的状态机设计是这样的系统上电后默认进入“待机模式”等待遥控器发送模式切换指令收到指令后进入对应模式。遥控模式优先级最高避障模式次之循迹模式只在没有遥控指令、且避障没有触发时运行。用伪代码来表达就是typedef enum { MODE_REMOTE, MODE_OBSTACLE, MODE_TRACKING } CarMode; CarMode currentMode MODE_REMOTE; while (1) { uint8_t cmd get_ble_cmd(); // 非阻塞读取蓝牙数据 if (cmd ! 0xFF) { currentMode parseMode(cmd); } if (currentMode MODE_REMOTE) { remote_control(); } else if (currentMode MODE_OBSTACLE) { obstacle_avoidance(); } else { line_tracking(); } }一个小技巧是蓝牙指令不要直接执行而是先解析成目标模式再执行。比如发送字符“A”进入避障模式“B”进入循迹模式“C”返回遥控模式这样遥控、避障、循迹之间可以随时主动切换而不是靠“有没有数据”来猜。实测下来这种显式切换比自动抢占的方式稳定得多至少不会出现“你明明想让它循迹它却因为蓝牙残留数据停在原地”的尴尬情况。3. 循迹的核心逻辑五路传感器与PID差速3.1 五路模块怎么读、怎么校准五路循迹传感器每个探头输出的是数字量还是模拟量取决于模组型号。我用的模组带比较器输出0或1黑色线检测到低电平白色地面检测到高电平。读取方式就是五个GPIO直接读不需要ADC。上电第一时间要先做校准把小车放在全白的地面上读一遍五个探头的输出值存为基准再放在全黑或者黑线上读一遍。这样即使环境光线变化也能通过阈值判断当前输出是高还是低。摆放位置有个细节五路探头要均匀分布在车底中央中间一路对准车头中轴线两边的探头间距要跟黑线宽度匹配。我的黑线宽度是2cm探头间距设计成1.5cm这样中间三路能够稳稳压住黑线左右两路检测偏离。如果间距太大会出现小车在黑线上蛇形走位如果太小直线行驶时左右两路会频繁误触发。3.2 从if-else到PID差速转向的平滑处理新手写法通常是左偏就右转右偏就左转全偏就掉头。这种二值控制的问题在于转向是跳变的小车速度稍微快一点就会冲过弯道。我的做法是引入PID偏差计算先根据五路传感器的状态映射出一个偏差量errorint error_map[32] { // 五路输出组合 - 偏差值0表示正中 // 例如 0x18左数第二三路压线对应 -2 // 0x0C右数第二三路压线对应 2 };然后对偏差做PID计算输出转向修正量int speed_left BASE_SPEED PID_Calculate(error); int speed_right BASE_SPEED - PID_Calculate(error);在实际调参里P值起步给30左右I值可以设得非常小或者先设0D值给20左右。跑起来以后先观察小车是不是在中线附近振荡如果有振荡就减P如果过弯跟不上就加P。循迹速度我一般控制在0.3m/s到0.5m/s之间再快的话普通TT马达的响应速度就开始吃力了。提示让电机PWM输出和转向修正有死区范围error小于2时不做转向修正否则电机一直在微调电池耗得快电机也容易发热。4. 避障的决策逻辑超声波不是越近越要停4.1 超声波与红外避障传感器的选型取舍HC-SR04超声波传感器的测距原理是发一个10us的TRIG脉冲然后测量ECHO引脚高电平的持续时间距离等于时间乘以声速除以2。具体实现代码几乎每个教程都有但我想强调一个容易忽略的点超声波模块发射角大概有15度如果前方障碍物是窄柱子或者桌腿超声波可能会扫不到等红外传感器检测到的时候已经离得很近了。所以我的方案是超声波负责前方35cm以内的大范围探测左右两侧各装一个红外避障模块负责侧方近距离检测夹角朝外45度左右。红外避障模块原理是发射红外光接收反射光强弱来判断是否有障碍物比较器阈值通过电位器调节调节距离范围大概在2cm到30cm之间。实测下来用超声波决定“减速还是转向”用红外决定“转向是否安全”这个分工最合理。4.2 避障决策表的构建避障逻辑不要写成满屏if嵌套我建议做成查表决策。把超声波距离分成三档S近、M中、F远左右红外各一档有/无一共3×2×212种组合每种组合对应一个动作。typedef struct { uint8_t distLevel; uint8_t leftBlock; uint8_t rightBlock; void (*action)(void); } ObstacleDecision; ObstacleDecision decisionTable[] { {LEVEL_NEAR, 0, 0, TurnLeft180}, {LEVEL_NEAR, 1, 0, TurnRight}, {LEVEL_NEAR, 0, 1, TurnLeft}, {LEVEL_NEAR, 1, 1, StopAndBeep}, // 其余组合按同样方式填充 };这样做的好处是决策逻辑一目了然后期想调整优先级或者增加新动作只需要改表不需要改程序骨架。而且查表的运行效率比多个if else高很多虽然在小车上这点性能差异感受不到但代码的可维护性提升了一大截。有一个经验值得分享前方近距离有障碍左右两侧都安全时不要默认向左转。很多小车设计成固定左转跑几次就会发现总往一个方向绕场地利用率很低。我建议加上一个“上次转向方向”的记忆变量这次向左下次就优先尝试向右能有效避免小车在狭窄区域反复打转。5. 遥控链路蓝牙串口协议与指令解析5.1 蓝牙模块配置与串口对接HC-05蓝牙模块上电后按住模块上的按键再上电就能进入AT指令模式串口波特率默认是38400。先发AT返回OK然后ATNAMECarATROLE1设为从机可以被手机连接ATUART9600,0,0把通信波特率改成9600改完波特率之后断开重新上电用手机蓝牙连接配对码一般是1234。模块的TXD接STM32的USART1_RXPA10RXD接USART1_TXPA9一定要共地。串口初始化设置9600波特率、8位数据、无校验、1位停止位然后就能互相收发数据了。我用的是HAL库的串口中断接收每次接收一个字节存入环形缓冲区主循环在空闲时去取这样不会因为蓝牙数据太多而卡死主流程。5.2 指令协议的定义与容错遥控指令不要用单个字符代表一个动作因为蓝牙传输过程中很容易丢包或者误码单个字符一旦错了小车会执行一个完全未知的动作。我用的协议是帧头数据校验typedef struct { uint8_t header; // 固定0xAA uint8_t carMode; // R遥控, O避障, T循迹 int8_t speed; // -100 ~ 100 int8_t turn; // -100 ~ 100 uint8_t checksum; // 前四个字节异或和 } RemoteFrame;接收端必须校验帧头、长度和校验和任何一个不对就丢弃整帧。这样做表面上好像增加了开销但实际效果是误触率几乎降为零。手机端我用的是现成的蓝牙串口调试APP它支持自定义按键发送十六进制字符串只需要把每一帧数据做成固定字符串发出去就行。如果环境里有多个蓝牙设备也不用担心串频因为校验和保护住了。6. 联调实测中的坑与排查思路6.1 一个典型的“车轮乱转”问题排查全过程第一次把三个功能合到一起的时候我遇到了一个非常诡异的问题单独测试遥控正常单独测试循迹也正常但一进入避障模式左轮明显发抖右轮偶尔反转。排查过程是这样的第一步检查电源波形。用万用表量TB6612的VM引脚发现避障模式下电压波动比遥控模式大得多但是并没有跌破电机最低工作电压。第二步检查PWM信号。用逻辑分析仪抓PA6和PA7的波形发现PWM频率是对的但占空比在一个很短的时间内跳来跳去像是被另一个进程改了。第三步查代码。避障模式里确实没有直接改PWM的函数但是避障循环里有每次20ms的超声波测距阻塞延时而PWM输出是用TIM2定时器中断更新的。超声波测距期间如果刚好发生定时器中断而中断处理函数里读取了某个和其他线程共享的全局变量就可能读到中间状态。问题出在我不小心在定时器中断里直接修改了全局的速度变量而主循环也在改导致了竞态。解决办法很简单所有跨中断和主循环共享的变量都改成volatile并且给速度更新加一个临界区保护。嵌入式里这种问题非常典型不用逻辑分析仪很难定位。6.2 电源跌落引发的连锁反应另一个坑发生在电池电量从7.4V掉到6.5V左右的时候。现象是循迹小车突然变得很“神经质”黑线明明在中间它却频繁左右摆头。排查到最后发现供电电压不足导致五个循迹传感器因为比较器参考电压波动输出信号变得不稳定。这个问题不是代码能解决的根源是供电架构设计不科学。我后来做了两件事第一把降压模块的输出电容加大到470uF并且把降压后的5V单独走一路给传感器避免和电机驱动共享稳压源第二在程序里加了低电量检测ADC采集电池电压低于6.8V就在OLED上显示警告并限制最高速度防止电机抢电导致单片机复位。电压问题如果等到“单片机复位”才意识到往往已经晚了因为复位可能是瞬间的你根本来不及观察现象。另外电机启动瞬间的反电动势会通过地线回流导致STM32的ADC采样值抖动。我给电机两端并联了104陶瓷电容和反向续流二极管TB6612输出到电机的线尽量短且双绞这部分硬件噪声处理好了很多“玄学”问题会自动消失。我在实际调试中的体会是这类小车项目90%的难度不在“写代码”而在“定位问题”和“供电设计”。如果你发现自己调了很久还是一头雾水先别急着改算法用万用表和逻辑分析仪把信号波形、电压波形全部拉出来看一遍很多时候答案就在波形里。这个项目做完以后你对定时器、PWM、串口中断、ADC采集、PID控制这些嵌入式最基础的知识都会有一个非常扎实的理解后面再去做平衡车、四轴、机械臂很多思路都能直接迁移过去。本文还有配套的精品资源点击获取
返回列表