基于STM32的自学习走迷宫智能小车设计

引言

本项目设计了一个基于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的自学习走迷宫智能小车,能够通过路径检测和避障策略,在迷宫中自动找到出口。系统结合了强化学习算法,使小车能够通过不断的探索和奖励机制找到最优路径,适用于教育、竞赛等场景的智能机器人项目。项目的可扩展性强,未来可以通过引入高级算法、远程控制和路径记录等功能,进一步提升小车的智能化和自动化水平。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/891708.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据质量差的代价是什么?

如今&#xff0c;许多数字企业都认为自己是数据驱动的。通过各种软件解决方案&#xff0c;数据无处不在&#xff0c;收集起来也非常方便&#xff0c;这使得企业能够被动地收集大量数据&#xff0c;并将其应用于决策制定。 然而&#xff0c;人们往往很容易在不考虑数据质量的情…

Light灯光组件+组件的相关操作+游戏资源的加载

Light灯光组件 Type: Directional:平行光&#xff0c;模仿的是太阳光 Spot:聚光灯 Area:区域光 Color&#xff1a; 颜色值 Mode: RealTime:实时 Mix:混合 Baked:烘焙 Intersity: 光照强度 Indirect Multiplier:光照强度乘数 Shadow Type:影子设置&#xff1a;…

云栖实录 | Hologres3.0全新升级:一体化实时湖仓平台

本文根据2024云栖大会实录整理而成&#xff0c;演讲信息如下&#xff1a; 演讲人&#xff1a; 姜伟华 | 阿里云智能集团资深技术专家、Hologres 负责人 丁 烨 | 阿里云智能集团产品专家、Hologres 产品负责人 活动&#xff1a; 2024 云栖大会 - 商用大数据计算与分析平台论…

OpenCV-人脸检测

文章目录 一、人脸检测流程二、关键方法三、代码示例四、注意事项 OpenCV是一个开源的计算机视觉和机器学习软件库&#xff0c;它提供了多种人脸检测方法&#xff0c;以下是对OpenCV人脸检测的详细介绍&#xff1a; 一、人脸检测流程 人脸检测是识别图像中人脸位置的过程&…

git--git reset

HEAD 单独一个HEAD eg:git diff HEAD 表示当前结点。 HEAD~ HEAD~只处理当前分支。 注意&#xff1a;master分支的上一个结点是tmp分支的所在的结点fc11b74, 79f109e才是master的第二个父节点。 HEAD~ 当前结点的父节点。 HEAD~1 当前结点的父节点。 HEAD~n 当前结点索…

kali linux 允许 root 用户登录 安装过程中不能创建 root 根用户密码 之后不能以根用户直接登录 即使是正确的管理员密码也无法登录

打开终端。 输入命令 sudo passwd root 并按回车键。 系统会提示您输入新的 UNIX 密码&#xff0c;输入您想要设置的密码并按回车键。 再次输入相同的密码进行确认。 如果密码设置成功&#xff0c;会显示 “passwd: password updated successfully”。 在登录界面&#xf…

模态与非模态的对话框

本文学习自&#xff1a; 《Qt Creato快速入门》 #include "widget.h" #include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); }1. #include "widget.h" #include "ui_w…

Linux:进程控制(三)——进程程序替换

目录 一、概念 二、使用 1.单进程程序替换 2.多进程程序替换 3.exec接口 4.execle 一、概念 背景 当前进程在运行的时候&#xff0c;所执行的代码来自于自己的源文件。使用fork创建子进程后&#xff0c;子进程执行的程序中代码内容和父进程是相同的&#xff0c;如果子进…

算法: 位运算题目练习

文章目录 位运算判定字符是否唯一丢失的数字两整数之和只出现一次的数字 II消失的两个数字常见位运算总结 位运算 判定字符是否唯一 有很多解法,比如hash表,或者给字符串排个序,然后遍历… 写这道题时没注意到如果出现奇数个相同字符,此时就应该返回false了. 而不是全部放到位…

### 更新数据库时出错。原因:java.sql.SQLException: No database selected

