前言:本文主要是为了日常普通场合下测距做的对比实验,本实验主要包含2种模块超声波测距模块(HC-SR04)和红外测距模块(SHARP GP2Y0A21YK0F)。两种模块不管是测距原理和编程实验方式都是不相同的,其测距效果也存在很大差异。感兴趣的读者朋友,可以看看这篇文章,文章末尾有实验程序开源

硬件设备:STM32F103C8T6;OLED;超声波模块:HC-SR04和红外测距模块:SHARP GP2Y0A21YK0F

        硬件实物图:

        效果图:

 引脚连接:

超声波HC-SR04模块:

VCC --> VCC

GND --> GND

Trig --> PA5

Echo --> PA0

红外测距SHARP GP2Y0A21YK0F模块:

VCC --> VCC

GND --> GND

Vo(数据) --> PA1

一、超声波测距模块简介

超声波是振动频率高于20KHZ的机械波。它具有频率高、波长短、绕射现象小、方向性好、能够成为射线而定向传播等特点,应用广泛,适合大学生、工程师、技术人员以及电子爱好者等操作。

 新版HC-SRO4,性能远超老版HC-SRO4、US-015,在测距精度高于老版HC-SRO4和US-015的情况下,测距范围更远,可达6米,远超一般超声波测距模块。采用CS-100A超声波测距SOC芯片,高性能,工业级,宽电压、低价格,只有普通超声波测距模块一半的价格,而性能远超普通超声波测距模块。性能与US-025相同,均采用CS100A芯片接口完全兼容

主要参数:

超声波测距芯片:CS100A

工作电压:DC 3V-5.5V

工作电流:5.3mA

工作温度:-40℃-85℃

输出方式:GPI0

感应角度:小于15度

探测距离:2cm~600cm

探测精度:0.1cm+1%

工作原理:

        1、采用IO触发测量距离,给至少10us的高电平;

2、模块自动发送8个40khz的方波,自动检测是否有信号返回;

3、有信号返回、通过lo输出一高电平、高电平持续的时间就是超声波从发射到返回的时间,测试距离=(高电平时间*声速(340M/s)/2);

本模块有一个接口:4Pin供电及通信接口。为2.54mm间距的弯排针,如图所示:从左到右依次编号1、2、3、4,它们的定义如下∶

1号Pin:接VCC电源(直流3V-5.5V)。

2号Pin:接外部电路的Trig端,向此管脚输入一个10uS以上的高电平,可触发模块测距。

3号Pin:接外部电路的Echo端,当测距结束时,此管脚会输出一个高电平,电平宽度为超声波往返时间之和

4号Pin:接外部电路的地。

超声波时序图:

以上时序图表明你只需要提供一个10uS以上脉冲触发信号该模块内部将发出8个40kHz周期电平并检测回波

一旦检测到有回波信号则输出回响信号

回响信号的脉冲宽度与所测的距离正比。由此通过发射信号到收到的回响信号时间间隔可以计算得到距离。

公式: us/58-厘米或者uS/148-英寸;或是:距离=高电平时间*声速(340M/S)/2;

特别注意:

1、此模块不宜带电连接,若要带电连接则先让模块的GND端先连接,否则会影响模块的正常工作。

2、测距时,被测物体的面积不小于0.5平方米且平面尽量要求平整,否则影响测量的结果。

二、红外测距模块简介

