当前位置:   article > 正文

基于stm32cubeMX的的HAL库开发的智能小车------超声波避障小车_输入捕获实现超声波避障

输入捕获实现超声波避障

我的第一辆智能小车

提示:小编也是初学者,本文适用于想完成一个基础智能四轮车的初学者,大佬还请勿喷,欢迎各位指出错误的地方

使用的是STM32F103C8T6最小系统板

暑假在家无聊,刚好也在学习STM32的HAL库,就想着做个小车巩固自己学到的知识,顺便记录自己所遇到的错误

小编也是现学现写,准备做一个蓝牙遥控红外寻迹超声波避障小车

注意:这篇文章需要用到定时器输出比较和输入捕获,没有基础可能看不懂。

这篇博客讲述的就是如何去制作超声波避障小车

注意:没有基础的是无法完成的

1,相关传感器的介绍

舵机sg90模块

舵机SG90模块是一种小型舵机,适用于各种机器人和电子设备。它由一个直流电机、减速装置和位置反馈电路组成。该模块可以通过PWM信号来控制舵机的角度,典型的工作范围为0到180度。它具有快速响应、精准定位和稳定性好的特点,能够提供可靠的转动效果。

需要用到的知识:    定时器输出比较----pwm输出

                                                                                                       

使用原理:在PWM周期20MS以内控制有效电平的时间即可控制舵机的转动角度

                  

超声波传感器

工作原理: HC-SR04传感器的工作原理与一般超声波传感器相似,包括发射超声波脉冲和接收反射波。它由超声波发射器和接收器组成,通过测量发射和接收之间的时间差来计算距离。

距离测量范围: HC-SR04传感器的有效测量距离通常在2厘米到4.5米之间,取决于环境条件和具体实现。使用接口: HC-SR04传感器通常通过GPIO口与单片机或其他控制器连接。它需要两个引脚进行数据传输,一个引脚用于发射超声波脉冲,另一个引脚用于接收反射波。

需要使用的知识:定时器输入捕获

使用原理:描述起来比较麻烦,建议看下面的博客

不懂的点击这里

                                                                      

2.相关引脚的分配

舵机SG90模块

VCC                        5V供电

GND

信号线(橙色)            PA8       对应TIM1_CH1

超声波HC_04(新版)

VCC             3.3v-5v供电

GND

TRIG引脚              选用普通IO引脚即可    选用PA12

ECHO引脚            选用定时器引脚       PB5的TIM3_CH2重映射

3.stm32cubeMX的配置

这里是在上一篇----蓝牙小车的基础上完成的

相信大家学到这里了,基本的设置都会配置了

舵机的配置        

选用的是PA8  TIM1_CH1   高级定时器具有通用定时器的全部功能

选择定时器1的通道一的PWM输出模式

设置PSC预分频系数为72-1            ARR的值为20000-1  

PWM频率=72MHZ/(72-1+1)*(20000-1+1)=50hz

PWM周期=1/50hz=20ms

注意:      ARR的值与下面设置转动角度的有关,不懂的建议和我设置的一样

                                       

 超声波传感器的配置

开启定时器3通道2的输入捕获模式

将PSC预分频系数的值设置为72-1

ARR的值设置的65535

 开启定时器3的全局中断,这里不开启的话会导致获取到的超声波避障函数的值为0

4.代码展示部分

舵机部分

duoji.c

  1. #include "duoji.h"
  2. void SG90_GetAngle(float value)
  3. {/* 舵机转向函数*/
  4. /*
  5. PSC:20000-1 ARR:72-1
  6. 0 500
  7. 180 2500
  8. 角度 CCR的值
  9. */
  10. value=value/180*2000+500;
  11. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,value);
  12. /*value=50相当于一个周期内(20ms)有0.5ms高脉冲*/
  13. }
  14. void SG90_Init()
  15. {
  16. SG90_GetAngle(90);
  17. }
  18. void SG90_TurnL()
  19. {
  20. SG90_GetAngle(135);
  21. }
  22. void SG90_TurnR()
  23. {
  24. SG90_GetAngle(45);
  25. }

duoji.h

  1. #ifndef __DUOJI_H_
  2. #define __DUOJI_H_
  3. #include "main.h"
  4. #include "tim.h"
  5. void SG90_GetAngle(float value);
  6. void SG90_Init(void); //舵机头初始化,摆正
  7. void SG90_TurnL(void); //舵机头左转
  8. void SG90_TurnR(void); //舵机头右转
  9. #endif

超声波部分

这部分代码我引用了这个博主的,大家有不懂的点这里

