问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

HC-SR04超声波测距原理及实现

创作时间:
作者:
@小白创作中心

HC-SR04超声波测距原理及实现

引用
1
来源
1.
https://www.dianyuan.com/eestar/article-9101.html

HC-SR04超声波测距模块可提供2cm-400cm的非接触式距离感测功能,测距精度可达3mm。模块包括超声波发射器、接收器与控制电路,在智能小车的测距、避障,盲人拐杖,视力保护器(坐姿矫正),倒车雷达等应用中时常使用。

工作原理

HC-SR04基本工作原理:

  1. 使用单片机的一个引脚发送一个至少10us高电平的TTL脉冲信号到模块的Trig引脚,用于触发模块工作。
  2. 模块检测到触发信号之后,会自动发送8个40khz的方波,然后自动切换至监测模式,监测是否有信号返回(超声波信号遇障碍物会返回)。
  3. 如果有信号返回,通过模块的Echo引脚会输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。
  4. 因为声音在空气中的速度为340米/秒,即可计算出所测的距离。

代码实现

通过上面的分析,我们知道,获得超声波模块测得的距离的难点就是求得Echo引脚输出脉冲的高电平持续时间。

初始化

//文件"sr04.h"中添加定义
extern u32 msHcCount;
//超声波硬件接口定义
#define HCSR04_PORT  GPIOA
#define HCSR04_CLK       RCC_APB2Periph_GPIOA
#define HCSR04_TRIG      GPIO_Pin_2
#define HCSR04_ECHO      GPIO_Pin_3
#define TRIG_Send  PAout(2)
#define ECHO_Reci  GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)
//文件"sr04.c"中
void Hcsr04Init()
{  
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;   
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(HCSR04_CLK, ENABLE);
   
    GPIO_InitStructure.GPIO_Pin =HCSR04_TRIG;      
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);
    GPIO_ResetBits(HCSR04_PORT,HCSR04_TRIG);
     
    GPIO_InitStructure.GPIO_Pin =   HCSR04_ECHO;     
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);  
    GPIO_ResetBits(HCSR04_PORT,HCSR04_ECHO);      
          
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);   
     
    TIM_DeInit(TIM4);
    TIM_TimeBaseStructure.TIM_Period = (1000-1); 
    TIM_TimeBaseStructure.TIM_Prescaler =(72-1); 
    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);          
        
    TIM_ClearFlag(TIM4, TIM_FLAG_Update);  
    TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);    
    Hcsr04_NVIC();
    TIM_Cmd(TIM4,DISABLE);     
}  

测量距离

下面代码实现的是五次测量取平均值作为最终的结果。单次距离测量的方法采用了两种实现方式:定时器方式和延时函数的方式。

定时器方式

通过定时器4计数器值计算距离的具体实现代码如下所示:

u32 GetEchoTimer(void)
{
   u32 t = 0;
   t = msHcCount*1000;
   t += TIM_GetCounter(TIM4);
   TIM4->CNT = 0;  
   delay_ms(50);
   return t;
}  

float Hcsr04GetLength(void )
{
   u32 t = 0;
   int i = 0;
   float lengthTemp = 0;
   float sum = 0;
   while(i<5)
   {
      TRIG_Send = 1;      
      delay_us(20);
      TRIG_Send = 0;
      while(ECHO_Reci == 0);      
      OpenTimerForHc();        
      i = i + 1;
      while(ECHO_Reci == 1);
      CloseTimerForHc();        
      t = GetEchoTimer();      
     
      lengthTemp = ((float)t/58.0);
     
      sum = lengthTemp + sum ;        
    }
   
    lengthTemp = sum/5.0;
    return lengthTemp;
}  
延时函数方式

也是取五次测量值的平均值作为结果,在计算Echo引脚输出高电平时间的时候,只要while(ECHO_Reci)为真,计时即+10us,直至高电平结束,即可获得高电平持续的总时间。

void HCSR04_Ranging(float *p)
{
  u8 i=0;
  u32 j=0;
  float HCSR04_Temp = 0.0;  
  for(i=0;i<5;i++)
  {
    TRIG_Send=1;
    delay_us(40);
    TRIG_Send=0;
    while(!ECHO_Reci);
    while(ECHO_Reci)
    {
      delay_us(10);
      j++;
    }
    HCSR04_Temp+=j*10;  //模块最大可测距4m 
    j=0;
    delay_ms(60);//防止发射信号对回响信号的影响
  }
  *p= HCSR04_Temp/5/58.0;     
}  

注意:文中多次使用类似while循环:while(ECHO_Reci),其实这样做容易让单片机陷入死循环,各位可以试着想想有没有好的方式避免。

距离换算

查看手册,我们会看到,手册上说:

测量距离(cm) = 高电平持续的us数 / 58

为什么us值/58即是以cm为单位的距离值呢?

正常的换算公式为:

测试距离 = (高电平时间*声速(340m/s))/2

除以2的原因是,超声波的信号是往返的耗时等于高电平时间,我们求距离,需要除以2。

上面的测量距离单位为m,高电平时间为s, 如果我们把测量距离的单位换为cm,高电平时间改为us, 则上面的公式就修改为:

测量距离cm = (高电平时间us/1000000) * 340 / 2 * 100

即测量距离cm = 高电平时间us * 17 / 1000;

即测量距离cm = 高电平时间us / (1000/17);而1000/17 ≈ 58.82

所以一般为了方便计算,距离换算就是将求得的高电平时间除以58,即得距离值,单位cm。

硬件连接

目前HC-SR04这个模块有很多版本,最好选用3.3V和5V兼容的版本。我也拿了一个5V的老版本做了一下测试,使用3.3V供电,测量的数据不对,什么也不改变的情况下,将电源引脚供电改为5V供电,返回的数据就正常了。

如果使用5V老版本的HC-SR04模块,为了使系统能够稳定,最好选用5V耐受的IO引脚,诸如带有下面FT标识的引脚。

实际效果图

测试结果

分别将HC-SR04放置于障碍物前30cm、20cm、10cm处各测量两次,具体数据如下所示:

通过上面我们可以看出,定时器的方式的准确度明显高于延时函数的实现方式,自己分析一下,为什么延时函数的方式误差会差这么多呢?当然这里面的误差还包括我摆放的原因导致的误差。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号