SR04超声波测距传感器
模块来源
采购链接:
https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-19589090137.10.33c336b4KtAN1t&id=608943401463
资料下载链接:
https://pan.baidu.com/s/1sSah9PvLBrmbA7So-6YcSw
资料提取码:qq35
规格参数
工作电压:3-5.5V
工作电流:5.3MA
感应角度:小于15度
探测距离:2CM-600CM
探测精度:0.1CM+1%
输出方式: GPIO
管脚数量:4 Pin
原理解析
只需要在 Trig 管脚(触发信号)输入一个 10US 以上的高电平,系统便可发出 8 个 40KHZ 的超声波脉冲,然后检测回波信号。当检测到回波信号后,通过 Echo 管脚输出。根据 Echo 管脚输出高电平的持续时间可以计算距离值。即距离值为:(高电平时间*340m/s)/2。
当测量距离超过 HC-SR04 的测量范围时,仍会通过 Echo管脚输出高电平的信号,高电平的宽度约为 66ms。如图 6 所示:
测量周期:当接收到 HC-SR04 通过 Echo 管脚输出的高电平脉冲后,便可进行下一次测量,所以测量周期取决于测量距离,当距离被测物体很近时,Echo 返回的脉冲宽度较窄,测量周期 就很短;当距离被测物体比较远时,Echo 返回的脉冲宽度较宽,测量周期也就相应的变长。最坏情况下,被测物体超出超声波模块的测量范围,此时 返回的脉冲宽度最长,约为 66ms,所以最坏情况下的测量周期稍大于 66ms 即可(取 70ms 足够)。
移植过程
引脚选择
移植至工程
我们的目标是将例程移植至ESP32-S3开发板上。已经为大家提供了完整的驱动代码,按照以下步骤,即可完成移植。
具体新建文件夹和新建c和h文件在 【DHT11温湿度传感器】章节中的1.4.2小节中有详细的教学,这里就不再多说了。
只不过这里我们将文件名 bsp_dht11.c 和 bsp_dht11.h 换成 bsp_ultrasonic.c 和 bsp_ultrasonic.h,文件夹名字改为SR04。
代码写入
在 bsp_ultrasonic.c 文件中写入:
#include "bsp_ultrasonic.h"
//定时器句柄
esp_timer_handle_t ceju = 0;
static bool timer_initialized = false;
int64_t star = 0;
int64_t endTime = 0;
float distance = 0;
void delay_ms(unsigned int ms)
{
vTaskDelay(ms / portTICK_PERIOD_MS);
}
void delay_us(unsigned int us)
{
ets_delay_us(us);
}
//定时器回调函数,作为超时处理
void timer_once(void *arg)
{
int64_t tick=esp_timer_get_time();
esp_timer_delete(ceju);
}
/******************************************************************
* 函 数 名 称:bsp_ultrasonic
* 函 数 说 明:超声波初始化
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:TRIG引脚负责发送超声波脉冲串
******************************************************************/
void Ultrasonic_Init(void)
{
gpio_config_t trig_config = {
.pin_bit_mask = (1ULL<<SR04_TRIG), //配置引脚
.mode =GPIO_MODE_OUTPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE, //不使能下拉
.intr_type = GPIO_INTR_DISABLE //不使能引脚中断
};
gpio_config(&trig_config);
gpio_config_t echo_config = {
.pin_bit_mask = (1ULL<<SR04_ECHO), //配置引脚
.mode =GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE, //不使能下拉
.intr_type = GPIO_INTR_DISABLE //不使能引脚中断
};
gpio_config(&echo_config);
}
/******************************************************************
* 函 数 名 称:Hcsr04GetLength
* 函 数 说 明:获取测量距离
* 函 数 形 参:无
* 函 数 返 回:测量距离
* 作 者:LC
* 备 注:无
******************************************************************/
float Hcsr04GetLength(void)
{
/*测5次数据计算一次平均值*/
float length = 0;
float t = 0;
float sum = 0;
unsigned int i = 5;
esp_timer_create_args_t once_test={ //定时器结构体初始化
.callback= &timer_once,
.arg=NULL,
.name="HC_SR04Timer"
};
if (!timer_initialized)
{
esp_timer_init(); // 初始化定时器
timer_initialized = true;
}
esp_timer_create(&once_test,&ceju); //创建定时器
while(i--)
{
gpio_set_level(SR04_TRIG, 1);//trig拉高信号,发出高电平
delay_us(20);//持续时间超过10us
gpio_set_level(SR04_TRIG, 0);//trig拉低信号,发出低电平
/*Echo发出信号 等待回响信号*/
/*输入方波后,模块会自动发射8个40KHz的声波,与此同时回波引脚(echo)端的电平会由0变为1;
(此时应该启动定时器计时);当超声波返回被模块接收到时,回波引 脚端的电平会由1变为0;
(此时应该停止定时器计数),定时器记下的这个时间即为
超声波由发射到返回的总时长;*/
while(gpio_get_level(SR04_ECHO) == 0);//echo等待回响
//Echo低电平结束后,定时器开始一个单个周期工作,到达1740us就回调函数
esp_timer_start_once(ceju,1740);
delay_us(1);
//获取当前时间 记录当前时间star为Echo引脚变高的开始时间
star = esp_timer_get_time();
while(gpio_get_level(SR04_ECHO)==1)
{
endTime = esp_timer_get_time(); //记录Echo引脚变为低电平的结束时间
//注意,一定要把结束时间的代码放到循环里面,如果放到循环外面可能不能正常测距
}
//计算Echo引脚高电平持续的时间
endTime = endTime-star;
//计算距离,时间单位为us
float cm=((float)endTime/58.0);
sum += cm;
}
distance = sum / 5;//五次平均值
return distance;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
在 bsp_ultrasonic.h文件中写入:
#ifndef _BSP_ULTRASONIC_H_
#define _BSP_ULTRASONIC_H_
#include "driver/gptimer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "freertos/queue.h"
#include <inttypes.h>
#include "sdkconfig.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "rom/ets_sys.h"
#include "esp_system.h"
#include "driver/gptimer.h"
#include "esp_timer.h"
#define SR04_TRIG 1
#define SR04_ECHO 2
void delay_us(unsigned int us);
void delay_ms(unsigned int ms);
void timer_once(void *arg); //回调函数
void Ultrasonic_Init(void);//超声波初始化
float Hcsr04GetLength(void );//获取超声波测距的距离
#endif
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
移植验证
在main.c中输入代码如下
#include <stdio.h>
#include "bsp_ultrasonic.h"
void app_main(void)
{
Ultrasonic_Init();
printf("SR04 Start....\r\n");
while(1)
{
printf("distance: %0.2f\n",Hcsr04GetLength());
delay_ms(1000);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
上电效果(距离20cm放置障碍物):
驱动代码: