STM32超声波避障小车(stm32f103c8t6/HAL/舵机云台+超声波)

系列文章目录

一、小车1.0——基本蓝牙小车(仅蓝牙遥控小车运动方向)
二、小车2.0——蓝牙小车PLUS(可以蓝牙控制方向+蓝牙直接调节车速)
三、小车3.0——避障小车(超声波+舵机云台)
四、小车4.0——手柄方向感知操控小车(mpu6050+双蓝牙透传)


文章目录

  • 系列文章目录
  • 前言
  • 一、前期准备
  • 二、CubeMX中的设置
    • 2.1. 时钟树的配置
    • 2.2. TIM的设置
      • 2.2.1. TIM2设置
      • 2.2.2. TIM3设置
      • 2.2.3. TIM4设置
    • 2.3. INx分配的GPIO参数配置
      • 2.3.1. INx设置:
      • 2.3.2. Trig设置:
  • 三、代码
    • 总体项目代码结构
    • 3.1. 超声波输入捕获代码
      • chaoshengbo.h
      • chaoshengbo.c
    • 3.2. 舵机PWM代码
    • 3.3. us级延时函数代码
      • delay.h
      • delay.c
    • 3.4. 小车驱动
    • 3.5. main.c
  • 总结


前言

提示:学习这篇文章《超声波避障小车》之前还需要掌握小车驱动以及超声波测距的相关内容

学习完HC-SR04超声波模块的使用以及怎样驱动小车之后,就可以通过简单的代码实现基础的蓝牙避障小车了。
HC-SR04超声波模块的使用详见----->《超声波模块的使用》
小车驱动程序的讲解详见 ----------->小车驱动(这个链接是蓝牙小车的,驱动部分不用看usart中内容)


提示:以下是本篇文章正文内容,下面案例可供参考

一、前期准备

需要准备
STM32F103C8T6 —————————— 1个
12V电池————–—————————— 1个
L298N电机驱动 ——————————— 2个
小车底座 —————————————— 1个
稳压模块或者可调降压模块 —————— 1个
超声波模块HC-SR04————————— 1个
舵机SG90 -————————————— 1个

二、CubeMX中的设置

2.1. 时钟树的配置

(1)点击RCC开启HSE和LSE,并选择RC或晶体作为时钟源
STM32超声波避障小车(stm32f103c8t6/HAL/舵机云台+超声波)_第1张图片
(2)配置时钟树
STM32超声波避障小车(stm32f103c8t6/HAL/舵机云台+超声波)_第2张图片

最终最右侧显示为
STM32超声波避障小车(stm32f103c8t6/HAL/舵机云台+超声波)_第3张图片

2.2. TIM的设置

2.2.1. TIM2设置

(1)点击TIM2,在Mode选项中设置Clock Source为Internal Clock。设置Channel1为PWM Generation CH1,Channel2为PWM Generation CH2,其余默认即可。
STM32超声波避障小车(stm32f103c8t6/HAL/舵机云台+超声波)_第4张图片
(2)在Mode下面的Configuration选项中Parameter Settings的参数设置
STM32超声波避障小车(stm32f103c8t6/HAL/舵机云台+超声波)_第5张图片
(3)TIM2 的GPIO参数设置
CH1,CH2都设置为推挽输出,高速
在这里插入图片描述
STM32超声波避障小车(stm32f103c8t6/HAL/舵机云台+超声波)_第6张图片

2.2.2. TIM3设置

(1)点击TIM3,在Mode选项中设置Clock Source为Internal Clock。
STM32超声波避障小车(stm32f103c8t6/HAL/舵机云台+超声波)_第7张图片
(2)在Mode下面的Configuration选项中Parameter Settings的参数设置
STM32超声波避障小车(stm32f103c8t6/HAL/舵机云台+超声波)_第8张图片
(3)TIM3中NVIC设置
STM32超声波避障小车(stm32f103c8t6/HAL/舵机云台+超声波)_第9张图片

2.2.3. TIM4设置

(1)点击TIM4,在Mode选项中设置Clock Source为Internal Clock,并将TIM4_CH4设置为输入捕获模式
STM32超声波避障小车(stm32f103c8t6/HAL/舵机云台+超声波)_第10张图片

(2)在Mode下面的Configuration选项中Parameter Settings的参数设置
STM32超声波避障小车(stm32f103c8t6/HAL/舵机云台+超声波)_第11张图片
(3)TIM4中NVIC设置
在这里插入图片描述
(4)TIM4 的GPIO参数设置
STM32超声波避障小车(stm32f103c8t6/HAL/舵机云台+超声波)_第12张图片