将下面代码添加到tim.c中,复制粘粘到最下面

  1. //[7]:0,没有成功的捕获;1,成功捕获到一次.
  2. //[6]:0,还没捕获到低电平;1,已经捕获到低电平了.
  3. //[5:0]:捕获低电平后溢出的次数
  4. uint8_t TIM3CH2_CAPTURE_STA; // 输入捕获状态
  5. uint16_t TIM3CH2_CAPTURE_VAL; //输入捕获值
  6. //溢出回调函数和捕获回调函数
  7. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  8. {
  9. if ((TIM3CH2_CAPTURE_STA & 0x80) == 0) // 还未捕获成功
  10. {
  11. if (TIM3CH2_CAPTURE_STA & 0x40) // 捕获到一个下降沿
  12. {
  13. if ((TIM3CH2_CAPTURE_STA & 0x3F) == 0x3F) // 高电平的时间太长
  14. {
  15. TIM3CH2_CAPTURE_STA |= 0X80; // 标记为成功捕获一次
  16. TIM3CH2_CAPTURE_VAL = 0XFFFF;
  17. }
  18. else
  19. TIM3CH2_CAPTURE_STA++; // 否则标记溢出数加1
  20. }
  21. }
  22. }
  23. // 捕获中断发生时执行 上升沿复位开始计时,下降沿获取捕获值计算
  24. void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
  25. {
  26. if ((TIM3CH2_CAPTURE_STA & 0X80) == 0) //还未捕获成功 [7]:0,没有成功的捕获;1,成功捕获到一次.
  27. {
  28. if (TIM3CH2_CAPTURE_STA & 0X40) // 成功率捕获到1个下降沿 [6]:0,还没捕获到低电平;1,已经捕获到低电平了.
  29. {
  30. // usart_printf("get down\r\n");
  31. TIM3CH2_CAPTURE_STA |= 0X80; // 标记成功,捕获到1次高电平完成
  32. TIM3CH2_CAPTURE_VAL = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_2); // 捕获当前设置捕获值
  33. TIM_RESET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_2); // 清除原来设置
  34. TIM_SET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_2, TIM_ICPOLARITY_RISING); // 捕获到下降沿之后,将捕获到复位为上升沿
  35. }
  36. else // 捕获到一个上升沿
  37. {
  38. // usart_printf("get up\r\n");
  39. TIM3CH2_CAPTURE_STA = 0;
  40. TIM3CH2_CAPTURE_VAL = 0;
  41. TIM3CH2_CAPTURE_STA |= 0X40; //将STA置为0x40 当下一次触发中断时,会进入上面的if语句
  42. __HAL_TIM_DISABLE(&htim3);
  43. __HAL_TIM_SET_COUNTER(&htim3, 0);
  44. TIM_RESET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_2);
  45. TIM_SET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_2, TIM_ICPOLARITY_FALLING);
  46. __HAL_TIM_ENABLE(&htim3);
  47. }
  48. }
  49. }

将下面的代码添加到main.h中

  1. extern uint8_t TIM3CH2_CAPTURE_STA; // 输入捕获状态
  2. extern uint16_t TIM3CH2_CAPTURE_VAL; //输入捕获值
  3. extern uint8_t unit_change; //单位变换

HCSR04.C

  1. /**
  2. * @file HCSR04.c
  3. * @author Zhong Zepeng (1935595312@qq.com)
  4. * @brief
  5. * @version 0.1
  6. * @date 2022-11-25
  7. *
  8. * @copyright Copyright (c) 2022
  9. *
  10. */
  11. #include "HCSR04.h"
  12. #include "gpio.h"
  13. #include "tim.h"
  14. #include "usart.h"
  15. #include "User_Debug.h"
  16. /**
  17. * @brief 激活超声波定时器
  18. *
  19. */
  20. void HCSR_04()
  21. {
  22. uint32_t i;
  23. HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_SET);
  24. for (i = 0; i < 72 * 40; i++)
  25. __NOP();
  26. HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_RESET);
  27. }
  28. /**
  29. * @brief 关闭超声波定时器
  30. *
  31. */
  32. void Stop_HCSR_04()
  33. {
  34. HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_RESET);
  35. }
  36. /**
  37. * @brief 计算超声波检测的距离
  38. *
  39. * @return float
  40. */
  41. //uint8_t TIM3CH2_CAPTURE_STA; // 输入捕获状态
  42. //uint16_t TIM3CH2_CAPTURE_VAL; //输入捕获值
  43. uint8_t unit_change;
  44. float getSR04Distance()
  45. {
  46. float len = 0;
  47. uint32_t time = 0;
  48. if (TIM3CH2_CAPTURE_STA & 0X80) // 输入捕获 触发
  49. {
  50. time = TIM3CH2_CAPTURE_STA & 0X3f; // 获得溢出次数
  51. time *= 65535; // 一次溢出为65536 得到溢出的时间
  52. time += TIM3CH2_CAPTURE_VAL; // 溢出的时间+现在定时器的值 得到总的时间
  53. if (unit_change == 0)
  54. {
  55. len = (time * 342.62 * 100 / 2000000); // 计算得到距离 cm
  56. }
  57. // else if (unit_change == 1)
  58. // {
  59. // len = time * 342.62 * 100 / 200000000; // 计算得到距离 m
  60. // usart_printf("m\r\n");
  61. // }
  62. TIM3CH2_CAPTURE_STA = 0; // 清除溢出
  63. }
  64. return len;
  65. }

 HCSR04.h

  1. #ifndef __HCSR04_H
  2. #define __HCSR04_H
  3. #include "stdint.h"
  4. void HCSR_04(void);
  5. void Stop_HCSR_04(void);
  6. float getSR04Distance(void);
  7. #endif

