原理:超声波(声音)在空气中传播的速度为已知340m/s(也会受温度影响轻微,在粗测中可忽略),超声波遇到障碍物时就会原路反射回来,根据L=(V T)1/2 可求得发出声波的位置到障碍物的距离(因为时间T是超声波来回两段路程的时间,所以要除以2)。
HC-SR04模块介绍:
VCC引脚:接+5V。
GND引脚:接GND。
Trig引脚:实际是trigger,有触发引发的意思,到时候只需要给这个引脚一个持续10us的高电平,HC-SR04就会自动地发射8个40KHz的方波(即为超声波)。
Echo引脚:echo实际是是回声回波的意思,当HC-SR04成功的向外发射超声波的时刻开始,这个引脚就会变成高电平,高电平会一直持续到HC-SR04接收到回波为止。
注意:由上面的各引脚的功能我们可知道Trig和Echo必须接在arduino的D口(即数字端口)
程序示例:(trig引脚我是接在了arduino的D3口,echo就接在了D4口)
/*
日期:2016.04.06
编辑器:sublime text 3 (基于arduino-1.6.5)
功能:通过SR04超声波传感器进行测距,并通过串口监视器显示测出的距离
*/
const int Trig = 3; // 设定SR04连接的Arduino引脚
const int Echo = 4;
double distance,time ;
void setup()
{
Serial.begin(9600); // 初始化串口通信及连接SR04的引脚
pinMode(Trig, OUTPUT);
pinMode(Echo, INPUT); //要检测引脚上输入的脉冲宽度,需要先设置为输入状态
Serial.println("The distance is :");
}
void loop()
{
digitalWrite(Trig, LOW);
delayMicroseconds(2);
digitalWrite(Trig, HIGH);
delayMicroseconds(10); //产生一个10us的高脉冲去触发SR04
digitalWrite(Trig, LOW);
time = pulseIn(Echo, HIGH); // 检测脉冲宽度,注意返回值是微秒us
distance = time /58 ; //计算出距离,输出的距离的单位是厘米cm
Serial.print(distance); //把得到的距离值通过串口通信返回给电脑,通过串口监视器显示出来
Serial.println("cm");
delay(1000);
}
把模块与arduino连接好,然后把程序写好后就下载到arduino里面运行,然后打开串口监视器,就可以看到有数据不断地在屏幕上输出。
pulseIn(Echo, HIGH)的作用是把Echo引脚高电平的持续时间测出,并返回,返回值的单位是微秒us。
计算过程:L = (1/2) * 340 *(time /10^6) * 100 = time / 58
上面计算过程包括了把us变成s , 速度乘时间, m变成cm 三个部分。
注意:在把超声波对着目标障碍物的时候,模块与目标障碍物之间的其他障碍物【有可能】会影响测距的准确性,因为声波的方向性并不强,并不是只朝着一个方向传播的,当沿某一个方向传播的超声波遇到的障碍物比目标障碍物的距离要近并且回波成功的被超声波模块接收到的时候测出的距离值就是不准的了。下面是一个示意图,可能有点夸张了,但 想要表达的意思是在的。
超声波发射器向某一方向发射超声波,在发射的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时。声波在空气中的传播速度为340m/s,根据计时器记录的时间t,就可以计算出发射点距障碍物的距离s,即:s=340m/s×t / 2 。这就是所谓的时间差测距法。
pulseIn函数知识要点:
pulseIn():用于检测引脚输出的高低电平的脉冲宽度。
pulseIn(pin, value)
pulseIn(pin, value, timeout)
Pin---需要读取脉冲的引脚
Value---需要读取的脉冲类型,HIGH或LOW
Timeout---超时时间,单位微秒,数据类型为无符号长整型。
使用方法及时序图:
1、使用Arduino采用数字引脚给SR04的Trig引脚至少10μs的高电平信号,触发SR04模块测距功能;
2、触发后,模块会自动发送8个40KHz的超声波脉冲,并自动检测是否有信号返回。这步会由模块内部自动完成。
3、如有信号返回,Echo引脚会输出高电平,高电平持续的时间就是超声波从发射到返回的时间。此时,我们能使用pulseIn()函数获取到测距的结果,并计算出距被测物的实际距离。
代码如下:
const int TrigPin = 2;
const int EchoPin = 3;
float distance;
void setup()
{ // 初始化串口通信及连接SR04的引脚
Serial.begin(9600);
pinMode(TrigPin, OUTPUT);
// 要检测引脚上输入的脉冲宽度,需要先设置为输入状态
pinMode(EchoPin, INPUT);
Serial.println("Ultrasonic sensor:");
}
void loop()
{
// 产生一个10us的高脉冲去触发TrigPin
digitalWrite(TrigPin, LOW);
delayMicroseconds(2);
digitalWrite(TrigPin, HIGH);
delayMicroseconds(10);
digitalWrite(TrigPin, LOW);
// 检测脉冲宽度,并计算出距离
distance = pulseIn(EchoPin, HIGH) / 58.00;
Serial.print(distance);
Serial.print("cm");
Serial.println();
delay(1000);
}
pulseIn函数其实就是一个简单的测量脉冲宽度的函数,默认单位是us。也就是说pulseIn测出来的是超声波从发射到接收所经过的时间。对于除数58也很好理解,声音在干燥、摄氏 20度的空气中的传播速度大约为343米/秒,合34,300厘米/秒。或者,我们作一下单位换算,34,300除以1,000,000厘米/微秒。即为:0.0343厘米/微秒,再换一个角度,1/(0.0343 厘米/微秒)即:29.15 微秒/厘米。这就意味着,每291.5微秒表示10CM的距离。1厘米就是29.15微秒。但是发送后到接收到回波,声音走过的是2倍的距离呀。
所以实际距离就是1厘米,对应58.3微秒。实际上整个测距过程是测的发出声波到收到回波的时间,你的程序里的第一个distance实际上是时间us。所以换成距离cm,要除以58。当然除以58.3可能更精确。所以我们可以用 pulseIn(EchoPin, HIGH) / 58.00获取测得的距离。
————————————————