2.3. INx分配的GPIO参数配置

注意:这里的GPIO设置只用添加电机模块的INx以及超声波的发送端Trig,其余的已经在TIM的设置中配置过了

2.3.1. INx设置:

8个INx与PA11的参数设置一致,但是User Label不一样,对应如下:
IN1——PA8
IN2——PA12
IN3——PA13
IN4——PA14
IN11——PA15
IN22——PB0
IN33——PB1
IN44——PB2
STM32超声波避障小车(stm32f103c8t6/HAL/舵机云台+超声波)_第13张图片
最终结果为:
STM32超声波避障小车(stm32f103c8t6/HAL/舵机云台+超声波)_第14张图片

2.3.2. Trig设置:

STM32超声波避障小车(stm32f103c8t6/HAL/舵机云台+超声波)_第15张图片

自此就全部设置完了
最终:

STM32超声波避障小车(stm32f103c8t6/HAL/舵机云台+超声波)_第16张图片

三、代码

注意:这里我仅添加了超声波输入捕获测距程序和舵机PWM调速,小车驱动的程序见前言的链接

总体项目代码结构

STM32超声波避障小车(stm32f103c8t6/HAL/舵机云台+超声波)_第17张图片

3.1. 超声波输入捕获代码

chaoshengbo.h

#ifndef CHAOSHENGBO_CHAOSHENGBO_H_
#define CHAOSHENGBO_CHAOSHENGBO_H_

#include "stm32f1xx_hal.h" //HAL库文件声明
#include 
#include "../delay/delay.h"


#define TRIG_ON  HAL_GPIO_WritePin(GPIOB, TRIG_Pin, GPIO_PIN_SET)   //定义TRIG输出高电平
#define TRIG_OFF  HAL_GPIO_WritePin(GPIOB, TRIG_Pin, GPIO_PIN_RESET)//定义TRIG输出低电平
extern TIM_HandleTypeDef htim4;//声明TIM4的HAL库结构体
extern TIM_HandleTypeDef htim3;//声明TIM3的HAL库结构体

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);//定时器中断回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim);//定时器输入捕获中断回调函数

#endif /* CHAOSHENGBO_CHAOSHENGBO_H_ */

chaoshengbo.c

#include "chaoshengbo.h"


/********************************************************************************************
 *设置变量
 *distances:超声波所测距离
 *t        :回响信号脉冲持续时间
 *high_time[0]:回响信号脉冲上升沿发生时间
 *high_time[1]:回响信号脉冲下降沿发生时间
 *c_values :标志值,用于定时器输入捕获回调函数

 ********************************************************************************************/
float distances;
uint32_t t=0;
uint32_t high_time[2]={0};
uint8_t c_values=0;

/********************************************************************************************
 * 定时器中断回调函数 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
 *
 * 说明:
 * 因为SR04每次发送超声波的时间间隔要大于60ms,
 * 故通过Cube MX 已经将TIM3设置为100ms的定时器,每隔100ms才执行一次这个定时器中断回调函数
 * 即每隔100ms发送一个20us的高电平脉冲,同时开启定时器4输入捕获并设置为上升沿捕获
 *
 ********************************************************************************************/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{


	if(htim==&htim3)                      //判断是否为TIM3溢出中断
	{
		TRIG_OFF;                         //先将超声波模块SR04的发送端TRIG拉低
		TRIG_ON;                          //再将超声波模块SR04的发送端TRIG拉高,并且持续20ms后再拉低
		delay_us(20);
		TRIG_OFF;
		__HAL_TIM_SET_CAPTUREPOLARITY(&htim4,TIM_CHANNEL_4,TIM_ICPOLARITY_RISING);//设置为上升沿捕获
		HAL_TIM_IC_Start_IT(&htim4,TIM_CHANNEL_4);//开启定时器输入捕获

	}

}

