基于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

#include "duoji.h"
void SG90_GetAngle(float value)
{/* 舵机转向函数*/
    /*
    PSC:20000-1          ARR:72-1
        0       500
        180     2500
        角度   CCR的值
    */
   value=value/180*2000+500;
    __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,value);
    /*value=50相当于一个周期内(20ms)有0.5ms高脉冲*/
}
void SG90_Init()
{
   SG90_GetAngle(90); 
}
void SG90_TurnL()
{
   SG90_GetAngle(135); 
}
void SG90_TurnR()
{
   SG90_GetAngle(45); 
}

duoji.h

#ifndef __DUOJI_H_
#define __DUOJI_H_
 
#include "main.h"
#include "tim.h"
void SG90_GetAngle(float value);
void SG90_Init(void);        //舵机头初始化,摆正
void SG90_TurnL(void);        //舵机头左转
void SG90_TurnR(void);        //舵机头右转
#endif


超声波部分

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

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

//[7]:0,没有成功的捕获;1,成功捕获到一次.
//[6]:0,还没捕获到低电平;1,已经捕获到低电平了.
//[5:0]:捕获低电平后溢出的次数
uint8_t TIM3CH2_CAPTURE_STA;  // 输入捕获状态
uint16_t TIM3CH2_CAPTURE_VAL; //输入捕获值
//溢出回调函数和捕获回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if ((TIM3CH2_CAPTURE_STA & 0x80) == 0) // 还未捕获成功
  {
    if (TIM3CH2_CAPTURE_STA & 0x40) // 捕获到一个下降沿
    {
      if ((TIM3CH2_CAPTURE_STA & 0x3F) == 0x3F) // 高电平的时间太长
      {
        TIM3CH2_CAPTURE_STA |= 0X80; // 标记为成功捕获一次
        TIM3CH2_CAPTURE_VAL = 0XFFFF;
      }
      else
        TIM3CH2_CAPTURE_STA++; // 否则标记溢出数加1
    }
  }
}

// 捕获中断发生时执行 上升沿复位开始计时,下降沿获取捕获值计算
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
  if ((TIM3CH2_CAPTURE_STA & 0X80) == 0) //还未捕获成功  [7]:0,没有成功的捕获;1,成功捕获到一次.
  {
    if (TIM3CH2_CAPTURE_STA & 0X40) // 成功率捕获到1个下降沿  [6]:0,还没捕获到低电平;1,已经捕获到低电平了.
    {
      // usart_printf("get down\r\n");
      TIM3CH2_CAPTURE_STA |= 0X80;                                            // 标记成功,捕获到1次高电平完成
      TIM3CH2_CAPTURE_VAL = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_2); // 捕获当前设置捕获值
      TIM_RESET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_2);                       // 清除原来设置
      TIM_SET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_2, TIM_ICPOLARITY_RISING);  // 捕获到下降沿之后,将捕获到复位为上升沿
    }
    else // 捕获到一个上升沿
    {
      // usart_printf("get up\r\n");
      TIM3CH2_CAPTURE_STA = 0;
      TIM3CH2_CAPTURE_VAL = 0;
      TIM3CH2_CAPTURE_STA |= 0X40; //将STA置为0x40 当下一次触发中断时,会进入上面的if语句
      __HAL_TIM_DISABLE(&htim3);
      __HAL_TIM_SET_COUNTER(&htim3, 0);
      TIM_RESET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_2);
      TIM_SET_CAPTUREPOLARITY(&htim3, TIM_CHANNEL_2, TIM_ICPOLARITY_FALLING);
      __HAL_TIM_ENABLE(&htim3);
    }
  }
}

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

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

HCSR04.C

/**
 * @file HCSR04.c
 * @author Zhong Zepeng (1935595312@qq.com)
 * @brief
 * @version 0.1
 * @date 2022-11-25
 *
 * @copyright Copyright (c) 2022
 *
 */
#include "HCSR04.h"
#include "gpio.h"
#include "tim.h"
#include "usart.h"
#include "User_Debug.h"
/**
 * @brief 激活超声波定时器
 *
 */
