初玩树莓派 B 6 人体红外感应报警
bbs.pediy.com
前面的 LED 灯我们操作使用的 GPIO 的输出功能,这次我们终于需要用到 GPIO 的输入功能了。由
于这个人体红外感应模块的使用比较简单。所以我们实验完毕以后配合前面的蜂鸣器一起,做一个简单
的人体感应报警器。
1 HC-SR501 感应模块简介
我们采用 HC-SR501 型号的人体红外感应器来探测人体。更加详细的参数参考模块的使用说明书。
对照前面的参数以及电路图,找到下面的左右针脚正负极,中间的 PIN 为感应输出,感应到人体时,
输出 3.3V 高电平,检测不到信号时输出 0。同时还要求工作电压在 4.5V-20V 之间。恰好树莓派的 P1
编号中第 2,4 号 PIN 都是 5V 的电压,满足要求,所以这次我们要接 5V 的电压。
参数调节旋钮是用来扭动控制一些参数的。比如探测的延时时间,灵敏度等等。具体可以参看 HC
-SR501 的说明书。这里我们都使用默认值。
但是有一个关键的 L H 模式调节阀门要介绍一下,右上角有三个针脚,按照我实物照片,假定从上
到下为 123 。还有一个黄色的套接头,图中套接头接通了 2 3 号,代表了 H 模式,这个套接头是可以拔
下来的,然后插到上面来,接通 1 2 号,代表了 L 模式。
L 模式是不可重复触发,当探测到一次人体时,输出一次高电平,保持一段时间恢复低电平,在此
期间如果还是检测到了人体也不再延长这个高电平的时间。等到低电平的封锁时间(前面默认是 2.5S)
过了以后才又开始检测。
H 模式是可以重复触发,如果一直感应到人体时,会一直输出高电平,直到探测不到人体后保持小
段时间然后恢复低电平。
2 GPIO 输入的上拉和下拉
对于学习软件的人来说,软件的世界只有 0 和 1,所以我接触硬件之前也是这么认为的。所以
我在使用人体红外感应的时候遇到了一个问题,我认为只要设置 GPIO 的模式为 INPUT,后面只
需要读取针脚的状态 0,1 就行了。结果我遇到一个问题。当我在设置比如 pin22(wiringpi 标号为
6)为 INPUT 模式,接上一根线后,这一条线另一端什么都不接,按理说这时应该输入为 0V,但
是我尝试读取发现并不是一直保持低电平,而是一会儿高,一会低,用手握住另外一端就会输出
高电平。当我接 pin3(wiringPi 标号为 8)却始终是高电平。不得不查询各种资料,发现还有上拉
和下拉这种说法。
当我们给一个针脚接入 GND,那么就是低电平,如果我们给一个针脚 3.3V,那么就是高电平,
状态是很确定的。如果我们什么都不接,那么这个针脚处于悬浮状态,很容易受到外接的干扰,
可能是高也可能是低,也可能是处于高和低之间的状态。这时候我们就要明确指定这个针脚应该
处于高或者低,不能让他处于悬浮状态。接入一个上拉电阻能够让这个针脚处于明确的高电平状
态,接入一个下拉电阻能够让他处于明确的低电平状态。前面我们用作输出的时候都是明确给定
了输出的高低状态。关于上拉电阻和下拉电阻,有一篇英文解释写的很不错,我也是参考这篇来
看的,里面的测试大家也可以用树莓派测试一下。(http://www.bit-101.com/blog/?p=3813)。
PIN3 始终处于高电平状态是因为。这个 PIN 口是用于树莓派 I2C 设备的,内部外接了一个物
理的上拉电阻。所以他的状态一直是高电平,作为 INPUT 不能使用这个 PIN。
PIN22 时高时低就是由于处于悬浮状态。所以我们要使用这个 PIN 就比如为他明确指定悬浮
的时候是高还是低。wiringpi 通过 pullUpDnControl 来控制这个变量。
3 接线以及测试
模块左边的针脚 1 接 P1 编号的 PIN2 为 5V 的正极,模块右边的针脚 3 的负极接 PIN6,模块
中间的针脚 2 输出线接 PIN22(wiringPi 就是标号 6)。
接线图如下:
图中我连蜂鸣器也接上去了。当我们检测到人体的时候。使用前一节的 beep 函数发出警告声音。
我们先初步检测一下模块有没有工作正常。测试 HC-SR501 不同的模式。
选择的 H 模式,套接头接下面两个脚。也就是可以重复触发,检测到人体,一直处于高电平。
可以看出中间是连续的检测,也就是高电平的时间随着人的活动延长了。
如果选择的 L 模式,套接头接上面两个脚。也就是不可以重复触发,检测到人体,输出高电
平一段时间,后续一小段时间内检测到也不再延长这个高电平时间,必须等到锁定时间过了才会
再次检测。
可以看出中间高电平的时间不是持续的。
检测的代码很简单:
#include
#include
#include
#include
#define INFRAREDPIN 6
int main()
{
int AnyBodyHere=0;
wiringPiSetup();
//设置为输入模式
pinMode(INFRAREDPIN,INPUT);
//很重要。控制默认情况下此 PIN 处于下拉低电平状态
pullUpDnControl(INFRAREDPIN,PUD_DOWN);
while(true)
{
//每一秒检测依次状态
delay(1000);
//读取当前 pin 的输入状态
AnyBodyHere=digitalRead(INFRAREDPIN);
if(AnyBodyHere)
{
printf("There is somebody here\n");
}
else
{
printf("There is no one here\n");
}
}
}
我们稍微修改一下。在检测到人体的时候使用第五节的 beep 函数执行报警的操作,这里我们选择
使用 H 模式,持续感应,感应到以后使用 beep 发声。这样就简单实现了人体感应后自动报警。
具体代码下载 infrared.c 参考。