/********************************************************************************************
 * 定时器输入捕获回调函数 void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
 *
 *说明:
 *ECHO接收回响信号脉冲,这个回调函数要被执行2次
 *这个回调函数在类似于一个分叉路口,上升沿捕获走路口0,下降沿捕获走路口1
 *
 ********************************************************************************************/
	void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
	{
		if(htim==&htim4)
		{
			switch(c_values)
			{//标志值c_values初始设定值为0,上升沿输入捕获,先执行回调函数执行case(0)中内容

			case(0): high_time[0]=HAL_TIM_ReadCapturedValue(&htim4,TIM_CHANNEL_4);//获取上升沿的捕获值,即接收的高电平开始时间
			         __HAL_TIM_SET_CAPTUREPOLARITY(&htim4,TIM_CHANNEL_4,TIM_ICPOLARITY_FALLING);//设置为下降沿捕获
			         c_values++;//标志值c_values值变为1,下次回调函数执行case(1)中内容
			         break;


			case(1): high_time[1]=HAL_TIM_ReadCapturedValue(&htim4,TIM_CHANNEL_4);//获取下降沿的捕获值,即接收的高电平结束时间
			         HAL_TIM_IC_Stop_IT(&htim4,TIM_CHANNEL_4); //关闭TIM4输入捕获
			         c_values=0;                 //标志值清零,用于下次输入捕获回调函数
			         htim4.Instance->CNT=0;      //TIM4计数值清零
				     t=high_time[1]-high_time[0];//下降沿捕获值-上升沿捕获值=回响信号高电平脉冲持续时间t
				     distances= t*0.017; //速度0.034cm/us,计算出的距离要除以2,distances的单位是cm
			         break;
			default: break;
			}
		}
	}

3.2. 舵机PWM代码

我直接将这个舵机PWM调速.c写到了control.c中

	void SG90_Init()//舵机转90°
	{
		__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2,1500);  //sg90是逆时针转动
	}
	void SG90_Turn_L()//舵机转135°
	{
		__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2,2000);
	}
	void SG90_Turn_R()//舵机转45°
	{
		__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2,1000);
	}


3.3. us级延时函数代码

delay.h

#ifndef DELAY_DELAY_H_
#define DELAY_DELAY_H_

#include "stm32f1xx_hal.h" HAL库文件声明
void delay_us(uint32_t us); //us级延时函数

#endif /* DELAY_DELAY_H_ */

delay.c

#include "delay.h"

void delay_us(uint32_t us) //利用CPU循环实现的非精准应用的微秒延时函数
{
    uint32_t delay = (HAL_RCC_GetHCLKFreq() / 8000000 * us); //使用HAL_RCC_GetHCLKFreq()函数获取主频值,经算法得到1微秒的循环次数
    while (delay--); //循环delay次,达到1微秒延时
}

3.4. 小车驱动

略,小车驱动的程序见前言的链接,我写的《蓝牙小车》中有十分详细的介绍,
唯一不同的是因为TIM2设置的预分频以及计时周期的不同,__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1,5000);的设定值有所改变。

3.5. main.c

/* USER CODE BEGIN Includes */
#include "../../icode/control/control.h"
#include "../../icode/chaoshengbo/chaoshengbo.h"
/* USER CODE END Includes */



/* USER CODE BEGIN 1 */
extern  float distances;
uint32_t S=20;//设定距离标准值
uint32_t LS,RS=0;//测定的左右两边距离值
/* USER CODE END 1 */



/* USER CODE BEGIN 2 */

HAL_TIM_Base_Start_IT(&htim3);//开启定时器3中断
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); //直流电机PWM
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2); //SG90PWM
SG90_Init();//SG90舵机初始化,也就是转90°,朝向小车前方
CAR_STOP();
HAL_Delay(500);

/* USER CODE END 2 */
	


while (1)
{
  /* USER CODE END WHILE */
  /* USER CODE BEGIN 3 */
	if(distances>S)
	{
	    CAR_GO();
	}
	else
	{
	    CAR_STOP();
	    SG90_Turn_L();
	    HAL_Delay(1500);
	    LS=distances;
	    SG90_Turn_R();
	    HAL_Delay(1500);
	    RS=distances;
	    SG90_Init();
	
	    if(LS>RS&&LS>S)
	    {
	  	  CAR_LGO();
	  	  HAL_Delay(500);
	    }
	    else if(RS>LS&&RS>S)
	    {
	  	  CAR_RGO();
	  	  HAL_Delay(500);
	    }
	    else
	    {
	  	  CAR_BACK();
	  	  HAL_Delay(500);
	    }
	}
  }
  /* USER CODE END 3 */


总结

总体说来,这个避障小车的避障功能不是很完善,还存在一些视野盲区。因为通过舵机的转动,超声波模块只能监测到小车车头90°的范围,只能算是个半成品吧,这个项目目前是将所学的PWM控制,以及超声波整合在一起作为一个小整体,也算是小车之路的必经处吧。。。

欢迎大家积极交流,本文未经允许谢绝转载!!!

你可能感兴趣的:(各种STM32小车,单片机,stm32)