更新数据库时出错。原因&#xff1a;java.sql.SQLException: No database selected 问题&#xff1a;原因&#xff1a;解决办法&#xff1a; 问题&#xff1a; 在基于idea环境中学习搭建mybatis框架时&#xff0c;MySQL数据库执行插入语句遇到以下异常&#xff1a; com.intel…

SMARTFORMS 可选项CONDITION设置条件,根据条件真假显示不一样的内容

文章目录 开发过程执行测试是否输出 开发过程 执行测试 是否输出

前端开发攻略---使用ocr识别图片进行文字提取功能

1、引入资源 通过链接引用 <script src"https://cdn.bootcdn.net/ajax/libs/tesseract.js/5.1.0/tesseract.min.js"></script> npm或其他方式下载 npm i tesseract 2、示例 <!DOCTYPE html> <html lang"en"><head><meta…

PHP智慧餐饮新风尚点餐系统

智慧餐饮新风尚点餐系统 —— 美食与科技的完美碰撞 &#x1f37d;️ 开篇&#xff1a;智慧餐饮的崛起 在快节奏的现代生活中&#xff0c;智慧餐饮正逐渐成为我们日常的一部分。随着科技的飞速发展&#xff0c;餐饮行业也在不断创新&#xff0c;力求为顾客提供更加便捷、高效…

如何微调(Fine-tuning)大语言模型?

从 GPT3 到 ChatGPT、从GPT4 到 GitHub copilot的过程&#xff0c;微调在其中扮演了重要角色。什么是微调&#xff08;fine-tuning&#xff09;&#xff1f;微调能解决什么问题&#xff1f;什么是 LoRA&#xff1f;如何进行微调&#xff1f; 本文将解答以上问题&#xff0c;并…

Go语言基础学习(Go安装配置、基础语法)

一、简介及安装教程 1、为什么学习Go&#xff1f; 简单好记的关键词和语法&#xff1b;更高的效率&#xff1b;生态强大&#xff1b;语法检查严格&#xff0c;安全性高&#xff1b;严格的依赖管理&#xff0c; go mod 命令&#xff1b;强大的编译检查、严格的编码规范和完整的…

数据库的相关知识

数据库的相关知识 1.数据库能够做什么&#xff1f; 存储大量数据&#xff0c;方便检索和访问保持数据信息的一致、完整共享和安全通过组合分析&#xff0c;产生新的有用信息 2.数据库作用&#xff1f; 存储数据、检索数据、生成新的数据 3.数据库要求&#xff1f; 统一、…

leetcode128最长连续序列 golang版

题目描述 题目&#xff1a;给定一个未排序的整数数组 nums 找出数字连续的最长序列&#xff0c;不要求序列 元素在原数组中连续 的长度 请你设计并实现时间复杂度为On的算法解决此问题 示例 1&#xff1a; 输入&#xff1a;nums [100,4,200,1,3,2] 输出&#xff1a;4 解释&…

基于RPA+AI的网页自动填写机器人 | OPENAIGC开发者大赛高校组优秀作品

在第二届拯救者杯OPENAIGC开发者大赛中&#xff0c;涌现出一批技术突出、创意卓越的作品。为了让这些优秀项目被更多人看到&#xff0c;我们特意开设了优秀作品报道专栏&#xff0c;旨在展示其独特之处和开发者的精彩故事。 无论您是技术专家还是爱好者&#xff0c;希望能带给…

软件设计师---知识产权

著作权 著作权&#xff08;也称为版权&#xff09;&#xff1a;是指作者对其创作的作品享有的人身权和财产权。 人身权包括&#xff1a; 发表权&#xff1a;时限是作者终身及其死亡后50年署名权&#xff1a;不受时间限制修改权&#xff1a;不受时间限制保护作品完整权&#…

MFC扩展库BCGControlBar Pro v35.1新版亮点:改进网格控件性能

BCGControlBar库拥有500多个经过全面设计、测试和充分记录的MFC扩展类。 我们的组件可以轻松地集成到您的应用程序中&#xff0c;并为您节省数百个开发和调试时间。 BCGControlBar专业版 v35.1已全新发布了&#xff0c;这个版本改进网格控件的性能、增强工具栏编辑器功能等。 …