GP2YOA21YKOF是测距传感器单元PSD的集成组合构成(位置敏感探测器),IRED((红外发光二极管)和信号处理电路的各种物体的反射率,对环境温度工作时间不易受到影响的距离检测由于采用三角测量方法,这个装置输出对应于该电压检测距离,所以这种传感器还可以来作为接近传感器。

工作电压:4.5~5.5V DC

消耗电流:典型30mA

工作温度:-10~60℃

储存温度:-40~70℃

测量距离:10~80cm10cm内数据盲区

★输出类型:模拟量输出型

 引脚说明:

①Vo:模拟电压输出

②GND:地

③VCC:电源正

输出电压(v)与距离反射物体L (cm)

从上图就可以明显看出,该模块0~10cm内电压与距离不成单调关系,故一般该传感器的有效值在10~80cm

应用场合:

        1、触摸式开关(卫浴设备,照明控制等)

        2、机器人吸尘器

        3.传感器用于节能(自动取款机,复印机,自动售货机)

        4.游乐设备(机器人,街机游戏机)

三、OLED简介

        篇幅有限,如果这方面不熟悉的朋友可以去看看本人的另一篇文章,十分相近,希望对您有所帮助。【强烈推荐】基于stm32的OLED各种显示实现(含动态图)_混分巨兽龙某某的博客-CSDN博客https://blog.csdn.net/black_sneak/article/details/125418537?spm=1001.2014.3001.5501

四、CubexMX配置

        1、RCC配置外部高速晶振(精度更高)——HSE;

2、SYS配置:Debug设置成Serial Wire否则可能导致芯片自锁);

3、ADC1配置:配置ADC-IN1模数转换——红外测距仪所用(PA1接Vo)。

        4、 TIM2配置:设置定时器TIM2每1us向上计数一次通道1为上升沿捕获并连接到超声波模块的ECHO引脚,记得开启定时器中断(涉及到捕获中断+定时器溢出中断)。

 5、I2C2配置:作为OLED的通讯方式;

        6、GPIO配置:PA5接到了HC-SR04的TRIG触发引脚,默认输出低电平

7、TIM1配置:由上面可知HC-SR04的使用需要us级的延迟函数,HAL库自带只有ms的,所以需要自己设计一个定时器;

        8、时钟树配置:

              注意:ADC的时钟频率不要过高,否则会影响精度(8~12Mhz)

        9、工程配置

五、代码

5.1 超声波HC-SR04模块代码

其实,超声波HC-SR04的驱动就是基于GPIO口的调用。同时,由于超声波测距模块是基于超声波的物理性质,去进行距离测量,故此其精度受到很多因素影响

影响因素:温度,传播介质及其物理属性等

本次实验就不进行超声波模块的精度补偿了,后面有空可以给大家出一个相关的文章。

HC-SR04.h:

#ifndef HCSR04_H_
#define HCSR04_H_#include "main.h"
#include "delay.h"typedef struct
{uint8_t  edge_state;uint16_t tim_overflow_counter;uint32_t prescaler;uint32_t period;uint32_t t1;  //  上升沿时间uint32_t t2;   //  下降沿时间uint32_t high_level_us;    //  高电平持续时间float    distance;TIM_TypeDef* instance;uint32_t ic_tim_ch;HAL_TIM_ActiveChannel active_channel;
}Hcsr04InfoTypeDef;extern Hcsr04InfoTypeDef Hcsr04Info;/*** @description: 超声波模块的输入捕获定时器通道初始化* @param {TIM_HandleTypeDef} *htim* @param {uint32_t} Channel* @return {*}*/
void Hcsr04Init(TIM_HandleTypeDef *htim, uint32_t Channel);/*** @description: HC-SR04触发* @param {*}* @return {*}*/
void Hcsr04Start();/*** @description: 定时器计数溢出中断处理函数* @param {*}    main.c中重定义void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)* @return {*}*/
void Hcsr04TimOverflowIsr(TIM_HandleTypeDef *htim);/*** @description: 输入捕获计算高电平时间->距离* @param {*}    main.c中重定义void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)* @return {*}*/
void Hcsr04TimIcIsr(TIM_HandleTypeDef* htim);/*** @description: 读取距离 * @param {*}* @return {*}*/
float Hcsr04Read();#endif /* HCSR04_H_ */

HC-SR04.c:

#include "hc-sr04.h"Hcsr04InfoTypeDef Hcsr04Info;/*** @description: 超声波模块的输入捕获定时器通道初始化* @param {TIM_HandleTypeDef} *htim* @param {uint32_t} Channel* @return {*}*/
void Hcsr04Init(TIM_HandleTypeDef *htim, uint32_t Channel)
{/*--------[ Configure The HCSR04 IC Timer Channel ] */// MX_TIM2_Init();  // cubemx中配置Hcsr04Info.prescaler = htim->Init.Prescaler; //  72-1Hcsr04Info.period = htim->Init.Period;       //  65535Hcsr04Info.instance = htim->Instance;        //  TIM2Hcsr04Info.ic_tim_ch = Channel;if(Hcsr04Info.ic_tim_ch == TIM_CHANNEL_1){Hcsr04Info.active_channel = HAL_TIM_ACTIVE_CHANNEL_1;             //  TIM_CHANNEL_4}else if(Hcsr04Info.ic_tim_ch == TIM_CHANNEL_2){Hcsr04Info.active_channel = HAL_TIM_ACTIVE_CHANNEL_2;             //  TIM_CHANNEL_4}else if(Hcsr04Info.ic_tim_ch == TIM_CHANNEL_3){Hcsr04Info.active_channel = HAL_TIM_ACTIVE_CHANNEL_3;             //  TIM_CHANNEL_4}else if(Hcsr04Info.ic_tim_ch == TIM_CHANNEL_4){Hcsr04Info.active_channel = HAL_TIM_ACTIVE_CHANNEL_4;             //  TIM_CHANNEL_4}else if(Hcsr04Info.ic_tim_ch == TIM_CHANNEL_4){Hcsr04Info.active_channel = HAL_TIM_ACTIVE_CHANNEL_4;             //  TIM_CHANNEL_4}/*--------[ Start The ICU Channel ]-------*/HAL_TIM_Base_Start_IT(htim);HAL_TIM_IC_Start_IT(htim, Channel);
}/*** @description: HC-SR04触发* @param {*}* @return {*}*/
void Hcsr04Start()
{HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_SET);DelayUs(10);  //  10us以上HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_RESET);
}/*** @description: 定时器计数溢出中断处理函数* @param {*}    main.c中重定义void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)* @return {*}*/
void Hcsr04TimOverflowIsr(TIM_HandleTypeDef *htim)
{if(htim->Instance == Hcsr04Info.instance) //  TIM2{Hcsr04Info.tim_overflow_counter++;}
}/*** @description: 输入捕获计算高电平时间->距离* @param {*}    main.c中重定义void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)* @return {*}*/
void Hcsr04TimIcIsr(TIM_HandleTypeDef* htim)
{if((htim->Instance == Hcsr04Info.instance) && (htim->Channel == Hcsr04Info.active_channel)){if(Hcsr04Info.edge_state == 0)      //  捕获上升沿{// 得到上升沿开始时间T1,并更改输入捕获为下降沿Hcsr04Info.t1 = HAL_TIM_ReadCapturedValue(htim, Hcsr04Info.ic_tim_ch);__HAL_TIM_SET_CAPTUREPOLARITY(htim, Hcsr04Info.ic_tim_ch, TIM_INPUTCHANNELPOLARITY_FALLING);Hcsr04Info.tim_overflow_counter = 0;  //  定时器溢出计数器清零Hcsr04Info.edge_state = 1;        //  上升沿、下降沿捕获标志位}else if(Hcsr04Info.edge_state == 1) //  捕获下降沿{// 捕获下降沿时间T2,并计算高电平时间Hcsr04Info.t2 = HAL_TIM_ReadCapturedValue(htim, Hcsr04Info.ic_tim_ch);Hcsr04Info.t2 += Hcsr04Info.tim_overflow_counter * Hcsr04Info.period; //  需要考虑定时器溢出中断Hcsr04Info.high_level_us = Hcsr04Info.t2 - Hcsr04Info.t1; //  高电平持续时间 = 下降沿时间点 - 上升沿时间点// 计算距离Hcsr04Info.distance = (Hcsr04Info.high_level_us / 1000000.0) * 340.0 / 2.0 * 100.0;// 重新开启上升沿捕获Hcsr04Info.edge_state = 0;  //  一次采集完毕,清零__HAL_TIM_SET_CAPTUREPOLARITY(htim, Hcsr04Info.ic_tim_ch, TIM_INPUTCHANNELPOLARITY_RISING);}}
}/*** @description: 读取距离 * @param {*}* @return {*}*/
float Hcsr04Read()
{// 测距结果限幅if(Hcsr04Info.distance >= 500){Hcsr04Info.distance = 500;        //元器件资料说是600cm最高距离,这里保守一点}return Hcsr04Info.distance;
}

由于利用中断去读取定时测算的脉冲距离,所以这里需要重写定时器的中断服务函数。(这部分放在main.c最后即可)

/* USER CODE BEGIN 4 */
/*** @description: 定时器输出捕获中断* @param {TIM_HandleTypeDef} *htim* @return {*}*/
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)    //捕获回调函数
{Hcsr04TimIcIsr(htim);
}/*** @description: 定时器溢出中断* @param {*}* @return {*}*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)    //在中断回调函数中添加用户代码
{Hcsr04TimOverflowIsr(htim);
}
/* USER CODE END 4 */

