从零到一:基于STM32与五路红外传感器的智能循迹小车实战
1. 项目概述为什么选择STM32做循迹小车第一次接触嵌入式开发时很多人都会纠结该用什么主控芯片。我当年在51单片机和STM32之间犹豫了很久最终选择了STM32F103C8T6这款性价比极高的芯片。原因很简单它既有足够的外设资源5个定时器、2个ADC、37个GPIO又支持HAL库开发最关键的是价格只要十几块钱。对于循迹小车这种需要实时控制的项目STM32的72MHz主频完全够用而且CubeMX工具能帮我们快速完成初始化配置。五路红外传感器的布局也值得说道。常见的有三路和五路两种方案三路虽然便宜但遇到复杂路线比如直角弯就容易翻车。五路传感器通过最外侧两个探头能提前预判弯道实测下来循迹稳定性提升明显。我用的模块是TCRT5000红外对管5块钱就能买到黑色轨迹线识别距离在0.5-3cm可调记得要用螺丝刀把电位器调到合适位置。2. 硬件搭建从零组装你的第一辆智能车2.1 核心部件清单与选购建议主控板STM32F103C8T6最小系统板注意要买带USB转串口的版本电机驱动L298N模块建议选带光耦隔离的防止烧芯片传感器五路红外循迹模块注意要买模拟量输出的版本电源3节18650电池盒串联电压11.1V要给L298N和STM32分别供电车架淘宝搜智能小车底盘建议选带TT马达和橡胶轮的套装接线时有几个坑我提前帮大家踩了L298N的12V输入接电池正极5V输出可以给STM32供电但建议单独供电更稳定。红外模块的VCC最好接3.3V因为5V供电时输出高电平可能超过STM32的容忍电压。记得用万用表量一下我当初就烧过一个IO口。2.2 电路连接详解具体接线可以参照这个表格模块STM32引脚备注红外传感器1PA0最左侧传感器红外传感器2PA1左侧传感器红外传感器3PA2中间传感器关键红外传感器4PA3右侧传感器红外传感器5PA4最右侧传感器L298N IN1PB6左电机正极L298N IN2PB7左电机负极L298N IN3PB8右电机正极L298N IN4PB9右电机负极电机接线有个小技巧先用杜邦线接好所有线路上电测试电机转向。如果发现左右轮转向相反直接把L298N输出端的线序对调就行比改代码快多了。3. 软件开发CubeMX配置与算法实现3.1 CubeMX初始化关键步骤打开CubeMX新建工程时记得选对芯片型号。关键配置如下时钟树把HCLK调到72MHz输入8MHz晶振PLL倍频9倍GPIO将PA0-PA4设为输入模式对应五个红外传感器定时器配置TIM3的CH1和CH4为PWM输出控制电机速度串口开启USART1用于调试打印波特率115200生成代码前务必勾选Generate peripheral initialization as a pair of .c/.h files这样代码结构更清晰。我遇到过不勾选导致PWM无法输出的情况排查了半天才发现是CubeMX的坑。3.2 循迹算法深度解析核心逻辑是通过五个传感器的状态组合来判断路线走向。这里分享我的改进算法void Tracking() { // 读取传感器值0表示检测到黑线 uint8_t L !HAL_GPIO_ReadPin(sensor1_GPIO_Port, sensor1_Pin); // 最左 uint8_t l !HAL_GPIO_ReadPin(sensor2_GPIO_Port, sensor2_Pin); // 左 uint8_t m !HAL_GPIO_ReadPin(sensor3_GPIO_Port, sensor3_Pin); // 中 uint8_t r !HAL_GPIO_ReadPin(sensor4_GPIO_Port, sensor4_Pin); // 右 uint8_t R !HAL_GPIO_ReadPin(sensor5_GPIO_Port, sensor5_Pin); // 最右 // 直角转弯检测 if(L l m r R) { // 全黑线十字路口 handle_crossroad(); } else if(L l) { // 左急弯 sharp_left(); } else if(R r) { // 右急弯 sharp_right(); } // 常规路线修正 else if(l !r) { adjust_left(); // 小角度左修正 } else if(r !l) { adjust_right(); // 小角度右修正 } else { go_straight(); // 直行 } }相比原始代码这个版本增加了状态检测的容错机制。比如在sharp_left()函数里我加入了延时判断先直行300ms再转向避免传感器误判导致小车抖动。实测下来直角转弯成功率从60%提升到了95%。4. 调试技巧与性能优化4.1 常见问题排查指南电机不转先检查L298N的使能端ENA/ENB是否接高电平再用万用表量电机两端电压传感器无反应调节模块上的蓝色电位器用白纸测试时LED灯应该会变化小车走偏尝试交换左右电机接线或者在代码里调整PWM占空比补偿突然复位可能是电源功率不足建议用示波器看3.3V电压是否稳定4.2 高级优化方案当基础功能实现后可以尝试这些进阶玩法PID控制根据偏差大小动态调整电机转速代码片段如下// PID参数需要实际调试 float Kp0.5, Ki0.01, Kd0.1; int last_error 0, integral 0; void pid_control(int error) { integral error; int derivative error - last_error; int output Kp*error Ki*integral Kd*derivative; // 限制输出范围 output output 100 ? 100 : (output -100 ? -100 : output); // 应用左右轮速度差 set_motor_speed(70 output, 70 - output); last_error error; }速度分级直道全速弯道降速提升过弯稳定性记忆路径用数组存储传感器历史数据实现复杂路径规划记得在调试时用printf打印关键变量我通常会这样封装调试宏#define DEBUG 1 #if DEBUG #define LOG(fmt,...) printf([%s] fmt, __FUNCTION__, ##__VA_ARGS__) #else #define LOG(fmt,...) #endif最后说说电源管理的经验测试时发现电池电压降到10V以下时红外传感器会出现误检测。后来我在代码里加了电压检测功能当电压过低时让小车自动停车。硬件上可以在电池和L298N之间加个LC滤波电路成本不到2块钱但能有效消除电机干扰。