main.c

这里我是用函数封装了起来,大家使用的时候在while(1)里调用这个函数就行

因为超声波数据获取的时候有视野盲区,小编在代码方法添加了2个红外传感器防止撞墙

  1. void ultrasonic_waves()
  2. {
  3. //★舵机指向90° 正中间
  4. SG90_Init();
  5. Change_speed(70);
  6. HAL_Delay(700); //延时,不做延时的话,会超过采样频率
  7. HCSR_04(); //激活超声波模块
  8. distance_res[0] = getSR04Distance();
  9. HAL_Delay(10);
  10. if(LR1==0 || LR2==0)
  11. {
  12. HAL_Delay(10);
  13. if(LR1==0)
  14. {
  15. Backward();
  16. HAL_Delay(300);
  17. Turn_Right();
  18. HAL_Delay(200);
  19. }
  20. if(LR2==0)
  21. {
  22. Backward();
  23. HAL_Delay(300);
  24. Turn_Left();
  25. HAL_Delay(200);
  26. }
  27. }
  28. else if(distance_res[0]>35.00)
  29. {
  30. Forward();
  31. }
  32. else if(LR2==1&&LR2==1)//如果前方距离小于30厘米 停车测左右距离
  33. {
  34. Stopward();
  35. SG90_TurnL();//舵机左转45度测距
  36. HAL_Delay(1200);
  37. HCSR_04(); //激活超声波模块
  38. distance_res[1]=getSR04Distance();
  39. HAL_Delay(10);
  40. SG90_TurnR();//舵机右转45度测距
  41. HAL_Delay(1200);
  42. HCSR_04(); //激活超声波模块
  43. distance_res[4]=getSR04Distance();
  44. HAL_Delay(10);
  45. SG90_Init();
  46. if(distance_res[1]>distance_res[4]) //如果左边的距离大于右边的距离
  47. {
  48. SG90_Init(); //舵机摆正
  49. HAL_Delay(700);
  50. HCSR_04(); //激活超声波模块
  51. distance_res[0] =getSR04Distance(); //重复测前方的距离同时左转
  52. HAL_Delay(100);
  53. Turn_Left();
  54. if(distance_res[0]>30.0000)
  55. {
  56. Forward();
  57. }
  58. if(distance_res[1]<distance_res[4]) //如果右边的距离大于左边的距离
  59. {
  60. SG90_Init();
  61. HAL_Delay(700);
  62. HCSR_04(); //激活超声波模块
  63. distance_res[0] =getSR04Distance(); //重复测前方的距离同时右转
  64. HAL_Delay(10);
  65. Turn_Right();
  66. {
  67. Forward();
  68. HCSR_04(); //激活超声波模块
  69. distance_res[0] = getSR04Distance();
  70. HAL_Delay(10);
  71. Turn_Right();
  72. if(distance_res[0]>30.0000)
  73. {
  74. Forward();
  75. }
  76. }
  77. }
  78. }
  79. }
  80. }

5.注意事项

1.舵机信号线使用的定时器不能和超声波传感器使用的一致,不然会导致超声波函数接收到的数据不准确,导致经常撞墙。

2.在获取超声波测距的数据的时候,可以使用USB转TTL转换器,用串口获取准确的数据,数据一定要稳定。

3.供电问题,一定要保证要稳定供电,供电不足会导致传感器无法正常工作

6.寄语

这个功能我调试了很久,相比于前2个功能比较复杂,关于代码,不推荐大家照搬,要根据自己的需求来改,大家有什么疑惑可以发评论区里,看到了我会回复

关于代码部位我已上传,分别关于舵机部分,超声波部分,避障小车部分

代码部分

7.视频展示               

基于stm32的HAL库开发的超声波避障小车

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/46222
推荐阅读
相关标签
  

闽ICP备14008679号