友情提示:380元/半年,儿童学编程,就上码丁实验室。
我是潘,曾经是个工程师。这是 “Arduino 公开课” 系列的入门教程。上一课介绍了温湿度模块和库的使用,现在我们用超声波模块测量距离。有任何疑问请在评论区提出,我会逐一回答。
超声波测距的原理是发射声波,声波遇到物体反射,模块接收,得出时间差,然后根据声速计算出物体距离。其应用非常之广,如现场测距,无人机避障、汽车雷达等,而且价格极为低廉,库成熟,是最常用的模块。这次我们介绍的是 HC-SR04、HC-SR05:
该模块一共有Vcc、GND、Trig 和 Echo,4个引脚。Arduino 通过 Trig 引脚给模块,不少于10us 数字信号(高电平),触发模块发射出 40KHz 的超声波,接收到返回声波后,Echo 输出高电平,根据触发和输出的时间差,就可以换算出距离。但我们不需要设计换算程序,因为这个模块有现成的库可以用,调用库里的方法即可。模块参数如下:
测量距离:2 ~ 450cm
分辨率:0.3cm
测量频率:40Hz(最快每25ms测量一次)
测量角度:15deg
工作电压:4.5 ~ 5.5V
工作电流:10 ~ 40mA
该模块实际测量距离约为 200cm,而且经常会有严重的漂移现象,因此建议多次采样,使用中位数,可以保证测量正确。
接线方式很简单:
开发程序之前,我们需要先下载 NewPing.h 库,这个库不在官方的索引里面,因此需要先下载:NewPing_v1.8
下载后不要急着解压,在 IDE 界面顶部菜单,选择“项目”中的“加载库”,然后点击 “添加一个.zip库” 即可加载。我们在编写程序前,同样“加载库”中,选择插入需要的库函数,IDE就会自动插入:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/*
作者:Ardui.Co
效果:超声波测距
版本:1.0
更新时间:2017年2月14日
*/
#include <NewPing.h>
#define TRIGGER_PIN 12 // 宏定义12号数字端口为触发
#define ECHO_PIN 11 // 宏定义11号数字端口为接收模块反馈信号
#define MAX_DISTANCE 200 //宏定义模块的最大测量距离,规格标450cm,但实测一般为200cm
NewPing sonar(TRIGGER_PIN,ECHO_PIN,MAX_DISTANCE);//声明模块的参数
voidsetup(){
Serial.begin(115200);// 设置串口的波特率,可以改为9600
}
voidloop(){
delay(500); // 每次测量的时间间隔,模块规格为40Hz,因此最小为25ms,但一般不少于30ms
Serial.print(“Ping: “);
Serial.print(sonar.ping_cm());// 调用库里面的 ping_cm() 方法,直接输出距离
Serial.println(“cm”);
}
|
上面是常规的接线方式,但 NewPing.h 是个非常强大的库,为节省 Arduino 端口,我们还可以将 Trig 和 Echo 接在一起,只用一条数据引线传输两种信号,只要简单修改下程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/*
作者:Ardui.Co
效果:超声波测距模块,使用单线连接
版本:1.0
更新时间:2017年1月13日
*/
#include <NewPing.h>
#define PING_PIN 12 // 宏定义12号数字端口为触发和接收端口
#define MAX_DISTANCE 200 //宏定义模块的最大测量距离,规格标450cm,但实测一般为200cm
NewPing sonar(PING_PIN,PING_PIN,MAX_DISTANCE);//声明模块的参数,注意Trig和Echo都是同一个端口
voidsetup(){
Serial.begin(115200);// 设置串口的波特率
}
voidloop(){
delay(500); // 每次测量的时间间隔,模块规格为40Hz,因此最小为25ms,但一般不少于30ms
Serial.print(“Ping: “);
Serial.print(sonar.ping_cm());// 调用库里面的 ping_cm() 方法,直接输出距离
Serial.println(“cm”);
}
|
如果测量距离超出了限定范围200cm,程序会怎么处理?答案是输出 0。
由于超声波测量容易受到环境因素影响,模块漂移几率较大,我们可以多次采样,然后取中位数(思考一下:为什么不是平均值?)避免忽大忽小的问题,NewPing.h 已经提供了 ping_median() 方法,但输出的是时间(毫秒),所以我们还要用到一个转换方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/*
作者:Ardui.Co
效果:超声波测距模块,使用单线连接
版本:1.0
更新时间:2017年1月13日
*/
#include <NewPing.h>
#define PING_PIN 12 // 宏定义12号数字端口为触发和接收端口
#define MAX_DISTANCE 200 //宏定义模块的最大测量距离,规格标450cm,但实测一般为200cm
NewPing sonar(PING_PIN,PING_PIN,MAX_DISTANCE);//声明模块的参数,注意Trig和Echo都是同一个端口
voidsetup(){
Serial.begin(115200);// 设置串口的波特率
}
voidloop(){
delay(500); // 每次测量的时间间隔,模块规格为40Hz,因此最小为25ms,但一般不少于30ms
Serial.print(“Ping: “);
intt=sonar.ping_median(5,200);//测量5次并设定最大距离为200cm,然后取中位数输出
Serial.print(sonar.convert_cm(t));// 使用convert_cm()方法,将时间转换为距离
Serial.println(“cm”);
}
|
NewPing.h 还提供了程序中断、积累计时等方法,在挑战篇中我们会用到。另外,阅读官方文档也是一个重要的学习途径:https://bitbucket.org/teckel12/arduino-new-ping/wiki/Home