用Arduino制作简易超声波测距仪
最近学着玩了一下Arduino,今天下午抽时间试着拿Arduino UNO做了一个简单的超声波测距仪。源代码已经给出来了,愿意动手就能做哦!
材料准备
材料 | 数量 |
---|---|
Arduino Uno或其他类似开发板及其配套数据线 | 1个 |
杜邦线 | 若干 |
超声波测距模块(HC-SR04) | 1个 |
四位数码管 | 1个 |
电阻 | 若干 |
括号里的是我自己使用的型号;当然,你还需要一台装有Arduino IDE的电脑。
Arduino基础
了解过Arduino的请跳过~~
Arduino怎么用?
如你所见,Arduino上有很多插孔,这个叫 I/O
,我们要做的就是通过 C++
程序控制I/O的读取和输出。
这个C++程序怎么写?
什么?你不会C++?快去这里学习吧。。。
Arduino程序必须包含两个函数: setup()
和 loop()
这两个函数简单来说就是先执行 setup()
函数初始化,在无限循环 loop()
函数
咳咳,还是这么解释吧:
void setup();
void loop();
int main() {
setup();
for(;;) {
loop();
}
return 0;
}
超声波测距模块
分析工作原理
由于各个型号的模块针脚可能不同,请查看相关文档,这里我根据我使用的HC-SR04介绍。
采用IO触发测距,给至少10us的高电平信号。模块自动发送8个40khz的方波,自动检测是否有信号返回。有信号返回,通过IO输出一高电平,高电平持 续的时间就是超声波从发射到返回的时间。测试距离=(高电平时间*声速(340m/s))/2
一个完整的测距过程
GND
接Arduino的GND
,VCC
接Arduino的5V
下面开始测距:
- 给
Trig
一个至少10微秒的脉冲 - 监听输出端口并开始计时
- 当输出端口出现高电平时计时结束
- 根据声速计算距离
代码
首先,为了接线方便,超声波测距模块连Arduino的 A2
~ A5
引脚。
#define GND A2
#define ECHO A3
#define TRIG A4
#define VCC A5
在 setup()
函数里我们初始化引脚
void setup() {
// …………
pinMode(GND, OUTPUT); // 输出 0V 电压
pinMode(VCC, OUTPUT); // 输出 5V 电压
pinMode(TRIG, OUTPUT); // 输出 控制信号
pinMOde(ECHO, INPUT); // 输入端
// …………
digitalWrite(VCC, HIGH); // VCC 5V 高电平
digitalWrite(GND, LOW); // GND 低电平
}
还记得上面的步骤吗?
在 loop()
里我们先将 Trig
设为高电平( digitalWrite(TRIG, HIGH);
),50微秒后变回低电平,也就是形成一个50微秒的脉冲
再调用Arduino库函数 pulseln()
,这个函数等待一个端口变为高电平并开始计时,再变为低电平时停止计时,并返回时间间隔(单位为微秒)
最后计算距离
代码如下:
void loop() {
digitalWrite(TRIG, HIGH); // 先将 `Trig` 设为高电平
delayMicroseconds(50); // 等待 50 微秒
digitalWrite(TRIG, LOW); // 先将 `Trig` 设为低电平
double time = double(pulseIn(ECHO, HIGH)) / 1000000; // 保存以秒为单位的时间间隔
show(time * 340 / 2); // 将计算结果传递给 `show()` 函数,这个函数的实现在后面
}
四位数码管
分析工作原理
我用的是共阴数码管,原理图如下:
可以看到,当12低电平时,其他引脚控制第一个数字,当9为低电平时,其他引脚控制第一个数字,以此类推。
注意!要在 12 , 9 , 8 , 6 四个引脚分别串联一个合适阻值的电阻,具体阻值要看数码管的工作电压。
如下表:
数字 | 高电平的引脚 |
---|---|
0 | ABCDEF |
1 | BC |
2 | ABDEG |
3 | ABCDG |
4 | BCFG |
5 | ACDFG |
6 | ACDEFG |
7 | ABC |
8 | ABCDEFG |
9 | ABCDFG |
代码
为了用字母而不是数字表示引脚,可以在程序的开头定义如下:
#define l1 13 // Arduino 的 13 号引脚 连数码管的 12 号引脚
#define l2 12 // Arduino 的 12 号引脚 连数码管的 9 号引脚
#define l3 11 // Arduino 的 11 号引脚 连数码管的 8 号引脚
#define l4 2 // Arduino 的 2 号引脚 连数码管的 6 号引脚
#define la 10 // Arduino 的 10 号引脚 连数码管的 11 号引脚
#define lb 8 // Arduino 的 8 号引脚 连数码管的 7 号引脚
#define lc 4 // Arduino 的 4 号引脚 连数码管的 4 号引脚
#define ld 6 // Arduino 的 6 号引脚 连数码管的 2 号引脚
#define le 7 // Arduino 的 7 号引脚 连数码管的 1 号引脚
#define lf 9 // Arduino 的 9 号引脚 连数码管的 10 号引脚
#define lg 3 // Arduino 的 3 号引脚 连数码管的 5 号引脚
#define ldp 5 // Arduino 的 5 号引脚 连数码管的 3 号引脚
#define DELAY 5 // 用于控制每次测量的间隔
初始化引脚
void setup() {
for (int i = 2; i < 14; i++) {
pinMode(i, OUTPUT);
}
// …………
}
封装每个数字为函数
void flush() {
digitalWrite(la, LOW);
digitalWrite(lb, LOW);
digitalWrite(lc, LOW);
digitalWrite(ld, LOW);
digitalWrite(le, LOW);
digitalWrite(lf, LOW);
digitalWrite(lg, LOW);
digitalWrite(ldp, LOW);
}
void show_num(int num) {
switch (num) {
case 0:
_show_0();
break;
case 1:
_show_1();
break;
case 2:
_show_2();
break;
case 3:
_show_3();
break;
case 4:
_show_4();
break;
case 5:
_show_5();
break;
case 6:
_show_6();
break;
case 7:
_show_7();
break;
case 8:
_show_8();
break;
case 9:
_show_9();
break;
default:
break;
}
}
void _show_0() {
digitalWrite(la, HIGH);
digitalWrite(lb, HIGH);
digitalWrite(lc, HIGH);
digitalWrite(ld, HIGH);
digitalWrite(le, HIGH);
digitalWrite(lf, HIGH);
}
void _show_1() {
digitalWrite(lb, HIGH);
digitalWrite(lc, HIGH);
}
void _show_2() {
digitalWrite(la, HIGH);
digitalWrite(lb, HIGH);
digitalWrite(lg, HIGH);
digitalWrite(ld, HIGH);
digitalWrite(le, HIGH);
}
void _show_3() {
digitalWrite(la, HIGH);
digitalWrite(lb, HIGH);
digitalWrite(lg, HIGH);
digitalWrite(ld, HIGH);
digitalWrite(lc, HIGH);
}
void _show_4() {
digitalWrite(lf, HIGH);
digitalWrite(lg, HIGH);
digitalWrite(lb, HIGH);
digitalWrite(lc, HIGH);
}
void _show_5() {
digitalWrite(la, HIGH);
digitalWrite(lf, HIGH);
digitalWrite(lg, HIGH);
digitalWrite(lc, HIGH);
digitalWrite(ld, HIGH);
}
void _show_6() {
digitalWrite(la, HIGH);
digitalWrite(lf, HIGH);
digitalWrite(le, HIGH);
digitalWrite(ld, HIGH);
digitalWrite(lc, HIGH);
digitalWrite(lg, HIGH);
}
void _show_7() {
digitalWrite(la, HIGH);
digitalWrite(lb, HIGH);
digitalWrite(lc, HIGH);
}
void _show_8() {
digitalWrite(la, HIGH);
digitalWrite(lb, HIGH);
digitalWrite(lc, HIGH);
digitalWrite(ld, HIGH);
digitalWrite(le, HIGH);
digitalWrite(lf, HIGH);
digitalWrite(lg, HIGH);
}
void _show_9() {
digitalWrite(la, HIGH);
digitalWrite(lb, HIGH);
digitalWrite(lc, HIGH);
digitalWrite(ld, HIGH);
digitalWrite(lf, HIGH);
digitalWrite(lg, HIGH);
}
注意!
我们要显示的是XX.XX米,其中第二个小数点要正确显示,我们写一个函数,接受一个小于10000的正整数,如344,显示为03.44(米)。所以前面调用 show()
的时候传入的参数应该乘100。
void show(int num) {
// 一次测量结果显示 300 / DELAY 秒。
for (int i = 0; i < 300 / DELAY; i++) {
int tmp = num;
int j;
flush();
j = tmp % 10;
show_num(j);
digitalWrite(l4, LOW);
delay(DELAY);
digitalWrite(l4, HIGH);
tmp -= j;
tmp /= 10;
flush();
j = tmp % 10;
show_num(j);
digitalWrite(l3, LOW);
delay(DELAY);
digitalWrite(l3, HIGH);
tmp -= j;
tmp /= 10;
flush();
j = tmp % 10;
show_num(j);
digitalWrite(ldp, HIGH);
digitalWrite(l2, LOW);
delay(DELAY);
digitalWrite(l2, HIGH);
tmp -= j;
tmp /= 10;
flush();
j = tmp % 10;
show_num(j);
digitalWrite(l1, LOW);
delay(DELAY);
digitalWrite(l1, HIGH);
}
}
全部代码
#define l1 13
#define l2 12
#define l3 11
#define l4 2
#define la 10
#define lb 8
#define lc 4
#define ld 6
#define le 7
#define lf 9
#define lg 3
#define ldp 5
#define GND A2
#define ECHO A3
#define TRIG A4
#define VCC A5
#define DELAY 5
void setup() {
for (int i = 2; i < 14; i++) {
pinMode(i, OUTPUT);
}
pinMode(GND, OUTPUT);
pinMode(VCC, OUTPUT);
pinMode(TRIG, OUTPUT);
pinMOde(ECHO, INPUT);
digitalWrite(VCC, HIGH);
digitalWrite(GND, LOW);
}
void loop() {
digitalWrite(TRIG, LOW);
delayMicroseconds(5);
digitalWrite(TRIG, HIGH);
delayMicroseconds(50);
digitalWrite(TRIG, LOW);
double time = double(pulseIn(ECHO, HIGH)) / 10000;
show(int(time * 340 / 2));
}
void show(int num) {
for (int i = 0; i < 300 / DELAY; i++) {
int tmp = num;
int j;
flush();
j = tmp % 10;
show_num(j);
digitalWrite(l4, LOW);
delay(DELAY);
digitalWrite(l4, HIGH);
tmp -= j;
tmp /= 10;
flush();
j = tmp % 10;
show_num(j);
digitalWrite(l3, LOW);
delay(DELAY);
digitalWrite(l3, HIGH);
tmp -= j;
tmp /= 10;
flush();
j = tmp % 10;
show_num(j);
digitalWrite(ldp, HIGH);
digitalWrite(l2, LOW);
delay(DELAY);
digitalWrite(l2, HIGH);
tmp -= j;
tmp /= 10;
flush();
j = tmp % 10;
show_num(j);
digitalWrite(l1, LOW);
delay(DELAY);
digitalWrite(l1, HIGH);
}
}
void flush() {
digitalWrite(la, LOW);
digitalWrite(lb, LOW);
digitalWrite(lc, LOW);
digitalWrite(ld, LOW);
digitalWrite(le, LOW);
digitalWrite(lf, LOW);
digitalWrite(lg, LOW);
digitalWrite(ldp, LOW);
}
void show_num(int num) {
switch (num)
{
case 0:
_show_0();
break;
case 1:
_show_1();
break;
case 2:
_show_2();
break;
case 3:
_show_3();
break;
case 4:
_show_4();
break;
case 5:
_show_5();
break;
case 6:
_show_6();
break;
case 7:
_show_7();
break;
case 8:
_show_8();
break;
case 9:
_show_9();
break;
default:
break;
}
}
void _show_1() {
digitalWrite(lb, HIGH);
digitalWrite(lc, HIGH);
}
void _show_2() {
digitalWrite(la, HIGH);
digitalWrite(lb, HIGH);
digitalWrite(lg, HIGH);
digitalWrite(ld, HIGH);
digitalWrite(le, HIGH);
}
void _show_3() {
digitalWrite(la, HIGH);
digitalWrite(lb, HIGH);
digitalWrite(lg, HIGH);
digitalWrite(ld, HIGH);
digitalWrite(lc, HIGH);
}
void _show_4() {
digitalWrite(lf, HIGH);
digitalWrite(lg, HIGH);
digitalWrite(lb, HIGH);
digitalWrite(lc, HIGH);
}
void _show_5() {
digitalWrite(la, HIGH);
digitalWrite(lf, HIGH);
digitalWrite(lg, HIGH);
digitalWrite(lc, HIGH);
digitalWrite(ld, HIGH);
}
void _show_6() {
digitalWrite(la, HIGH);
digitalWrite(lf, HIGH);
digitalWrite(le, HIGH);
digitalWrite(ld, HIGH);
digitalWrite(lc, HIGH);
digitalWrite(lg, HIGH);
}
void _show_7() {
digitalWrite(la, HIGH);
digitalWrite(lb, HIGH);
digitalWrite(lc, HIGH);
}
void _show_8() {
digitalWrite(la, HIGH);
digitalWrite(lb, HIGH);
digitalWrite(lc, HIGH);
digitalWrite(ld, HIGH);
digitalWrite(le, HIGH);
digitalWrite(lf, HIGH);
digitalWrite(lg, HIGH);
}
void _show_9() {
digitalWrite(la, HIGH);
digitalWrite(lb, HIGH);
digitalWrite(lc, HIGH);
digitalWrite(ld, HIGH);
digitalWrite(lf, HIGH);
digitalWrite(lg, HIGH);
}
void _show_0() {
digitalWrite(la, HIGH);
digitalWrite(lb, HIGH);
digitalWrite(lc, HIGH);
digitalWrite(ld, HIGH);
digitalWrite(le, HIGH);
digitalWrite(lf, HIGH);
}
接线
前面其实都已经讲过了,这里再复述一遍:
Arduino引脚 | 四位数码管引脚 | 超声波测距仪引脚 |
---|---|---|
A2 | GND | |
A3 | ECHO | |
A4 | TRIG | |
A5 | VCC | |
3 | 5 | |
4 | 4 | |
5 | 3 | |
6 | 2 | |
7 | 1 | |
8 | 7 | |
9 | 10 | |
10 | 11 | |
11 | 8 | |
12 | 9 | |
13 | 12 |
完成!
我已经成功了,你也快去试试吧~~