HY-SRF05 超声波测距模块

目录

模块简介

电气参数

实物规格

引脚接线

工作原理

时序图

公式推导

驱动代码

Timer.h

Timer.c

Ultrasound.h

Ultrasound.c

main.c

代码分析


模块简介

HY-SRF05 超声波测距模块可提供2cm-450cm 的非接触式距离感测功能,测距精度可达3mm。 

模块包括超声波发射器、 接收器与控制电路。

电气参数

电气参数HY-SRF05 超声波模块
工作电压DC 5 V                (4.5V 至 5.5V)
工作电流 15mA                (10 至 40mA)
工作频率 40Hz

静态电流

小于2mA

最远射程 4.5m
最近射程 2cm
测量角度 15 度
输入触发信号10uS 的 TTL 脉冲
输出回响信号输出 TTL 电平信号, 与射程成比例
规格尺寸 45*20*15mm

实物规格

引脚接线

VCC5V电源
GNDGND接地
TRIGPB1触发控制, 信号输入(对模块而言是输入)
ECHOPB0回响信号输出
OUT不接开关量输出(当报警模块使用)

工作原理

(1) 采用IO 口TRIG 触发测距, 给至少10us 的高电平信号;
(2) 模块自动发送8 个40khz 的方波, 自动检测是否有信号返回;
(3) 有信号返回, 通过IO 口ECHO 输出一个高电平, 高电平持续的时间就是超声
波从发射到返回的时间。 测试距离=(高电平时间*声速(340m/s) ) /2;

超声波测距原理是在超声波发射装置发出超声波,它的根据是接收器接到超声波时的时间差,与雷达测距原理相似。 超声波发射器向某一方向发射超声波,在发射时刻的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时。

超声波测距原理_百度百科 (baidu.com)

时序图

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

回响信号的脉冲宽度与所测的距离成正比。
由此通过 发射信号到收到的回响信号时间间隔可以计算得到距离。
公式: : uS/58=厘米或者uS/148=英寸或距离=高电平时间*声速(340m/s)/2;

距离计算公式的推导在本博客公式推导部分
: 1、 此模块不宜带电连接, 若要带电连接, 则先让模块的GND端先连接,否则会影响模块的正常工作。
2、 测距时, 被测物体的面积不少于0.5 平方米且平面尽量要求平整, 否则影响测量的结果。

3.建议测量周期为60ms 以上, 以防止发射信号对回响信号的影响.

公式推导

Distance=340m/s*time/2=34000cm*time/1000000us/2==time/58

Distance单位为cm,time单位为us

模块可测距离为:2cm-450cm

代入公式,可得time范围为116us~26100us

 英文手册

Echo : The pulse length is propotional to the distance from the obstacle ( 100usec to 25ms, times out if 30ms)

译文:回声:脉冲长度与障碍物的距离成正比(100us到25ms, 30ms超时)

则可以令定时器1us计数一次,即1MHz,计数频率为72M/72=1M,计数器可以为60000,可以计数60000次,绰绰有余。

驱动代码

这个函数用来处理多组测量的距离,减小误差。数据排序采用冒泡算法

【排序算法】1.冒泡排序-C语言实现-CSDN博客

有能力的同学可以学学其他较好的排序算法

/**
  * @brief          统分函数的英文名称是trimmean,又叫修剪函数
  * @param      	Data-待处理数组 ,len-数组长度,deleted_bothdata-去掉的最大值的个数=去掉的最小值的个数
  * @retval         去掉指定个数最大值与最小值后平均值				
  */
float Trimmean(float *Data,uint8_t len,uint8_t deleted_bothdata)
{
    uint8_t i,j,flag=0;
    float temp,sum=0;

    //冒泡排序-升序
    for(i=0;i<len-1;i++)
    {
        flag=0;
        for(j=0;j<len-1-i;j++)
        {
            if(Data[j]>Data[j+1])
            {
                temp=Data[j];
                Data[j]=Data[j+1];
                Data[j+1]=temp;
                flag=1;
            }
        }
        if(flag==0){break;}
        
    }
    for(i=deleted_bothdata;i<len-deleted_bothdata;i++)
    {
        sum+=Data[i];
    }
    return sum/(len-deleted_bothdata*2);
}

