stm32之智能小车总结

        作为学习stm32f103c8t6阶段的收官项目,这里做下总结,源码放在了最后。

一、功能描述

  • 1、跟随功能
  • 2、循迹功能
  • 3、避障功能
  • 4、测速功能
  • 5、温湿度常显
  • 6、oled显示
  • 7、语音或蓝牙进行功能切换

二、主要代码解析

2.1、main

main函数主要展示while里的功能,具体的实现在car_function文件内。

int main(void)
{HAL_Init();MX_GPIO_Init();MX_USART1_UART_Init();MX_TIM2_Init();MX_TIM4_Init();MX_TIM1_Init();MX_TIM3_Init();MX_I2C1_Init();init();while (1){get_mode();reset();switch(runMode) {case tracingMode: traceing();break;case followMode:follow();break;case avoidMode:avoid();break;case stopMode:stop_car();break;}display_temp_humi();}
}

2.2、init

        初始化一个是要开启串口中断,另外要把电机旋转90让超声波正对前方,再者就是显示空数据。

这里没有开启测速的中断TIM3,因为开启会影响DHT11的时序,导致其卡死到检测温湿度的while循环里。

void init() {//开启串口中断蓝牙在用HAL_UART_Receive_IT(&huart1, &buf, 1);//开启pwm,并旋转至最前方sg90_init();//初始化oledoled_init();oled_clear_all();oled_show_string(1,2,"mode : ready");oled_show_string(2,2, "speed:   0cm/s");oled_show_string(3,2, "Temp :--.--");oled_show_string(4,2, "Temp :--.--");
}

2.3、display_temp_humi

        停止模式时,温湿度正常在main 函数里正常检测,在小车的其它模式,要限制温湿度检测的频率,否则会影响小车的运行。小车的其它模式要比温湿度优先级高。在非停止模式时,这里会计数,当计数到50w次时才会进行一次检测。

void display_temp_humi() {// 停止模式时正常检测湿度,非停止模式,计数50w检测一次if(runMode != stopMode) {count ++;if(count <= 500000) { return; }count = 0;} count = 0;//记得关中断,否则会影响DHT11采集数据HAL_TIM_Base_Stop_IT(&htim3);char msg[16];uint8_t result = trig_dht();receive_data();oled_clear(4, 8, 56, 128);sprintf(msg, "Temp : %d.%d C", datas[2], datas[3]);oled_show_string(3,2,msg);sprintf(msg, "Humi : %d.%d %%", datas[0], datas[1]);oled_show_string(4,2,msg);;HAL_Delay(500);
}

 2.4、changeMode

        切换电机的模式,PWM 是变速模式,主要用在寻迹模式,NORMAL是正常模式,用在跟随和避障模式。L0110s 部分引脚要接入到stm32具体pwm功能的引脚上。模式的切换要重新初始化相应的引脚。

void changeMode(uint8_t m) {mode = m;if(mode == NORMAL) {HAL_TIM_PWM_Stop(&htim2,TIM_CHANNEL_1);HAL_TIM_PWM_Stop(&htim2,TIM_CHANNEL_2);init_port();} else {MX_TIM2_Init();HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);HAL_Delay(500);}
}

2.5、测速

定时器1s,查看外部中断进入了多少次。即可算出速度(当前测速模块有问题,速度偏大)

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {// 展示速度//oled部分清屏sprintf(speedString, "speed:%4dcm/s", speedCnt);//old__clear_bottom_half();oled_show_string(2,2,speedString);speedCnt = 0;
}void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {if(GPIO_Pin != GPIO_PIN_10) {return ;}if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_10) == GPIO_PIN_RESET)speedCnt++;
}

2.6、循迹

循迹用的是pwm模式,原理是利用红外发射的光线有没有反射回来。

