引言
本项目设计了一个基于STM32的自学习走迷宫智能小车。小车通过多个超声波传感器、红外传感器等,检测周围障碍物和路径。它采用简单的强化学习算法,在不断探索的过程中自我调整路径,从而最终找到迷宫的出口。系统适用于智能机器人实验、教育以及竞赛项目,具备一定的自学习和智能导航能力。
环境准备
1. 硬件设备
- STM32F103C8T6 开发板(或其他 STM32 系列)
- 超声波传感器(如 HC-SR04,用于检测障碍物)
- 红外传感器(如 TCRT5000,用于检测迷宫路径线)
- L298N 电机驱动模块(用于控制小车的电机)
- 直流电机和车轮(用于小车行驶)
- PWM 控制器(用于调节电机速度)
- 蜂鸣器(用于路径发现提示)
- OLED 显示屏(用于显示小车状态)
- USB-TTL 串口调试工具
- 电阻、杜邦线、面包板等基础电子元件
2. 软件工具
- STM32CubeMX:用于初始化 STM32 外设。
- Keil uVision 或 STM32CubeIDE:用于编写和下载代码。
- ST-Link 驱动程序:用于下载程序到 STM32。
项目实现
1. 硬件连接
- 超声波传感器连接:将 HC-SR04 的 Trig 和 Echo 引脚连接到 STM32 的 GPIO(如 PA0 和 PA1),用于检测迷宫中的障碍物。
- 红外传感器连接:将 TCRT5000 的输出引脚连接到 STM32 的 ADC 输入引脚(如 PA2),用于检测迷宫中的黑线路径。
- 电机驱动连接:将 L298N 电机驱动模块的输入引脚连接到 STM32 的 GPIO(如 PA3、PA4、PA5、PA6),用于控制小车的前进、后退、左转和右转。
- 蜂鸣器连接:将蜂鸣器的控制引脚连接到 STM32 的 GPIO(如 PA7),用于路径发现和学习成功的提示。
- OLED 显示屏连接:将 OLED 的 SDA 和 SCL 引脚连接到 STM32 的 I2C 接口(如 PB6 和 PB7),用于显示小车状态信息。
2. STM32CubeMX 配置
- 打开 STM32CubeMX,选择你的开发板型号。
- 配置系统时钟为 HSI,确保系统稳定运行。
- 配置 GPIO 引脚用于超声波传感器、红外传感器和电机控制。
- 配置 I2C,用于与 OLED 显示屏通信。
- 配置 TIM1 生成 PWM 信号,用于调节电机速度。
- 生成代码,选择 Keil 或 STM32CubeIDE 作为工具链。
3. 编写主程序
在生成的项目基础上,编写迷宫路径检测、碰撞避障、强化学习算法和小车运动控制的代码。以下是自学习走迷宫智能小车的基本代码示例:
#include "stm32f1xx_hal.h"
#include "ultrasonic.h"
#include "motor.h"
#include "infrared.h"
#include "oled.h"
// 定义一些控制参数
#define DISTANCE_THRESHOLD 20 // 障碍物距离小于 20 cm 时需要避障
#define LEFT_TURN_REWARD 1 // 左转奖励值
#define RIGHT_TURN_REWARD 2 // 右转奖励值
#define MOVE_FORWARD_REWARD 5 // 前进奖励值
#define COLLISION_PENALTY -10 // 碰撞惩罚值
// 函数声明
void System_Init(void);
void Detect_Obstacle(void);
void Follow_Path(void);
void Make_Decision(void);
void Move_Car(uint8_t direction);
void Display_Status(void);
// 全局变量
uint32_t distance = 0; // 用于存储超声波测得的距离
uint8_t path_detected = 0; // 路径是否检测到
int8_t reward = 0; // 当前动作的奖励值
void System_Init(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
MX_TIM1_Init();
OLED_Init();
Ultrasonic_Init();
Motor_Init();
Infrared_Init();
OLED_ShowString(0, 0, "Maze Solver Ready");
}
// 检测障碍物并避障
void Detect_Obstacle(void)
{
distance = Ultrasonic_Measure();
if (distance < DISTANCE_THRESHOLD)
{
Move_Car(2); // 碰撞前退
reward += COLLISION_PENALTY;
HAL_Delay(500);
}
}
// 检测路径
void Follow_Path(void)
{
path_detected = Infrared_Detect();
if (path_detected)
{
Move_Car(0); // 沿线前进
reward += MOVE_FORWARD_REWARD;
Display_Status(); // 显示状态
}
else
{
// 选择随机动作
Make_Decision();
}
}
// 决策过程(左转或右转)
void Make_Decision(void)
{
if (distance < DISTANCE_THRESHOLD) // 遇到障碍物时需要决定转向
{
// 随机选择左转或右转
if (HAL_GetTick() % 2 == 0)
{
Move_Car(1); // 左转
reward += LEFT_TURN_REWARD;
}
else
{
Move_Car(3); // 右转
reward += RIGHT_TURN_REWARD;
}
}
}
// 控制小车运动,0: 前进,1: 左转,2: 后退,3: 右转
void Move_Car(uint8_t direction)
{
switch (direction)
{
case 0: // 前进
Motor_SetDirection(1, 1);
Motor_SetSpeed(80, 80);
break;
case 1: // 左转
Motor_SetDirection(1, -1);
Motor_SetSpeed(60, 60);
break;
case 2: // 后退
Motor_SetDirection(-1, -1);
Motor_SetSpeed(80, 80);
break;
case 3: // 右转
Motor_SetDirection(-1, 1);
Motor_SetSpeed(60, 60);
break;
}
}
// 显示状态信息
void Display_Status(void)
{
OLED_Clear();
OLED_ShowString(0, 0, "Distance: ");
OLED_ShowNumber(64, 0, distance, 4);
OLED_ShowString(0, 1, "Reward: ");
OLED_ShowNumber(64, 1, reward, 4);
}
int main(void)
{
System_Init();
while (1)
{
Detect_Obstacle(); // 检测并避障
Follow_Path(); // 检测并沿路径行驶
HAL_Delay(500); // 每0.5秒更新一次状态
}
}
4. 各模块代码
超声波传感器检测
通过超声波传感器检测小车前方障碍物的距离,确保小车能够避开障碍物:
#include "ultrasonic.h"
// 初始化超声波传感器
void Ultrasonic_Init(void)
{
// 配置 GPIO 引脚
}
// 测量距离
uint32_t Ultrasonic_Measure(void)
{
uint32_t distance = 0;
uint32_t local_time = 0;
// 发送 Trig 脉冲
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
HAL_Delay(10); // 10 微秒脉冲
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);
// 等待 Echo 的高电平并计算时间
while (!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1)); // 等待 Echo 引脚变高
while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1)) // 计算 Echo 高电平的时间
{
local_time++;
HAL_Delay(1); // 延时 1 微秒
}
// 计算距离 (声音速度 34000 cm/s)
distance = (local_time * 0.034) / 2; // 除以 2 是因为声音往返
return distance;
}
红外传感器检测路径
通过红外传感器检测黑线路径,引导小车行驶方向:
#include "infrared.h"
// 初始化红外传感器
void Infrared_Init(void)
{
// 配置 GPIO 引脚
}
// 检测路径
uint8_t Infrared_Detect(void)
{
// 读取红外传感器输出,返回 1 表示检测到黑线,0 表示未检测到
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2) == GPIO_PIN_SET)
{
return 1; // 检测到路径
}
return 0; // 未检测到路径
}
电机控制
通过 L298N 电机驱动模块控制小车的前进、后退、左转和右转:
#include "motor.h"
// 初始化电机
void Motor_Init(void)
{
// 初始化 GPIO 和 PWM
}
// 设置电机速度
void Motor_SetSpeed(uint8_t left_speed, uint8_t right_speed)
{
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, left_speed); // 左电机 PWM
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, right_speed); // 右电机 PWM
}
// 设置电机方向,1 表示前进,-1 表示后退,0 表示停止
void Motor_SetDirection(int8_t left_dir, int8_t right_dir)
{
// 控制左侧和右侧电机的前进、后退
if (left_dir == 1)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET); // 左电机前进
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
}
else if (left_dir == -1)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET); // 左电机后退
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}
if (right_dir == 1)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET); // 右电机前进
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET);
}
else if (right_dir == -1)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); // 右电机后退
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);
}
}
OLED 显示
OLED 显示屏用于显示小车的实时状态,如距离、奖励值等:
#include "oled.h"
// 初始化 OLED 显示屏
void OLED_Init(void)
{
// OLED 初始化代码
}
// 显示字符串
void OLED_ShowString(uint8_t x, uint8_t y, const char *str)
{
// 在 OLED 显示屏上显示字符串
}
// 显示数字
void OLED_ShowNumber(uint8_t x, uint8_t y, uint32_t num, uint8_t len)
{
// 显示整数
}
// 清屏
void OLED_Clear(void)
{
// 清除 OLED 显示内容
}
⬇帮大家整理了单片机的资料
包括stm32的项目合集【源码+开发文档】
点击下方蓝字即可领取,感谢支持!⬇
点击领取更多嵌入式详细资料
问题讨论,stm32的资料领取可以私信!
系统工作原理
-
路径检测:通过红外传感器检测迷宫中的路径(通常为黑线)。当检测到路径时,小车继续沿路径前进;如果没有检测到路径,则通过决策模块选择转向方向。
-
障碍物检测与避障:系统通过超声波传感器实时检测前方的障碍物。如果检测到障碍物,小车会后退并选择左转或右转以避开障碍物。
-
决策与强化学习:小车通过简单的强化学习策略进行路径决策。当执行某一操作(如前进、转弯等)时,根据当前的状态(如障碍物距离、路径状态)给予相应的奖励或惩罚值,从而引导小车逐渐找到最佳的走迷宫策略。
-
状态显示:OLED 显示屏实时显示小车的状态,包括障碍物距离、奖励值等,便于用户调试和查看小车的运行情况。
常见问题与解决方法
1. 路径检测不准确
- 问题原因:红外传感器未正确安装或感应灵敏度不够。
- 解决方法:调整红外传感器的安装位置和检测灵敏度,确保能准确检测到黑线路径。
2. 避障反应迟缓
- 问题原因:超声波传感器检测距离不准确或信号处理不及时。
- 解决方法:确保超声波传感器的信号时序设置正确,并调节超声波的检测频率,及时响应障碍物。
3. 小车无法准确转弯
- 问题原因:电机控制的转向逻辑或 PWM 信号不稳定。
- 解决方法:检查电机驱动模块的接线,确保转向时 PWM 信号平稳,并根据需要调整转弯角度。
扩展功能
-
路径记录与回放:可以增加路径记录功能,将小车的每一步行动记录下来。完成迷宫后,系统可以根据记录的路径进行回放,再次走过最优路径。
-
远程控制与数据上传:通过蓝牙或Wi-Fi模块扩展,可以将小车的状态和路径数据上传到云端,或通过手机进行远程控制。
-
高级学习算法:可以引入更复杂的强化学习算法(如Q-learning或深度强化学习),使小车在走迷宫过程中具有更好的学习和探索能力。
结论
通过本项目,我们设计了一个基于STM32的自学习走迷宫智能小车,能够通过路径检测和避障策略,在迷宫中自动找到出口。系统结合了强化学习算法,使小车能够通过不断的探索和奖励机制找到最优路径,适用于教育、竞赛等场景的智能机器人项目。项目的可扩展性强,未来可以通过引入高级算法、远程控制和路径记录等功能,进一步提升小车的智能化和自动化水平。