5.2 红外测距SHARP GP2Y0A21YK0F模块代码

其实,红外测距模块就是单纯的ADC读取,通过电压结合手册中电压与距离的关系公式得到计算的距离。

ranging.h:

#ifndef __SHARP2Y0A21_H
#define __SHARP2Y0A21_H #include "main.h"#define Adc1IN1Distance_READ_TIMES 10      //定义红外传感器读取次数,以便取平均值void DistanceSensor_Init(void);                 //初始化红外传感器
float DistanceSensor_Get_Val(void);             //读取红外传感器的值#endif 

ranging.c:

#include "sharp.h"
#include "adc.h"
#include "main.h"
#include "stdio.h"//初始化ADC,不用修改
//这里我们仅以规则通道为例                                                         //初始化传感器,需要修改端口和引脚号,这里是c出口,c1引脚,ADC1的IN1
void DistanceSensor_Init(void)
{GPIO_InitTypeDef  GPIO_InitStructure;__HAL_RCC_GPIOA_CLK_ENABLE();//使能GPIOA时钟//先初始化ADC1通道11 IO口GPIO_InitStructure.Pin = GPIO_PIN_1;//PA1GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;//模拟输入GPIO_InitStructure.Pull = GPIO_NOPULL ;//不带上下拉HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化  MX_ADC1_Init();//初始化ADC1
}
//PA1=IN1
float DistanceSensor_Get_Val(void)
{uint32_t temp_val=0;float distemp=0.0;uint8_t t;for(t=0;t<Adc1IN1Distance_READ_TIMES;t++){temp_val+=HAL_ADC_GetValue(&hadc1);   //读取ADC值,通道1HAL_Delay(5);}temp_val/=Adc1IN1Distance_READ_TIMES;//得到平均值,这个是平均的ADC,distemp=temp_val*3.3/4095;//电压对应距离distemp=(-13.2*distemp*distemp*distemp)+72.84*distemp*distemp-140*distemp+107.12;return distemp;}

5.3 OLED显示代码

OLED模块作为常用的数据输出显示模块,应该是必须要掌握的。如果有朋友不是很熟悉,可以去参考本人上面提到的那篇文章,十分详尽!!!

唯一不同的点:本实验的目的是需要对比一下超声波测距模块红外测距模块的效果怎么样。其精度最高越好,这里就需要考虑到实现OLED显示含有小数的数字功能!

        含有小数的数字显示API函数:

//z_len为整数显示位数,f_len为小数显示位数,size2为字体大小
void OLED_Showdecimal(u8 x,u8 y,float num,u8 z_len,u8 f_len,u8 size2)
{           u8 t,temp;u8 enshow;int z_temp,f_temp;      z_temp=(int)num;//整数部分for(t=0;t<z_len;t++){temp=(z_temp/oled_pow(10,z_len-t-1))%10;if(enshow==0 && t<(z_len-1)){if(temp==0){OLED_ShowChar(x+(size2/2)*t,y,' ',size2);continue;}elseenshow=1;}OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2); }//小数点OLED_ShowChar(x+(size2/2)*(z_len),y,'.',size2); f_temp=(int)((num-z_temp)*(oled_pow(10,f_len)));//小数部分for(t=0;t<f_len;t++){temp=(f_temp/oled_pow(10,f_len-t-1))%10;OLED_ShowChar(x+(size2/2)*(t+z_len)+5,y,temp+'0',size2); }
}

5.4 main函数

int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_I2C2_Init();MX_ADC1_Init();MX_TIM2_Init();MX_TIM1_Init();/* USER CODE BEGIN 2 */OLED_Init();OLED_CLS();Hcsr04Init(&htim2, TIM_CHANNEL_1);  // 通道选择Hcsr04Start();  //  启动超声波/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 *///显示实验对比OLED_ShowCN_STR(30,0,0,4);//红外测距显示HAL_ADC_Start(&hadc1);adcx=HAL_ADC_GetValue(&hadc1);distance=DistanceSensor_Get_Val();OLED_ShowCN_STR(0,2,4,5);OLED_Showdecimal(80,2,distance,3,2,16);//超声波测距显示Hcsr04Start();OLED_ShowCN_STR(0,4,9,5);OLED_Showdecimal(80,4,Hcsr04Read(),3,2,16);//显示单位OLED_ShowCN_STR(30,6,14,5);}/* USER CODE END 3 */
}

六、实验效果

测距模块对比实验

经过本人由于拍摄不方便,但是效果还是很明显的。经过笔者反复标定测试发现,超声波HC-SR04测距的效果从反应速度测量范围精度等都略优于红外测距模块。而且,超声波模块比红外测距模块便宜很多,emmm,不是很理解其意义所作。当然,红外模块受外界因素的影响比超声波模块少很多,超声波模块在很多情况下是需要补偿校准的。

代码开源

链接:https://pan.baidu.com/s/1ouwFLF8ru9DROIFSZnEITg 提取码:dktp

基于STM32的超声波HC-SR04和红外测距模块测量距离的实验对比(HAL库)相关推荐

  1. 距离感应音乐玩具计算机系统设计,可编程机器人玩具程小奔红外测距传感器测量距离案例...

    文:邱老师 上次课程我们学习了用速度乘以时间计算程小奔移动距离的方法.那么,它能否测量还没有走过的路程距离呢?答案是可以的. 程小奔编程机器人集合了多种传感器,今天我们要使用程小奔机器人的红外测距传感 ...

  2. 基于stm32的超声波HC-SR04测距仪含距离报警(温度补偿)

         前言:本文主要是紧跟前一篇文章中有关超声波HC-SR04模块进行的扩展实验,主要涉及超声波测距的温度补偿(DHT11),并搭配蜂鸣器的距离报警.整体实验较为简单,为常用的几个传感器模块相互配 ...

  3. 基于STM32的超声波雷达项目【可拟合构建平面地图】(代码开源)

            前言:本文为手把手教学基于STM32的超声波雷达项目--HC-SR04雷达.本次项目采用的是STM32作为MCU,搭配常用的HC-SR04超声波模块与舵机SG90实现模拟雷达检测的效果 ...

  4. 基于STM32的超声波倒车检测装置

    基于STM32的超声波倒车检测装置 一.前言 这里是为了完成学校嵌入式系统及应用实验而做的一个作业,硬件资源使用的是STM32F103VBT6开发板.HC-SR04超声波模块,蜂鸣器和数码管开发板上以 ...

  5. 基于STM32和超声波测距传感器的测距功能设计

    基于STM32和超声波测距传感器的测距功能设计(使用陌生传感器的流程介绍) 引言 项目设计 项目简介 开发工具 硬件设计 软件设计 开发流程 阅读手册 配置并测试传感器相关设置 软件开发 总结 后续 ...

  6. stm32超声波扫频_基于STM32的超声波发生器扫频信号源的实现

    基于 STM32 的超声波发生器扫频信号源的实现 张加岭,李善波,侯颖钊,赵 杰 [摘 要] 摘要:扫频信号源采用以 STM32F103 单片机为核心,实现高精度锯 齿波扫频.由于超声波电源换能器串联 ...

  7. K_A12_007 基于STM32等单片机驱动AS608光学指纹识别模块 OLED0.96显示

    K_A12_007 基于STM32等单片机驱动AS608光学指纹识别模块 OLED0.96显示 一.资源说明 二.基本参数 参数 引脚说明 三.驱动说明 对应程序: 四.部分代码说明 1.接线引脚定义 ...

  8. 基于STM32三路超声波避障小车

    基于STM32的避障小车 最近几天的学习了STM32输入捕获输入捕获的相关知识,为了巩固自己学习的知识特意制作一辆有三个超声波组成的4轮避障小车来加深对输入捕获的理解. 1.输入捕获简介 输入捕获模式 ...

  9. 基于STM32的超声波测距

    一.HC-SR04模块介绍 HC-SR04超声波测距模块可提供2cm-400cm的非接触式距离感测功能,测距精度可高达3mm:模块包括超声波发射器.接收器.与控制电路. 模块的基本工作原理为: (1) ...

  10. 经验分享帖 基于STM32的超声波测距HC-SR04(附程序)

    CSDN上其实有很多超声波测距的博客,但我还是想写一篇,主要是附上可用的程序,伸手党最爱.其实我也是个伸手党,不过还是希望大家能自己动手自己多练自己能实现. 同时写下我的心得与看法: 1,程序是用ST ...

最新文章

  1. MS-DAYOLO来了!多尺度域自适应的YOLO,恶劣天气也看得见!
  2. CuteEditor 编辑器的字体样式无法控制的问题解决
  3. 6.824 MapReduce lab1 2020(一)
  4. android studio如何编译测试,Android Studio 进行单元测试完整教程
  5. 松下年净利润预计降20% 或启动新一轮裁员
  6. 灯珠电路图_可充电led台灯电路图
  7. 利用D3D抓取GPU数据
  8. 问题五十九:怎么求一元六次方程在区间内的所有不相等的实根(3)——修正一个问题
  9. python 基础语法梳理
  10. 论文笔记_S2D.07-2017-CVPR-RefineNet: 用于高分辨率语义分割的多路径精细网络
  11. 爬取三个acm网站题库(neuqoj pku hdu)
  12. sd u盘 速度测试软件,u盘速度测试(FlashBench)sd卡速度测试
  13. Windows与网络基础-15-本地安全策略
  14. web-页面body添加背景图片
  15. 社会网络分析——Social Network Analysis
  16. Mysql 安装PMM监控 (一台主机安装)
  17. c语言x20是什么意思,为什么vivo X20坚持不用TYPE-C插口?
  18. linux 查看文件命令
  19. 黄金时代 —— Pytorch学习记录(一)
  20. Linux权限委派(生产环境必备)

热门文章

  1. java 对象转map,map转对象
  2. idea配置tomcat热部署
  3. 华三comware跳槽_走进网络操作系统——Comware软件架构浅谈
  4. 数据库连接出错。错误代码:-2147467259。错误原因:未指定的错误
  5. 易优cms设置完伪静态之后,产品板块出现404
  6. 微软开源网络攻防模拟工具CyberBattleSim介绍及源码分析
  7. 快递鸟电子面单对接文档(顺丰、ESM、圆通通用)
  8. js动态生成表格(添加删除行操作)
  9. 用Bluemix虚拟机搭建自己的博客系统
  10. get 和 post 区别