void traceing() {if(runMode != lastMode) {lastMode = runMode;changeMode(PWM);HAL_Delay(500);// 处理oledoled_clear_1_line();oled_show_string(1,2,"mode : trace");}if(leftTraceValue() == GPIO_PIN_RESET && rightTraceValue() == GPIO_PIN_RESET) {forward();}if(leftTraceValue() == GPIO_PIN_RESET && rightTraceValue() == GPIO_PIN_SET) {leftward();}if(leftTraceValue() == GPIO_PIN_SET && rightTraceValue() == GPIO_PIN_RESET) {rightward();}if(leftTraceValue() == GPIO_PIN_SET && rightTraceValue() == GPIO_PIN_SET) {stop();}
}

2.7、避障

主要是利用超声波检测左前右的障碍物的距离来决定如何前进。

void avoid() {if(runMode != lastMode) {lastMode = runMode;changeMode(NORMAL);// 处理oledoled_clear_1_line();oled_show_string(1,2,"mode : avoid");HAL_Delay(500);}if(dir != MIDDLE) {dir = MIDDLE;turn_90_degree();HAL_Delay(300);}disMiddle = get_distance();if(disMiddle > 35) {forward();} else if(disMiddle < 10) {backward();} else {stop();turn_180_degree();HAL_Delay(300);disLeft = get_distance();turn_90_degree();HAL_Delay(300);turn_0_degree();dir = RIGHT;HAL_Delay(300);disRight = get_distance();if(disLeft < disRight) {rightward();HAL_Delay(150);stop();} if(disLeft > disRight){leftward();HAL_Delay(150);stop();}}}

2023-10-2 13点 超声波中断


void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {//脉冲测速if(GPIO_Pin == GPIO_PIN_10) {if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_10) == GPIO_PIN_RESET)speedCnt++;}//超声波echoif(GPIO_Pin == GPIO_PIN_12) {//while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_12) == GPIO_PIN_RESET);HAL_TIM_Base_Start(&htim1);__HAL_TIM_SetCounter(&htim1, 0);while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_12) == GPIO_PIN_SET);HAL_TIM_Base_Stop(&htim1);int cnt = __HAL_TIM_GetCounter(&htim1);distance = 340 * 0.000001 * cnt * 100 / 2;}}

2.8、跟随

原理同循迹,so esay。

void follow() {if(runMode != lastMode) {lastMode = runMode;changeMode(NORMAL);// 处理oledoled_clear_1_line();oled_show_string(1,2,"mode : follow");HAL_Delay(100);}if(leftFollowValue() == GPIO_PIN_RESET && rightFollowValue() == GPIO_PIN_RESET) {forward();}if(leftFollowValue() == GPIO_PIN_RESET && rightFollowValue() == GPIO_PIN_SET) {leftward();}if(leftFollowValue() == GPIO_PIN_SET && rightFollowValue() == GPIO_PIN_RESET) {rightward();}if(leftFollowValue() == GPIO_PIN_SET && rightFollowValue() == GPIO_PIN_SET) {stop();}
}

三、效果

stm32小车

   

四、问题记录

1、计数定时器(TIM3)中断影响DHT11单总线的时序,导致会卡死到检测温度的while里,导致执行不了main函数里while的其它功能(小车模式切换),但是定时器中断还是可以运行的。

2、同理也会卡超声波while,所以开启避障模式时也要把TIM3关了。(利用外部中断,不用再关TIM)

3、PWM模式和GPIO的功能切换,起初以为只能在初始化里使用一种模式,但在调试之后发现是可以进行转换的。

4、oled是可以进行局部清屏的,oled清屏函数记录-CSDN博客。

5、修改蓝牙波特率,用错了指令,导致一直未成功。HC08 AT指令

6、触发DHT11和获取数据之间不能插入printf函数,否则会卡死到 while 循环里,效果同1

7、小车变速PWM模式时,在使用CubeMx配置引脚时,要把所有引脚输出低电平,否则PWM会不起作用。

8、面板包接线容易松动,导致语音模式引脚输出的电平乱跳。

9、单片机和直流电机单独供电,防止因为电机电流的问题导致单片机复位。

五、配置

跟随功能:

PB5 : 左红外传感器,输入模式

PA15: 右红外传感器,输入模式

循迹功能(原理和跟随一样):

PB3 : 左红外传感器,输入模式

PB4: 左红外传感器,输入模式

避障功能:

        超声波

   PA11 : sr04中的trig引脚,输出模式

   PA12: sr04中的echo引脚,输入模式(外部中断模式)

   TIM1: 用来超声波的计时

        舵机

   PA11 : sr04中的trig引脚,输出模式

   PA15: sr04中的echo引脚,输入模式

   TIM4: channel 4用来控制舵机的旋转角度

温湿度功能(DHT11):

PA8 : dht11中的Data引脚,(初始化时先配置成输入模式!!!,在需要的时候再切换成输出模式)

Oled

PB6(SCL) : 使用stm32 IIC1接口中的SCL

PB7(SDA): 使用stm32 IIC1接口中的SDA

蓝牙(hc04)

PA9(USART1_TX) : 使用stm32 串口1中的输出

PA10(USART1_RX): 使用stm32 串口1中的输入

语音(su03)

PB11: 对应su03的a25引脚,输入模式

PB12: 对应su03的a26引脚,输入模式

PB13: 对应su03的a27引脚,输入模式

直流电机 和 L9110S模块

PA0: 对应L9110s的B-1B引脚,TIM2中channle 1 的PWM模式

PA1: 对应L9110s的A-1B引脚,TIM2中channle 2 的PWM模式

PB0: 对应L9110s的B-1A引脚

PB2: 对应L9110s的A-1A引脚

l9110s中接线会影响电机的前进和后退,根据实际情况来处理引脚的配置,这里PA0 和 PA1 是控制前面的速度,PB0和PB2没有进行控制 

完整代码Github ----smart_car

Release 0.0.1 · barry-source/embedded (github.com)

六、修订

2023-10-2 13点:将超声波回应利用外部中断方式,这样在避障模式下,也可以进行测速

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

C# 读取Execl文件3种方法

方法 1&#xff0c;使用OLEDB可以对excel文件进行读取 1.1C#提供的数据连接有哪些 对于不同的.net数据提供者&#xff0c;ADO.NET采用不同的Connection对象连接数据库。这些Connection对我们屏蔽了具体的实现细节&#xff0c;并提供了一种统一的实现方法。 Connection类有四…

【Linux】线程池

目录 一、线程池1.什么是线程池2.线程池图解3.实现代码 二、单例模式1.单例模式的概念2.饿汉方式实现单例模式3.懒汉方式实现单例模式4.懒汉方式实现单例模式的线程池 一、线程池 1.什么是线程池 线程虽然比进程轻量了很多&#xff0c;但是每创建一个线程时&#xff0c;需要向…

UCOS的任务创建和删除

一、任务创建和删除的API函数 1、任务创建和删除本质就是调用uC/OS的函数 API函数 描述 OSTaskCreate() 创建任务 OSTaskDel() 删除任务 注意&#xff1a; 1&#xff0c;使用OSTaskCreate() 创建任务&#xff0c;任务的任务控制块以及任务栈空间所需的内存&#xff0c…

算法——买卖股票问题

309. 买卖股票的最佳时机含冷冻期 - 力扣&#xff08;LeetCode&#xff09; 一、 究其就是个动态规划的问题 算法实现图 初始化 由于有三个阶段&#xff0c;买入&#xff0c;可交易&#xff0c;冷冻期&#xff0c;那么用dp表表示现在为止的最大利润&#xff0c;则有 dp[0][…

asp.net core 远程调试

大概说下过程&#xff1a; 1、站点发布使用Debug模式 2、拷贝到远程服务器&#xff0c;以及iis创建站点。 3、本地的VS2022的安装目录&#xff1a;C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE下找Remote Debugger 你的服务器是64位就拷贝x64的目…

详解Linux的系统调用fork()函数

在Linux系统中&#xff0c;fork()是一个非常重要的系统调用&#xff0c;它的作用是创建一个新的进程。具体来说&#xff0c;fork()函数会在当前进程的地址空间中复制一份子进程&#xff0c;并且这个子进程几乎完全与父进程相同&#xff0c;包括进程代码、数据、堆栈以及打开的文…

WebSocket实战之四WSS配置

一、前言 上一篇文章WebSocket实战之三遇上PAC &#xff0c;碰到的问题只能上安全的WebSocket&#xff08;WSS&#xff09;才能解决&#xff0c;配置证书还是挺麻烦的&#xff0c;主要是每年都需要重新更新证书&#xff0c;我配置过的证书最长有效期也只有两年&#xff0c;搞不…

ElasticSearch第四讲:ES详解:ElasticSearch和Kibana安装

ElasticSearch第四讲&#xff1a;ES详解&#xff1a;ElasticSearch和Kibana安装 本文是ElasticSearch第四讲&#xff1a;ElasticSearch和Kibana安装&#xff0c;主要介绍ElasticSearch和Kibana的安装。了解完ElasticSearch基础和Elastic Stack生态后&#xff0c;我们便可以开始…

ctfshow—1024系列练习

1024 柏拉图 有点像rce远程执行&#xff0c;有四个按钮&#xff0c;分别对应四份php文件&#xff0c;开始搞一下。一开始&#xff0c;先要试探出 文件上传到哪里&#xff1f; 怎么读取上传的文件&#xff1f; 第一步&#xff1a;试探上传文件位置 直接用burp抓包&#xff0c;…

力扣练习——链表在线OJ

目录 提示&#xff1a; 一、移除链表元素 题目&#xff1a; 解答&#xff1a; 二、反转链表 题目&#xff1a; 解答&#xff1a; 三、找到链表的中间结点 题目&#xff1a; 解答&#xff1a; 四、合并两个有序链表&#xff08;经典&#xff09; 题目&#xff1a; 解…

【数据结构---排序】很详细的哦

本篇文章介绍数据结构中的几种排序哦~ 文章目录 前言一、排序是什么&#xff1f;二、排序的分类 1.直接插入排序2.希尔排序3.选择排序4.冒泡排序5.快速排序6.归并排序总结 前言 排序在我们的生活当中无处不在&#xff0c;当然&#xff0c;它在计算机程序当中也是一种很重要的操…

聊聊常见的IO模型 BIO/NIO/AIO 、DIO、多路复用等IO模型

聊聊常见的IO模型 BIO/NIO/AIO/DIO、IO多路复用等IO模型 文章目录 一、前言1. 什么是IO模型2. 为什么需要IO模型 二、常见的IO模型1. 同步阻塞IO&#xff08;Blocking IO&#xff0c;BIO&#xff09;2. 同步非阻塞IO&#xff08;Non-blocking IO&#xff0c;NIO&#xff09;3.…

排序算法之【希尔排序】

&#x1f4d9;作者简介&#xff1a; 清水加冰&#xff0c;目前大二在读&#xff0c;正在学习C/C、Python、操作系统、数据库等。 &#x1f4d8;相关专栏&#xff1a;C语言初阶、C语言进阶、C语言刷题训练营、数据结构刷题训练营、有感兴趣的可以看一看。 欢迎点赞 &#x1f44d…

八大排序源码(含优化)

文章目录 1、直接插入排序2、希尔排序3、选择排序4、冒泡排序5、堆排序6、快速排序快速排序递归实现霍尔法挖坑法前后指针法快速排序小区间优化 快速排序非递归实现 7、归并排序归并排序递归实现归并排序非递归 8、计数排序 大家好&#xff0c;我是纪宁&#xff0c;这篇文章是关…

java Spring Boot 自动启动热部署 (别再改点东西就要重启啦)

上文 java Spring Boot 手动启动热部署 我们实现了一个手动热部署的代码 但其实很多人会觉得 这叫说明热开发呀 这么捞 写完还要手动去点一下 很不友好 其实我们开发人员肯定是希望重启这种事不需要自己手动去做 那么 当然可以 我们就让它自己去做 Build Project 这个操作 我们…

Linux性能优化--性能工具:系统内存

3.0.概述 本章概述了系统级的Linux内存性能工具。本章将讨论这些工具可以测量的内存统计信息&#xff0c;以及如何使用各种工具收集这些统计结果。阅读本章后&#xff0c;你将能够&#xff1a; 理解系统级性能的基本指标&#xff0c;包括内存的使用情况。明白哪些工具可以检索…

Java21 新特性

文章目录 1. 概述2. JDK21 安装与配置3. 新特性3.1 switch模式匹配3.2 字符串模板3.3 顺序集合3.4 记录模式&#xff08;Record Patterns&#xff09;3.5 未命名类和实例的main方法&#xff08;预览版&#xff09;3.6 虚拟线程 1. 概述 2023年9月19日 &#xff0c;Oracle 发布了…

电子计算机核心发展(继电器-真空管-晶体管)

目录 继电器 最大的机电计算机之一——哈弗Mark1号&#xff0c;IBM1944年 背景 组成 性能 核心——继电器 简介 缺点 速度 齿轮磨损 Bug的由来 真空管诞生 组成 控制开关电流 继电器对比 磨损 速度 缺点 影响 代表 第一个可编程计算机 第一个真正通用&am…

使用晶体管做布尔逻辑和逻辑门

目录 二进制&#xff0c;三进制&#xff0c;五进制 true&#xff0c;false表示0&#xff0c;1 早期计算机采用进制 布尔逻辑 三个基本操作&#xff1a;NOT,AND,OR 基础“真值表” NOT 如何实现&#xff1f; AND如何实现&#xff1f; OR如何实现&#xff1f; 图标表示…

LLM之Colossal-LLaMA-2:Colossal-LLaMA-2的简介、安装、使用方法之详细攻略

LLM之Colossal-LLaMA-2&#xff1a;Colossal-LLaMA-2的简介、安装、使用方法之详细攻略 导读&#xff1a;2023年9月25日&#xff0c;Colossal-AI团队推出了开源模型Colossal-LLaMA-2-7B-base。Colossal-LLaMA-2项目的技术细节&#xff0c;主要核心要点总结如下: >> 数据处…