void HCSR_04()
{
    uint32_t i;
    HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_SET);
    for (i = 0; i < 72 * 40; i++)
        __NOP();
    HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_RESET);
}
/**
 * @brief  关闭超声波定时器
 *
 */
void Stop_HCSR_04()
{
    HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_RESET);
}
/**
 * @brief 计算超声波检测的距离
 *
 * @return float
 */
//uint8_t TIM3CH2_CAPTURE_STA;  // 输入捕获状态
//uint16_t TIM3CH2_CAPTURE_VAL; //输入捕获值
uint8_t unit_change;
float getSR04Distance()
{
    float len = 0;
    uint32_t time = 0;
    if (TIM3CH2_CAPTURE_STA & 0X80) // 输入捕获 触发
    {
        time = TIM3CH2_CAPTURE_STA & 0X3f; // 获得溢出次数
        time *= 65535;                     // 一次溢出为65536 得到溢出的时间
        time += TIM3CH2_CAPTURE_VAL;       // 溢出的时间+现在定时器的值 得到总的时间
        if (unit_change == 0)
        {
            len = (time * 342.62 * 100 / 2000000); // 计算得到距离 cm
        }
//        else if (unit_change == 1)
//        {
//            len = time * 342.62 * 100 / 200000000; // 计算得到距离 m
//            usart_printf("m\r\n");
//        }

        TIM3CH2_CAPTURE_STA = 0; // 清除溢出
    }
    return len;
}

 HCSR04.h

#ifndef __HCSR04_H
#define __HCSR04_H

#include "stdint.h"


void HCSR_04(void);
void Stop_HCSR_04(void);
float getSR04Distance(void);

#endif

main.c

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

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

void ultrasonic_waves()
{
    //★舵机指向90° 正中间
    SG90_Init();
    Change_speed(70);
    HAL_Delay(700); //延时,不做延时的话,会超过采样频率
    HCSR_04();      //激活超声波模块
    distance_res[0] = getSR04Distance();
    HAL_Delay(10);
    
    
    if(LR1==0 || LR2==0)
    {
       HAL_Delay(10);
       if(LR1==0)
       {
           Backward();
           HAL_Delay(300);
           Turn_Right();
           HAL_Delay(200);
       }
        if(LR2==0)
       {
           Backward();
           HAL_Delay(300);
           Turn_Left();
           HAL_Delay(200);
       }
    }
    else if(distance_res[0]>35.00)
    {
      Forward();  
    }

   else if(LR2==1&&LR2==1)//如果前方距离小于30厘米  停车测左右距离
   {
       
       Stopward();
       SG90_TurnL();//舵机左转45度测距
       HAL_Delay(1200);
        HCSR_04();      //激活超声波模块
       distance_res[1]=getSR04Distance();
       HAL_Delay(10);
       
       SG90_TurnR();//舵机右转45度测距
       HAL_Delay(1200);
        HCSR_04();      //激活超声波模块
       distance_res[4]=getSR04Distance();
       HAL_Delay(10);
       SG90_Init(); 


        if(distance_res[1]>distance_res[4])    //如果左边的距离大于右边的距离
        {
            SG90_Init(); //舵机摆正
            HAL_Delay(700);
            HCSR_04();      //激活超声波模块
            distance_res[0] =getSR04Distance();	//重复测前方的距离同时左转
            HAL_Delay(100);					
			Turn_Left();
            if(distance_res[0]>30.0000)
            {
                 Forward(); 
            }

        if(distance_res[1]<distance_res[4])    //如果右边的距离大于左边的距离
        {
            SG90_Init();
            HAL_Delay(700);
            HCSR_04();      //激活超声波模块
            distance_res[0] =getSR04Distance();  //重复测前方的距离同时右转
            HAL_Delay(10);		           
			Turn_Right();
            {
              Forward();  
              HCSR_04();      //激活超声波模块
              distance_res[0] = getSR04Distance();
              HAL_Delay(10);
              Turn_Right();
             if(distance_res[0]>30.0000)
            {
                 Forward(); 
            }
            }
        }
    }
   } 

}

5.注意事项

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

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

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

6.寄语

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

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

代码部分

7.视频展示               

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

  • 8
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值