5-1假期闲的没事继续折腾树莓派。这次是尝试模拟一个防盗报警器,用HC-SR501 被动红外动作感应器 (Passive Infrared/PIR motion sensor)来触发USBcamera拍照。大概的思路就是如果被动红外动作感应器被触发时,则调用USB摄像头连续拍照N次。
使用的设备:
树莓派
HC-SR501 被动红外动作感应模块 (工作电压5V,信号输出未触发0V ,触发时3.3V)
USB摄像头 (我使用的是Logitech C920,其实完全不用这么高端的……)
LED x1
470Ω 电阻 (与LED串联作为保护)
杜邦线
面包板
物理连线
连线之前的考虑:
许多传感器都没有电源接反的保护,接之前请务必再三确认正确再连接。
不同设备的数据输出不一定是3.3V的,有些有可能用5V表示1。我是先用万用表又验证了HC-SR501的数据输出是3.3V才敢连接树莓派的GPIO接口的。如果电压不匹配还非要去连接,则行为很可能异常,甚至损坏硬件。
线路连接:
HC-SR501连接树莓派 接线示意图
HC-SR501连接树莓派 电路图
HC-SR501的电源连接树莓派5V输出,GND连接树莓派的GND,中间的data连接树莓派的GPIO接口,我使用的是11口 (GPIO 17)。
USB摄像头连接树莓派的USB接口 (我是实际是连接到USB hub上了)
根据需要有可能要调整HC-SR501上的电位器来调节触发距离和延时
根据需要有可能要调整HC-SR501上的跳线位置来设置允许多次重复触发
检查连线:
目视确认面包线连接正确并且牢固,使用lsusb查看系统是否识别出了USB摄像头,使用 ls /dev/video* 检验USB摄像头的编号。
root@raspberrypi ~ # lsusb
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 1a40:0101 Terminus Technology Inc. 4-Port HUB
Bus 001 Device 005: ID 0bda:8176 Realtek Semiconductor Corp. RTL8188CUS 802.11n WLAN Adapter
Bus 001 Device 006: ID 046d:082d Logitech, Inc.
Bus 001 Device 007: ID 099a:7160 Zippy Technology Corp. Hyper Slim Keyboard
root@raspberrypi ~ # ls /dev/video*
/dev/video0
实现所用的bash脚本
下面脚本其实是通过轮询的方式每间隔1秒(可调)通过sysfs方式查询一下sensor的状态,然后复制sensor状态到另外一个GPIO接口;如果sensor是被触发,则调用fswebcam来实现拍照。
脚本中我尽量将不同功能拆成函数了,尽管这样效率并不是最高的。在init_led和init_sensor函数中,尽管只有1个报警用的LED和1个sensor,我还是用循环的方式去做初始化,这也不是最优的方法。这样做主要是为了以后做多个sensor和多个LED故意预留的。
HC-SR501传感器是通过3.3V输出来表示被触发时的“1”,这个电压驱动LED也足够,我实际测试了,即使不没有树莓派,1个LED连接到HC-SR501的data输出已经可以实现灯光告警,但是在这个时候LED的光线不够亮,而且不连接树莓派也没法去调用USB摄像头拍照了 ? ……
#!/bin/bash
#A Sample script to demo PIR motion sensor trigger LED and USB camera
#Written by Kang Liu ()
#You have the freedom to use and/or modify the script, and the freedom to distribute modified and therefore derivative script.
#USB video camera device
videodev="/dev/video0"
#gpio number for the sensor & LED
redled=18
sensor=17
#second(s) between each check
waitperiod=1
#photo settings
photorepeattimes=3
resolution="800x600"
#Directory to store captured photos
directory="/tmp"
#Init GPIO sysfs
#Set default as "Off" for LEDs
init_led ()
{
for i in $redled
do
if [ ! -d /sys/class/gpio/gpio$i ]
then
echo $i >/sys/class/gpio/export
fi
echo "out" >/sys/class/gpio/gpio$i/direction
echo 0 >/sys/class/gpio/gpio$i/value
done
}
init_sensor ()
{
for i in $sensor
do
if [ ! -d /sys/class/gpio/gpio$i ]
then
echo $i >/sys/class/gpio/export
fi
echo "in" >/sys/class/gpio/gpio$i/direction
done
}
init_led_sensor ()
{
init_led
init_sensor
}
#Turn off LED(s) before exit and unexport the sysfs
cleanup()
{
init_led_sensor
for i in $redled $sensor
do
if [ -d /sys/class/gpio/gpio$i ]
then
echo $i > /sys/class/gpio/unexport
fi
done
exit 0
}
capture_photo()
{
for (( c=0; c
do
filename=$directory/$(date -u +"%d%m%Y_%H%M-%S").jpg
fswebcam -d $videodev --timestamp "%Y-%m-%d %H:%M:%S (%Z)" -r $resolution $filename
sleep 1
done
}
check_activity()
{
sensor_status=`cat /sys/class/gpio/gpio$sensor/value`
#Mirror sensor status to another GPIO
echo $sensor_status > /sys/class/gpio/gpio$redled/value
#If sensor is triggered,capture photo
if [ "$sensor_status" -eq 1 ]
then
capture_photo
fi
}
init_led_sensor
trap cleanup INT TERM EXIT
while :
do
check_activity
sleep $waitperiod
done
实验后考虑的改进
如果不想在屏幕上看到每次拍照时执行的细节,可以考虑为fswebcam加上-q参数,将脚本中的fswebcam命令修改成如下:
fswebcam -q -d $videodev --timestamp "%Y-%m-%d %H:%M:%S (%Z)" -r $resolution $filename
树莓派的SD卡空间有限,图片的贮存位置在脚本中默认写的是/tmp目录,当然通过Linux挂载NFS/Samba (NT Folder)/云端等等对这段脚本而言,都仅仅是在系统中的某个目录。因此这里就没有特别去在图片存储方面再多考虑了,利用Linux系统本身的能力即可实现将存储“网络化/云端化”。
本文是用bash脚本方式实现功能的,上面代码只是做功能演示,效率并不高。如果用C去写一段代码,当传感器被触发后,用中断的方式触发告警动作可能会是比轮询更好的选择。留待以后有时间再去琢磨。
这次我使用的HC-SR501 传感器并不足够敏感。做完所有测试之后,我故意试了试从远处以很慢的速度接近传感器,其实只要足够慢是可以不触发报警的……如果真的要用来做防盗报警器,估计还需要用更灵敏的传感器,甚至将不同种类的传感器进行结合使用。总体而言,这其实是一个非常非常简单的实验。这个实验中使用的传感器也应该是几乎最简单最入门的了,只有0(未触发)和1(触发)两个状态。写这个脚本仅是利用树莓派将传感器告警与后续动作连接起来。至于后续动作是亮个LED灯,还是拍照,甚至是打出去电话、记录日志、发短信、带动继电器做通/断电动作等都是可以实现的。等日后有更实际些的应用再看怎么做了。
Share this: