news 2026/5/26 11:29:46

STM32F103RC+L298N+五路红外,手把手教你做个能跑直线的循迹小车(附完整代码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32F103RC+L298N+五路红外,手把手教你做个能跑直线的循迹小车(附完整代码)

STM32F103RC+L298N+五路红外循迹小车实战指南

引言

循迹小车作为嵌入式开发的经典入门项目,不仅能帮助初学者快速掌握硬件连接、传感器应用和电机控制等核心技能,还能通过实际调试过程培养解决问题的能力。本文将基于STM32F103RC微控制器和L298N电机驱动模块,结合五路红外传感器,带你从零开始打造一台能稳定跑直线的智能小车。

不同于简单的代码演示,我们会重点关注整个项目的完整实现流程——从元器件选型、电路设计到软件调试的每个环节都会详细展开。特别针对初学者容易遇到的电源干扰、接线错误、PID参数调节等痛点问题,提供经过实战验证的解决方案。

1. 硬件选型与电路设计

1.1 核心元器件清单

一个可靠的循迹小车系统需要精心选择每个组件。以下是经过多次验证的硬件配置方案:

组件名称型号/参数数量备注说明
主控芯片STM32F103RC1具备足够GPIO和PWM资源
电机驱动模块L298N1支持双路直流电机驱动
红外传感器TCRT50005建议购买带比较器输出的模块
直流减速电机TT马达(6V/200RPM)2带编码器版本更佳
电源模块LM2596降压模块1输入7-12V,输出5V/3A
电池18650锂电池(7.4V)2需配套电池盒

提示:红外传感器建议选择已经集成比较器的模块,可以省去外部电路设计,降低入门难度。

1.2 电源系统设计

电源稳定性是影响小车性能的关键因素,常见问题包括:

  • 电机启动时导致MCU复位
  • 传感器供电不稳造成误检测
  • L298N驱动电压不足影响电机扭矩

推荐采用双路独立供电方案

  1. 动力电源:7.4V锂电池直接供给L298N的电机驱动端
  2. 控制电源:通过LM2596降压到5V,为STM32和传感器供电
// 电源连接示意图 电池正极 → L298N(12V输入) 电池正极 → LM2596(输入) → 5V输出 → STM32_VDD

1.3 传感器布局优化

五路红外传感器的安装位置直接影响循迹效果。经过实测,推荐以下布局参数:

  • 传感器间距:1.5-2cm(适应常见黑色电工胶带轨迹)
  • 离地高度:0.5-1cm(需根据实际场地调整)
  • 安装角度:略微向前倾斜10-15度(提高前瞻性)
[传感器排列示意图] 左2 ─ 左1 ─ 中 ─ 右1 ─ 右2

2. 硬件连接与调试

2.1 STM32与L298N连接

L298N模块的正确连接是控制电机的关键。以下是经过优化的接线方案:

L298N引脚STM32连接功能说明
ENAPA8 (TIM1_CH1)左电机PWM控制
IN1PB12左电机方向控制1
IN2PB13左电机方向控制2
ENBPA9 (TIM1_CH2)右电机PWM控制
IN3PB14右电机方向控制1
IN4PB15右电机方向控制2

注意:务必先确认电机转向是否正确,再固定小车结构。错误的转向会导致控制逻辑完全相反。

2.2 红外传感器接口配置

五路红外传感器建议采用以下GPIO分配方案:

#define IR_LEFT2 PC0 #define IR_LEFT1 PC1 #define IR_MIDDLE PC2 #define IR_RIGHT1 PC3 #define IR_RIGHT2 PC4

初始化代码示例:

void IR_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOC_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); }

2.3 常见硬件问题排查

在初期调试阶段,可能会遇到以下典型问题:

  1. 电机不转

    • 检查L298N使能跳线帽是否已移除
    • 确认PWM信号是否正常输出(可用示波器或LED测试)
    • 测量电机两端电压是否达到预期
  2. 传感器误触发

    • 调整传感器电位器,改变检测灵敏度
    • 检查供电电压是否稳定(应在4.5-5.5V之间)
    • 避免环境光干扰(可在传感器上方加遮光罩)
  3. 电源不稳定

    • 在STM32的VDD与GND之间并联100μF电容
    • 电机电源与控制电源地线在一点共地

3. 软件算法实现

3.1 基础循迹逻辑设计

五路传感器可以提供丰富的路径信息,我们采用状态机方式处理:

