本系列文章为作者原创,未经作者书面同意,不得转载!
首先,我们来了解一下超声波,科学家们将每秒钟振动的次数称为声音的频率,它的单位是赫兹(Hz)。我们人类耳朵能听到的声波频率为20Hz-20000Hz。因此,我们把频率高于20000赫兹的声波称为“超声波”。
超声波方向性好,穿透能力强,易于获得较集中的声能,在水中传播距离远,可用于测距、测速、清洗、焊接、碎石、杀菌消毒等。在医学、军事、工业、农业上有很多的应用:
在动物的世界里,超声波也起着不可替代的作用:
蝙蝠和海豚就是依靠自身发出的超声波来定位捕获猎物。
超声波测距仪就是根据超声波的特点设计而成:
我们今天的项目就是制作一个数字超声波测距仪。
在这个项目中,您将学到的
学会使用超声波测距传感器
学习使用四位数码管
另外,通过这个项目您也会学习到LED显示模块的一般驱动原理。
我们选用Arduino Uno作为数字超声波测距仪的主控板,还会用到一个超声波测距模块和一个共阴四位数码显示模块,由于我们采用的超声波测距模块最大测距为4.5米,精度为0.2厘米,考虑到我们的显示模块为4位,所以我们将显示距离的单位设定为厘米,前三位显示整数部分,最后一位显示小数部分,正好能够满足超声波测距模块的精度要求。
工具和组件
2.1 工具列表
本项目不需要额外的工具。
2.2 元器件列表
2.3.1 SR-04超声波测距模块
SR-04超声波测距模块性能稳定,测度距离精确,盲区小,关键是还很便宜,在创客圈应用最为广泛,包括:机器人避障、物体测距、液位检测等等。
2.3.1.1 技术参数
使用电压 DC 5V
静态电流 小于2mA
感应角度 不大于15度
探测距离 2cm-450cm
探测精度 0.2cm
2.3.1.2 引脚说明
VCC:供电 5V DC
TRIG:控制端
ECHO:接收端
GND:接地,电源负极
2.3.1.3 工作原理
采用IO口TRIG触发测距,给至少10us的高电平信号;
模块自动发送8个40khz的方波,自动检测是否有信号返回;
有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。
测试距离 = (高电平时间 * 声速(340M/S)) / 2
所以这个模块的使用方法还是比较简单的,在TRIG控制口发一个10US以上的高电平,就可以在ECHO接收口等待高电平输出,一有输出就可以开定时器计时,当此口变为低电平时就可以读定时器的值,此时就为此次测距的时间,根据上面的公式即可计算出距离。
小知识:
声音的传播需要物质,物理学中把这样的物质叫做介质。
声音在不同的介质中的传播速度:
真空 0m/s(也就是不能传播)
空气(15℃) 340m/s
空气(25℃) 346m/s
软木 500m/s
煤油(25℃) 1324m/s
蒸馏水(25℃) 1497m/s
海水(25℃) 1531m/s
铜(棒) 3750m/s
大理石 3810m/s
铝(棒) 5000m/s
铁(棒) 5200m/s
声音在不同的物质中的传播速度不同。
2.3.2 共阴四位数码管
数码管是一种半导体发光器件,数码管可分为七段数码管和八段数码管,区别在于八段数码管比七段数码管多一个用于显示小数点的发光二极管单元DP(decimal point),其基本单元是发光二极管。
共阴四位数码管是一种数字显示屏,由4个八段数码管组成,能够显示4个数字,支持显示小数点和时间格式。
数码管是一种半导体发光器件,其基本单元是发光二极管。因此也需要串联电阻,以防电流过大。
2.3.2.1 引脚说明
如下图所示:abcdefgh 为数码管LED引脚,每个数字由7条线(LED)组成,用a-g控制,h控制小数点;同时通过1-4引脚控制当前设置的四个数字中的哪一个。
3 电路设计
3.1 电路图
根据我们的项目需求,设计电路图如下:
3.2 电路原理
由于四位数码管基本上用掉了所有数字口,除了0、1之外,由于0、1这两个引脚是UNO连接电脑的串口,为了方便通过串口打印调试信息,一般尽量少占用,所以超声波测距模块在这里使用了模拟口A4和A5。
知识点:
Arduino UNO电路板的数字口有13个,但有的项目我们可能需要更多的数字口,当我们数字端口不够用时,该怎么办呢?当然,您可以购买性能更为强大的Arduino电路板,如MEGA 2560,但有没有其它办法呢?
其实Arduino电路板的模拟输入口可以很方便的当数字口用,以UNO为例,对应的GPIO:A0=14、A1=15、A2=16......以此类推,使用方法和使用数字端口一样。
4 程序设计
4.2 主程序设计
/*
名称:超声波测距仪
功能:
作者:YXK
时间:2018.6.5
*/
const int trigPin = 18; //定义超声波测距模块trig引脚 A4
const int echoPin = 19; //定义超声波测距echo引脚 A5const int led[8] = {2,3,4,5,6,7,8,9}; //定义数码管的LED引脚
const int com[4] = {13,12,11,10}; //定义数码管的数字位引脚float checkDistance(int trig, int echo); //超声波测距函数
int firstBit,secondBit,thirdBit,fourthBit; //定义四位数码管每位要显示的值,依次是第1、2、3、4位float distFloat; //声明一个浮点型距离变量
int distInt; //声明一个整形距离变量
int eyeDelay=500; //视觉延迟时间,单位微秒//数码管0-F .码值表
unsigned char num[17][8] =
{
//a b c d e f g h
{1, 1, 1, 1, 1, 1, 0, 0}, //0
{0, 1, 1, 0, 0, 0, 0, 0}, //1
{1, 1, 0, 1, 1, 0, 1, 0}, //2
{1, 1, 1, 1, 0, 0, 1, 0}, //3
{0, 1, 1, 0, 0, 1, 1, 0}, //4
{1, 0, 1, 1, 0, 1, 1, 0}, //5
{1, 0, 1, 1, 1, 1, 1, 0}, //6
{1, 1, 1, 0, 0, 0, 0, 0}, //7
{1, 1, 1, 1, 1, 1, 1, 0}, //8
{1, 1, 1, 1, 0, 1, 1, 0}, //9
{1, 1, 1, 0, 1, 1, 1, 1}, //A
{1, 1, 1, 1, 1, 1, 1, 1}, //B
{1, 0, 0, 1, 1, 1, 0, 1}, //C
{1, 1, 1, 1, 1, 1, 0, 1}, //D
{1, 0, 0, 1, 1, 1, 1, 1}, //E
{1, 0, 0, 0, 1, 1, 1, 1}, //F
{0, 0, 0, 0, 0, 0, 0, 1}, //.
};void setup()
{
for(int i=0;i<8;i++)
pinMode(led[i],OUTPUT);
for(int i=0;i<4;i++)
pinMode(com[i],OUTPUT);pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}void loop()
{
distFloat = checkDistance(trigPin, echoPin);
distInt = (int)distFloat*10;
//将距离显示在四位数码管上,需要将dist变量拆分成第一位、第二位、第三位、第四位
firstBit = distInt/1%10;
secondBit = distInt/10%10;
thirdBit = distInt/100%10;
fourthBit = distInt/1000%10;
for(int i=0;i<=500;i++){ //开始在数码管上进行显示
display(2,16); //显示小数点
display(1,firstBit); //显示第一位,即整数部分的百位
delayMicroseconds(eyeDelay); //做了一个视觉延迟
display(2,secondBit);
delayMicroseconds(eyeDelay);
display(3,thirdBit);
delayMicroseconds(eyeDelay);
display(4,fourthBit);
delayMicroseconds(eyeDelay);
}
}void display(unsigned char d,unsigned char n) //显示函数,d可选数值范围1-4,n可选数值范围0-16,16为小数点
{
for(int i=0;i<8;i++) //去除余晖
digitalWrite(led[i],LOW);switch(d) //选通位选
{
case 1:
digitalWrite(com[0],LOW); //选择位1
digitalWrite(com[1],HIGH);
digitalWrite(com[2],HIGH);
digitalWrite(com[3],HIGH);
break;
case 2:
digitalWrite(com[0],HIGH);
digitalWrite(com[1],LOW); //选择位2
digitalWrite(com[2],HIGH);
digitalWrite(com[3],HIGH);
break;
case 3:
digitalWrite(com[0],HIGH);
digitalWrite(com[1],HIGH);
digitalWrite(com[2],LOW); //选择位3
digitalWrite(com[3],HIGH);
break;
case 4:
digitalWrite(com[0],HIGH);
digitalWrite(com[1],HIGH);
digitalWrite(com[2],HIGH);
digitalWrite(com[3],LOW); //选择位4
break;
default:break;
}
for(int i=0;i<8;i++)
digitalWrite(led[i],num[n][i]); //按照码值表进行显示
}float checkDistance(int trig, int echo) //超声波测距函数
{
digitalWrite(trig, LOW); //控制端TRIG先发一个低电平,2微妙
delayMicroseconds(2);
digitalWrite(trig, HIGH); //控制端TRIG先一个高电平,2微妙
delayMicroseconds(10);
digitalWrite(trig, LOW);
float distance = pulseIn(echo, HIGH)/58; //根据接收端ECHO获得的高电平时长计算距离
delay(10);
return distance;
}
这个程序就不再解释了,程序中的注释已经非常清楚了!
4 安装调试
下面我们根据电路图将两个模块跟UNO连接上:
测试一下,效果不错!这里稍微提醒一下,由于超声波本身的特性,对于测试软目标距离,如衣物,会有一定误差,对于硬目标距离的测试,如墙壁,会比较准确,您可以测试测试!
5 总结扩展
为了能够让大家明白LED显示模块的一般驱动原理,这个项目我没有使用任何库,您会发现主程序比较长,看起来似乎也比较复杂,关键是还不能复用。
您能够根据这个主程序,为超声波测距模块和四位数码管写两个库吗?后续,如果有项目中也需要它们,您就可以很方便的复用了!
后面我们还会采用采用基于I2C接口的四位数码管制作一个超声波测距仪!
如果您喜欢本文,您可以点击一下下面的喜欢按钮,您也可以关注我,谢谢您的支持!