Timer.h

#ifndef             _TIMER_H_
#define				_TIMER_H_

void Timer_Init(void);
#endif

Timer.c

#include "stm32f10x.h"                  // Device header
#include "Timer.h"

void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	
	TIM_InternalClockConfig(TIM2);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 60000- 1;		
	TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;  //记一次数1us
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	

	TIM_Cmd(TIM2, DISABLE);
}

Ultrasound.h

#ifndef             _ULTRASOUND_H_
#define				_ULTRASOUND_H_

void Ultrasound_Init(void);
float Ultrasound_GetDistance(void);

#endif

Ultrasound.c

#include "stm32f10x.h"                  // Device header
#include "Ultrasound.h"
#include "Delay.h"

#define test_num 10

void Ultrasound_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;

	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;           // 1-Trig
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

    //默认输出低电平

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;           // 0-Echo
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}


void Ultrasound_Start(void)
{
    GPIO_SetBits(GPIOB,GPIO_Pin_1);
    Delay_us(15);
    GPIO_ResetBits(GPIOB,GPIO_Pin_1); 
}



/*去掉最大值与最小值,求平均值函数,统分函数的英文名称是trimmean,又叫修剪函数*/
float Trimmean(float *Data,uint8_t len,uint8_t deleted_bothdata)
{
    uint8_t i,j,flag=0;
    float temp,sum=0;

    //冒泡排序-升序
    for(i=0;i<len-1;i++)
    {
        flag=0;
        for(j=0;j<len-1-i;j++)
        {
            if(Data[j]>Data[j+1])
            {
                temp=Data[j];
                Data[j]=Data[j+1];
                Data[j+1]=temp;
                flag=1;
            }
        }
        if(flag==0){break;}
        
    }
    for(i=deleted_bothdata;i<len-deleted_bothdata;i++)
    {
        sum+=Data[i];
    }
    return sum/(len-deleted_bothdata*2);
}

float Ultrasound_GetDistance(void)
{
    uint16_t time=0;        //us  
    float Distance[test_num]={0};//cm
    uint8_t i;

    for(i=0;i<test_num;i++)
    {
        Ultrasound_Start();
     
        while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==RESET);
        if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==SET)
        {
            TIM_Cmd(TIM2,ENABLE);
            while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==SET);
            if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==RESET)
            {
                TIM_Cmd(TIM2,DISABLE);
                time=TIM2->CNT;
                TIM_SetCounter(TIM2,0);
                Distance[i]=(34000*time/1000000)/2;//cm

            }

        }
        Delay_ms(80);//测量周期60ms以上

    }
    //数据滤波,test_num次数据排序,舍弃最大最小值求平均值
     return  Trimmean(Distance,test_num,2);

}

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"
#include "Ultrasound.h"

float Disatance;

int main(void)
{
	OLED_Init();
	Ultrasound_Init();
	Timer_Init();
	OLED_ShowString(1,1,"000.0");
	while (1)
	{
		Disatance=Ultrasound_GetDistance();
		OLED_ShowNum(1,1,Disatance,3);
		OLED_ShowNum(1,5,(uint16_t)(Disatance*10)%1000%100%10,1);


		Delay_ms(100);
	}
}

代码分析

float Ultrasound_GetDistance(void)函数中有while和Delay延时。

阻塞延迟会影响其他任务的执行,导致它们暂时停止,等待延迟结束后才能继续执行。这种延迟方式会浪费CPU,因为在延迟期间,CPU无法执行其他任务。会影响main函数中while内的其他任务。

我们应采用更好的方法来实现功能,将会在下一篇更新。看到这里了,点个赞吧。感谢🙇‍

参考手册

HY-SRF05 使用手册明书 - 道客巴巴 (doc88.com)  ------中文版

M_HY-SRF05_0003.pdf (micros.com.pl)--------------------English

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值