typedef enum { ON_TRACK, // 00000 SLIGHT_LEFT, // 00100 SLIGHT_RIGHT, // 00010 SHARP_LEFT, // 11000 SHARP_RIGHT, // 00011 LOST_TRACK // 11111 } TrackState; TrackState GetTrackState(void) { uint8_t sensors = (HAL_GPIO_ReadPin(GPIOC, IR_LEFT2) << 4) | (HAL_GPIO_ReadPin(GPIOC, IR_LEFT1) << 3) | (HAL_GPIO_ReadPin(GPIOC, IR_MIDDLE) << 2) | (HAL_GPIO_ReadPin(GPIOC, IR_RIGHT1) << 1) | HAL_GPIO_ReadPin(GPIOC, IR_RIGHT2); switch(sensors) { case 0b00100: return ON_TRACK; case 0b01100: return SLIGHT_LEFT; // 其他状态判断... default: return LOST_TRACK; } }

3.2 PID控制算法实现

为了让小车跑得更直更稳,我们引入增量式PID算法:

typedef struct { float Kp, Ki, Kd; float last_error, prev_error; float integral; } PID_Controller; float PID_Update(PID_Controller* pid, float error) { float derivative = error - pid->last_error; pid->integral += error; float output = pid->Kp * error + pid->Ki * pid->integral + pid->Kd * derivative; pid->prev_error = pid->last_error; pid->last_error = error; return output; }

参数整定建议:

  • 先调P(比例),让小车能基本跟随但不振荡
  • 再调D(微分),抑制过冲和振荡
  • 最后调I(积分),消除静态误差

3.3 电机控制策略

基于PID输出,我们需要动态调整左右电机PWM:

void Motor_Control(float pid_output) { // 基础速度(可根据需要调整) uint16_t base_speed = 500; // 计算左右电机速度 uint16_t left_speed = base_speed - pid_output; uint16_t right_speed = base_speed + pid_output; // 限制PWM范围 left_speed = (left_speed > 999) ? 999 : left_speed; right_speed = (right_speed > 999) ? 999 : right_speed; // 更新PWM __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, left_speed); __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, right_speed); }

4. 系统调试与优化

4.1 分阶段调试方法

建议按照以下顺序逐步调试:

  1. 传感器测试

    • 单独测试每个传感器的开关状态
    • 确认检测距离和灵敏度一致
  2. 电机测试

    • 验证正反转控制逻辑
    • 测试PWM调速是否线性
  3. 开环测试

    • 固定PWM值,观察小车直线行驶偏差
  4. 闭环调试

    • 先调P参数,再引入D和I
    • 记录不同参数下的运行效果

4.2 性能优化技巧

经过多次实测,总结出以下优化经验:

  • 机械对称性

    • 确保车轮直径一致(可用卡尺测量)
    • 检查车体左右重量分布平衡
  • 软件滤波

    • 对传感器信号进行软件消抖
    • 采用移动平均滤波处理PWM输出
// 简单的移动平均滤波实现 #define FILTER_SIZE 5 float speed_filter[FILTER_SIZE] = {0}; uint8_t filter_index = 0; float ApplyFilter(float new_value) { speed_filter[filter_index] = new_value; filter_index = (filter_index + 1) % FILTER_SIZE; float sum = 0; for(int i=0; i<FILTER_SIZE; i++) { sum += speed_filter[i]; } return sum / FILTER_SIZE; }
  • 轨迹适应性
    • 针对不同宽度轨迹调整传感器阈值
    • 根据转弯半径动态调整PID参数

4.3 常见问题解决方案

在实际项目中,我们遇到过这些问题及解决方法:

  1. 小车走S形路线

    • 检查传感器安装是否水平
    • 降低P参数,增加D参数
    • 确认电机转速是否匹配
  2. 过弯时冲出轨迹

    • 提高转弯时的内侧电机减速幅度
    • 增加前瞻性(如将中间传感器前移)
  3. 直线行驶有偏差

    • 校准电机基准PWM值
    • 检查车轮是否打滑
    • 在平整度高的场地上测试

5. 完整代码架构

5.1 工程文件结构

一个组织良好的项目结构能提高开发效率:

├── Core/ │ ├── Src/ │ │ ├── main.c # 主循环和初始化 │ │ ├── motor.c # 电机控制接口 │ │ ├── sensor.c # 红外传感器处理 │ │ └── pid.c # PID算法实现 │ └── Inc/ # 对应头文件 ├── Drivers/ # HAL库文件 └── STM32F103C8T6_FLASH.ld # 链接脚本

5.2 主控制逻辑实现

main.c中的核心处理流程:

int main(void) { // 硬件初始化 HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_TIM1_Init(); IR_Init(); // PID控制器初始化 PID_Controller pid = {.Kp = 0.5, .Ki = 0.01, .Kd = 0.2}; while (1) { TrackState state = GetTrackState(); float error = CalculateError(state); float output = PID_Update(&pid, error); Motor_Control(output); HAL_Delay(10); // 10ms控制周期 } }

5.3 关键函数详解

CalculateError()根据传感器状态计算偏差:

float CalculateError(TrackState state) { switch(state) { case ON_TRACK: return 0.0f; case SLIGHT_LEFT: return -0.3f; case SLIGHT_RIGHT: return 0.3f; case SHARP_LEFT: return -1.0f; case SHARP_RIGHT: return 1.0f; default: return 0.0f; // 丢失轨迹保持直行 } }

Motor_Control()增强版带死区补偿:

void Motor_Control(float output) { static float left_comp = 1.0, right_comp = 1.0; // 校准模式:记录左右电机补偿系数 if(calibration_mode) { // ...校准逻辑... return; } uint16_t base = 500; uint16_t left = base * left_comp - output * 200; uint16_t right = base * right_comp + output * 200; // 应用PWM __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, left); __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, right); }

6. 进阶功能扩展

6.1 无线调试接口

添加蓝牙或2.4G模块实现实时参数调整:

// 通过串口接收PID参数 void USART1_IRQHandler(void) { if(USART1->SR & USART_SR_RXNE) { char cmd = USART1->DR; if(cmd == 'P') { // 接收并更新P参数 sscanf(rx_buffer, "P%f", &pid.Kp); } // 其他命令处理... } }

6.2 速度闭环控制

利用编码器实现更精确的速度控制:

  1. 配置TIM2/TIM3为编码器模式
  2. 定期读取计数器值计算实际转速
  3. 增加速度PID环
// 编码器初始化 TIM_Encoder_InitTypeDef encoder = {0}; encoder.EncoderMode = TIM_ENCODERMODE_TI12; encoder.IC1Polarity = TIM_ICPOLARITY_RISING; encoder.IC2Polarity = TIM_ICPOLARITY_RISING; HAL_TIM_Encoder_Init(&htim2, &encoder); HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_ALL);

6.3 多模式切换

通过按键实现不同运行模式:

typedef enum { MODE_MANUAL, // 手动控制 MODE_LINE_TRACK,// 循迹模式 MODE_CALIBRATE // 传感器校准 } OperationMode; void HandleModeSwitch(void) { if(HAL_GPIO_ReadPin(BUTTON_GPIO_Port, BUTTON_Pin) == GPIO_PIN_RESET) { HAL_Delay(50); // 消抖 current_mode = (current_mode + 1) % 3; UpdateIndicatorLED(); } }

7. 项目经验分享

在实际开发这个小车的过程中,有几个关键点值得特别注意:

电源布线:最初我们将所有电源线简单地拧在一起,结果电机启动时经常导致单片机复位。后来改用星型接地和增加去耦电容后,系统稳定性大幅提升。

传感器校准:五路红外传感器的灵敏度实际上存在差异,我们增加了上电自动校准功能,让小车在启动时自动记录每路传感器的基准值,显著提高了不同光照条件下的适应性。

机械结构:3D打印的车架虽然美观,但发现长时间运行后会有轻微变形影响行驶直线度。改用2mm铝板切割后,配合橡胶减震垫,解决了这个问题。

参数调节:PID参数不是一成不变的,我们最终实现了一套根据转弯半径动态调整参数的算法,当检测到急弯时自动提高微分系数,使小车能更平稳过弯。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/26 11:29:40

Netgear路由器终极救砖指南:使用NMRPFlash免费修复工具

Netgear路由器终极救砖指南&#xff1a;使用NMRPFlash免费修复工具 【免费下载链接】nmrpflash Netgear Unbrick Utility 项目地址: https://gitcode.com/gh_mirrors/nmr/nmrpflash NMRPFlash是一款强大的开源Netgear路由器修复工具&#xff0c;专门用于拯救变砖的Netge…

作者头像 李华
网站建设 2026/5/26 11:29:18

MongoDB find() 实战优化:从查不到到87毫秒的完整链路

1. 这不是语法手册&#xff0c;而是一份能让你当天就写出可靠查询的实战笔记 MongoDB find() 是每个刚接触文档数据库的人最先敲下的命令&#xff0c;但绝大多数人卡在“写出来能跑”和“写出来能用”之间——查不到数据时反复改条件却不知从何排查&#xff0c;聚合管道里字段名…

作者头像 李华
网站建设 2026/5/26 11:29:10

探索picacomic-downloader:基于Tauri架构的现代化漫画下载器深度解析

探索picacomic-downloader&#xff1a;基于Tauri架构的现代化漫画下载器深度解析 【免费下载链接】picacomic-downloader 哔咔漫画 picacomic pica漫画 bika漫画 PicACG 多线程下载器&#xff0c;带图形界面 带收藏夹&#xff0c;已打包exe 下载速度飞快 项目地址: https://g…

作者头像 李华
网站建设 2026/5/26 11:29:06

5分钟自动化部署:Brigadier解决Mac Boot Camp驱动管理难题

5分钟自动化部署&#xff1a;Brigadier解决Mac Boot Camp驱动管理难题 【免费下载链接】brigadier Fetch and install Boot Camp ESDs with ease. 项目地址: https://gitcode.com/gh_mirrors/bri/brigadier 在IT运维和跨平台部署的实际工作中&#xff0c;Mac电脑的Boot …

作者头像 李华
网站建设 2026/5/26 11:29:04

PUBG罗技压枪脚本终极指南:从零配置到实战精通

PUBG罗技压枪脚本终极指南&#xff1a;从零配置到实战精通 【免费下载链接】PUBG-Logitech PUBG罗技鼠标宏自动识别压枪 项目地址: https://gitcode.com/gh_mirrors/pu/PUBG-Logitech PUBG-Logitech是一款基于罗技鼠标宏的绝地求生自动压枪解决方案&#xff0c;通过先进…

作者头像 李华