HC-SR04超声波避障模块
HC-SR04 超声波测距模块可提供 2cm-400cm 的非接触式距离感测功能, 测距精度可达高到 3mm;模块包括超声波发射器、接收器与控制电路。 基本工作原理:
(1)采用IO口TRIG触发测距,给至少10us的高电平信号;
(2)模块自动发送8个40khz的方波,自动检测是否有信号返回;
(3)有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。
测试距离=(高电平时间*声速(340M/S))/2;
由于可使用用IO有限,本次我只使用了两个HC-SR04。
以下为粗略的流程图,由于缺少一个超声波,流程比较鸡肋,但逻辑上没有问题。
ultrasonic.h
#ifndef __ULTRASONIC_H
#define __ULTRASONIC_H
#include "sys.h"
void ulsonic0_config(void);
void ulsonic1_config(void);
u16 sonictest_forth(void);
u16 sonictest_right(void);
float changefunction(u16 count1);
#endif
ultrasonic.c
#include "ultrasonic.h"
#include "delay.h"
void ulsonic0_config() //前向
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启IO口对应的时钟
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2; //ECHO PA2
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3; //TRIG PA3
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
}
void ulsonic1_config() //右侧
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启IO口对应的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11; //**************ECHO A11
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0; //**************TRIG B0
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
u16 sonictest_forth(void) //前路测试
{
u16 res;
GPIO_SetBits(GPIOA,GPIO_Pin_3);
delay_us(20);
GPIO_ResetBits(GPIOA,GPIO_Pin_3); //触发TRIG
while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2) == 0);//等待ECHO高电平
TIM_SetCounter(TIM3,0);
TIM_Cmd(TIM3,ENABLE); //运行TIM3进行计时
while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2)==1);
TIM_Cmd(TIM3,DISABLE);//关闭定时器
res=TIM3->CNT;
return res;
}
u16 sonictest_right(void) //右路测试
{
u16 res;
GPIO_SetBits(GPIOB,GPIO_Pin_0);
delay_us(30);
GPIO_ResetBits(GPIOB,GPIO_Pin_0); //触发TRIG
while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_11) == 0);//等待ECHO高电平
TIM_SetCounter(TIM3,0);
TIM_Cmd(TIM3,ENABLE); //运行TIM3进行计时
while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_11)==1);
TIM_Cmd(TIM3,DISABLE);//关闭定时器
res=TIM3->CNT;
return res;
}
float changefunction(u16 count1) //count->distance
{
float distance1;
distance1=count1*0.017; //单位厘米cm
return distance1;
}
main.c
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "motor.h"
#include "timer.h"
#include "tick_ulsonic.h"
#include "ultrasonic.h"
/*********************************
可接超声波数量有限,故程序比较累赘
***************************************/
//count定时器数值
//float容错次数 减小超声波互扰因素
int main(void)
{
//float distance;
u16 count;
u8 fault=0;
SystemInit();
delay_init(); //延时函数初始化 nms<=1864
uart_init(115200);
LED_Init(); //初始化与LED连接的硬件接口
pwm_init(899,0);
delay_ms(1000);
delay_ms(1800);
Tim3_Config();
ulsonic0_config(); // ECHO PA2 TRIG PA3
ulsonic1_config(); // ECHO PA11 TRIG PB0
while(1)
{
LED=1;
fault=2;
motor_forth(); //前进
count=sonictest_forth();
// printf("count=%d\t\n",count);
// distance=changefunction(count);
// printf(" 当前距离为:%f\t\n",distance);
if(count<800){
count=sonictest_forth();fault--;}
if(count<800){
count=sonictest_forth();fault--;}
if(!fault)
{
LED=0;
motor_stop();
delay_ms(1000);
count = sonictest_right();
if(count<1000) //右侧不通,左转
{
motor_left();
delay_ms(500);
count=sonictest_forth();
if(count<800)
{
motor_left();
delay_ms(500);
}
}else{
motor_right();
delay_ms(500);
}
}
}
}
前方和右侧装有超声波模块的小车
鉴于实践中超声波测量数值偶有波动,猜测是先后发出的超声波产生干扰,故引入fault变量,增加容错率。