1. 项目概述
这个基于STM32F103C8T6单片机的智能循迹避障小车项目,是我在嵌入式系统课程设计中的实践成果。它集成了红外循迹、超声波避障、蓝牙遥控和OLED显示等多种功能模块,实现了一个完整的智能小车控制系统。作为嵌入式开发的经典练手项目,它不仅涵盖了硬件电路设计、传感器应用、电机控制等核心知识点,还能通过实际调试过程深入理解嵌入式系统的开发流程。
这个小车最核心的功能可以概括为两点:一是通过红外传感器实现黑线循迹功能,二是通过超声波传感器实现自动避障功能。此外,我们还加入了蓝牙遥控和数据显示功能,使得整个系统更加完善。下面我将从硬件设计、软件实现和调试经验三个方面,详细分享这个项目的完整开发过程。
2. 硬件系统设计
2.1 主控芯片选型与电路设计
我们选择STM32F103C8T6作为主控芯片,这是一款基于ARM Cortex-M3内核的32位微控制器,具有72MHz的主频、64KB Flash和20KB RAM,完全满足本项目的需求。这款芯片的优势在于:
- 丰富的外设接口:多个定时器、USART、SPI、I2C等
- 充足的GPIO资源:37个I/O引脚
- 性价比高:价格适中且性能足够
- 开发资料丰富:社区支持完善
电源部分采用Type-C接口输入5V电源,通过AMS1117-3.3V稳压芯片转换为3.3V为单片机供电。这里需要注意:
- 输入电源要加100μF的电解电容滤波
- 3.3V输出端要加10μF和0.1μF的电容组合
- 电源走线要足够宽,建议至少20mil
提示:在PCB布局时,稳压芯片要尽量靠近电源输入位置,且滤波电容要尽可能靠近芯片引脚放置。
2.2 传感器模块设计
2.2.1 红外循迹模块
采用TCRT5000红外反射式传感器,共使用5个传感器并排安装在小车底部,用于检测地面黑线。传感器输出为数字信号,当检测到黑线时输出高电平,否则输出低电平。
传感器布局建议:
- 中间传感器:用于精确循迹
- 左右两侧各两个传感器:用于检测偏离方向
- 传感器间距:15-20mm(根据实际赛道宽度调整)
2.2.2 超声波避障模块
使用HC-SR04超声波模块,测量范围2cm-400cm,精度可达3mm。通过舵机(SG90)带动超声波模块左右旋转(±90°),实现多方向障碍物检测。
超声波模块使用注意事项:
- 触发信号(Trig)至少需要10μs的高电平
- 测量周期建议≥60ms(防止信号干扰)
- 模块需要稳定的5V供电
- 测量角度约15°,安装时需要考虑探测范围
2.3 电机驱动设计
采用L298N双H桥电机驱动模块,可同时驱动两个直流电机。电机参数选择:
- 工作电压:6V
- 减速比:1:48
- 转速:约200RPM
- 扭矩:足够带动小车车身
电机驱动电路设计要点:
- 电机电源与逻辑电源要分开
- 每个电机两端要并联续流二极管
- 在电源端加装大容量电容(1000μF)滤波
- PWM频率建议选择5-10kHz
2.4 其他外设模块
- OLED显示模块:0.96寸I2C接口,用于显示距离、模式等信息
- 蓝牙模块:ECB02,基于蓝牙4.0,实现手机遥控功能
- 舵机模块:SG90,用于带动超声波旋转
3. 软件系统设计
3.1 系统架构设计
软件采用模块化设计,主要分为以下几个部分:
- 底层驱动层:GPIO、定时器、PWM、USART等外设驱动
- 传感器驱动层:超声波、红外、蓝牙等模块驱动
- 应用逻辑层:循迹算法、避障算法、状态机控制
- 用户界面层:OLED显示、蓝牙指令处理
系统主循环采用时间片轮询方式,各任务分配如下:
- 超声波测距:100ms一次
- 红外循迹检测:50ms一次
- 电机控制:20ms一次
- OLED刷新:200ms一次
- 蓝牙数据处理:有数据时立即处理
3.2 循迹算法实现
循迹控制采用PID算法,根据红外传感器检测到的位置偏差计算电机控制量。具体实现如下:
c复制// PID参数
float Kp = 0.5, Ki = 0.01, Kd = 0.2;
float error = 0, last_error = 0, integral = 0;
void Track_PID_Control(void)
{
// 获取传感器数据
int sensor_values = Get_IR_Sensors();
// 计算位置偏差
if(sensor_values == 0b00100) error = 0; // 居中
else if(sensor_values == 0b00010) error = 1; // 偏右1个单位
else if(sensor_values == 0b00001) error = 2; // 偏右2个单位
else if(sensor_values == 0b01000) error = -1; // 偏左1个单位
else if(sensor_values == 0b10000) error = -2; // 偏左2个单位
// PID计算
integral += error;
float output = Kp*error + Ki*integral + Kd*(error-last_error);
last_error = error;
// 电机控制
Set_Motor_Speed(LEFT_MOTOR, BASE_SPEED + output);
Set_Motor_Speed(RIGHT_MOTOR, BASE_SPEED - output);
}
3.3 避障算法实现
避障采用状态机设计,主要状态包括:
- 前进状态:直行并检测前方障碍
- 左转检测:舵机左转检测左侧障碍
- 右转检测:舵机右转检测右侧障碍
- 避障动作:根据检测结果执行转向或后退
关键代码实现:
c复制typedef enum {
STATE_FORWARD,
STATE_CHECK_LEFT,
STATE_CHECK_RIGHT,
STATE_TURN_LEFT,
STATE_TURN_RIGHT,
STATE_BACKWARD
} ObstacleAvoidState;
ObstacleAvoidState current_state = STATE_FORWARD;
void Obstacle_Avoidance(void)
{
static uint32_t check_timer = 0;
float front_dist, left_dist, right_dist;
switch(current_state)
{
case STATE_FORWARD:
front_dist = Get_Ultrasonic_Distance();
if(front_dist < SAFE_DISTANCE) {
current_state = STATE_CHECK_LEFT;
Set_Servo_Angle(90); // 左转90度
check_timer = HAL_GetTick();
}
break;
case STATE_CHECK_LEFT:
if(HAL_GetTick() - check_timer > 500) {
left_dist = Get_Ultrasonic_Distance();
if(left_dist > SAFE_DISTANCE) {
current_state = STATE_TURN_LEFT;
} else {
current_state = STATE_CHECK_RIGHT;
Set_Servo_Angle(-90); // 右转90度
check_timer = HAL_GetTick();
}
}
break;
// 其他状态处理类似...
}
}
3.4 蓝牙遥控实现
蓝牙模块通过串口与单片机通信,协议设计如下:
- 前进:'F'
- 后退:'B'
- 左转:'L'
- 右转:'R'
- 停止:'S'
- 模式切换:'M'
串口中断处理函数:
c复制void USART1_IRQHandler(void)
{
if(USART1->SR & USART_SR_RXNE) {
uint8_t ch = USART1->DR;
switch(ch) {
case 'F': Set_Car_Move(FORWARD); break;
case 'B': Set_Car_Move(BACKWARD); break;
case 'L': Set_Car_Move(LEFT); break;
case 'R': Set_Car_Move(RIGHT); break;
case 'S': Set_Car_Move(STOP); break;
case 'M': Toggle_Mode(); break;
}
}
}
4. 系统调试与优化
4.1 硬件调试技巧
-
电源调试:
- 先不接电机,测量各点电压是否正常
- 接上电机后观察电源波动情况
- 如果电压跌落严重,检查滤波电容是否足够
-
传感器调试:
- 红外传感器:用串口打印各传感器输出值,调整安装高度(建议5-10mm)
- 超声波传感器:测量不同距离的实际值,校准测距公式
- 舵机:检查转动角度是否准确,机械结构是否牢固
-
电机调试:
- 单独测试每个电机正反转
- 检查PWM频率是否合适(太高会导致电机啸叫)
- 测试不同占空比下的电机转速
注意:调试时建议使用调试助手或OLED实时显示关键参数,如传感器数值、电机PWM占空比等。
4.2 软件调试经验
-
循迹调试:
- 先调整Kp参数,使小车能快速响应偏差
- 然后加入Ki消除静态误差
- 最后加入Kd抑制振荡
- 典型参数范围:Kp(0.3-1.0), Ki(0-0.05), Kd(0.1-0.5)
-
避障调试:
- 调整SAFE_DISTANCE(建议20-30cm)
- 优化状态切换时间,避免过于频繁转向
- 测试不同表面材质的障碍物检测效果
-
蓝牙调试:
- 使用串口助手测试通信是否正常
- 检查指令响应时间,避免延迟过大
- 测试不同手机APP的兼容性
4.3 常见问题解决
-
小车走直线偏移:
- 检查电机转速是否一致,可单独校准
- 检查车体重心是否平衡
- 尝试调整PID参数
-
超声波测距不准确:
- 确保测量周期足够长(≥60ms)
- 检查电源是否稳定
- 避免在强光或反射率低的表面测试
-
蓝牙连接不稳定:
- 检查天线是否完好
- 避免金属物体遮挡
- 测试不同距离下的信号强度
-
系统复位或死机:
- 检查电源容量是否足够
- 添加看门狗定时器
- 检查堆栈空间是否充足
5. 项目扩展与改进
在完成基础功能后,可以考虑以下扩展方向:
- 增加摄像头模块,实现图像识别功能
- 添加WiFi模块,实现远程监控和控制
- 改用锂电池供电,增加续航能力
- 设计3D打印外壳,提升外观质感
- 实现多车通信和协同控制
对于初学者,我建议先确保基础功能稳定运行,再逐步添加扩展功能。在实际开发中,我最大的体会是:硬件设计要预留足够的调试接口,软件编写要注重模块化和可调试性,这样才能高效地解决问题。