打样板子购买物料时看到有HC-SR04模块,购入。模块工作电压3v-5.5v,直接用3.3v供电。
测距原理
声波在空气中的传播速度是固定的,发射的超声波遇到障碍物会反射回来,我们记录下发射波到接受反射波之间的时间差,就可以计算出模块距离障碍物的距离。我们可以把这个用于测距、避障等领域。
编程思路
启用定时器组0的定时器0,实现微秒延时和时间测量。定时器频率为4MHz,每个us计数4个。按模块使用方法,给Trig脚一个10us的高电平,测量echo脚高电平的时间,此时间即为声波信号发送到接收之间的时间。
程序写入到头文件中,在app_main函数中直接调用hcsr04_task()即可
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "sdkconfig.h"
#include "esp32/rom/ets_sys.h"
#include "driver/timer.h"
#include "driver/gpio.h"
//定义引脚,测距时小于35mm的距离,干扰,不准确
#define Trig 0
#define Echo 1
static const char *HCSR04TAG = "HCSR04";
//set 80m hz /20 ,4m hz tick
void hcsr04_timer_init(void)
{
#define TIMER_DIVIDER (20) // Hardware timer clock divider
#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) // convert counter value to seconds, 80M hz
int group = 0;
int timer = 0;
/* Select and initialize basic parameters of the timer */
timer_config_t config = {
.divider = TIMER_DIVIDER,
.counter_dir = TIMER_COUNT_UP,
.counter_en = TIMER_PAUSE,
.alarm_en = TIMER_ALARM_DIS,
.auto_reload = TIMER_AUTORELOAD_DIS,
}; // default clock source is APB
timer_init(group, timer, &config);
/* Timer's counter will initially start from value below.
Also, if auto_reload is set, this value will be automatically reload on alarm */
timer_set_counter_value(group, timer, 0);
timer_start(group, timer);
}
void hcsr04_delay_us(uint16_t us) {
uint64_t timer_counter_value = 0;
uint64_t timer_counter_update = 0;
//uint32_t delay_ccount = 200 * us;
timer_get_counter_value(0,0,&timer_counter_value);
timer_counter_update = timer_counter_value + (us << 2);
do {
timer_get_counter_value(0,0,&timer_counter_value);
} while (timer_counter_value < timer_counter_update);
}
void hcsr04_task(void)
{
uint64_t timer_counter_value = 0;
uint64_t timer_counter_update = 0;
float length_mm=0;
//设置Trig引脚为输出模式 Echo引脚为输入模式//
gpio_pad_select_gpio(Trig);
gpio_pad_select_gpio(Echo);
gpio_set_direction(Trig,GPIO_MODE_OUTPUT);
gpio_set_direction(Echo,GPIO_MODE_INPUT);
while(1){
hcsr04_timer_init(); //初始化
gpio_set_level(Trig,0);
hcsr04_delay_us(20);
gpio_set_level(Trig,1);//然后拉高Trig至少10us以上
ets_delay_us(10);
gpio_set_level(Trig,0);//再拉低Trig,完成一次声波发出信号
//检测Echo引脚,一直为低电平就一直在等待
while(gpio_get_level(Echo)==0){
}
timer_get_counter_value(0,0,&timer_counter_value);
while(gpio_get_level(Echo)==1){
}
timer_get_counter_value(0,0,&timer_counter_update);
//计算Echo引脚高电平持续的时间
if(timer_counter_update-timer_counter_value < 130000){//131989 value for error
length_mm = 0.0425*(timer_counter_update-timer_counter_value);//counter * 340000 / 4000000 / 2
ESP_LOGE(HCSR04TAG,"length: %.2f mm", length_mm);
}else{
//ESP_LOGE(HCSR04TAG,"length: error");
}
vTaskDelay(200 / portTICK_PERIOD_MS);
}
}
实验效果
达成目标。观测模块在小于35mm时数据不准;测量失败时定时器计数131989。