随着公司不断变大,作为报警监控用的“大电视”也越来越重要。但是更换位置之后,“大电视”被各种显示器遮挡,出现情况后,无法第一眼看到,所以做一个报警器来监控一下。

1 材料

准备需要的材料如下:

  • 树莓派一个;

  • SD 卡一张;

  • 报警器一个;

  • 电源线(带插头)一根;

  • 继电器一个;

  • 杜邦线数根;

  • USB 数据线一根;

  • HDMI 线一根;

  • 键盘一个;

  • 显示器一台;

主要设备如下:

2 安装环境

2.1 烧录系统

准备好一个树莓派镜像,这里使用的是 Raspbian Buster Lite

另外使用 balenaEtcher 烧录软件,进行镜像的烧录,如果有其他的软件,可以根据需要自行进行系统的烧录。

  1. 选择镜像,并选择对应的 SD 卡,点击烧录;

  2. 烧录成功;

2.2 初始化环境

将烧录好的 SD 卡,插到树莓派上,并给树莓派链接显示器、键盘、网线(非必须),之后插入 USB 上电。

经过一次自动重启后,树莓派会成功载入系统,并跳出登陆界面。输入用户名 pi 和默认密码 raspberry 后,进入到系统中。

设置 SSH 及 WiFi(如有必要设置键盘布局)等:

# 进入设置
sudo raspi-config

更新 apt 源及系统:

# apt source
sudo sed -i 's#://raspbian.raspberrypi.org#s://mirrors.ustc.edu.cn/raspbian#g' /etc/apt/sources.list
sudo sed -i 's#://archive.raspberrypi.org/debian#s://mirrors.ustc.edu.cn/archive.raspberrypi.org/debian#g' /etc/apt/sources.list.d/raspi.list

# update and upgrade
sudo apt-get update
sudo apt-get upgrade -y

安装后面需要的模块及软件:

sudo apt-get install -y nginx python3-pip python3-rpi.gpio
sudo pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple flask uwsgi

3 调试继电器

由于报警灯默认是用 220V 的交流电,上来直接测试,会有比较大的安全风险,所以我们这里先用 LED 灯来进行测试,如果成功,再将 LED 灯替换为报警灯。

3.1 继电器

继电器很简单,一端接树莓派进行开关控制,另外一端接设备,如图:

这个继电器对内是直接用树莓派的 5V 电压,对外可以接:

  • 10A 250V 交流电
  • 10A 125V 交流电
  • 10A 30V 直流电
  • 10A 28V 的直流电

从上图可以看到,对外三个接口对应的开关状态,中间接火线,如果希望默认开关长闭状态,对应左边;如果希望默认开关长开状态,对应右边。我们这里希望报警器默认是关闭的,所以接入右边。

3.2 LED

LED 灯就比较简单了,直接两个阵脚,一个接入 GPIO,一个接入负极。

最后整体如图:

3.2 调试

这里用 Python3 简单调试一下,代码如下:

import RPi.GPIO as GPIO
import time

# GPIO 17
led_pin = 11
# GPIO 18
relay_pin = 12


def setup():
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(led_pin, GPIO.OUT)
    GPIO.setup(relay_pin, GPIO.OUT)

    # led on
    GPIO.output(led_pin, GPIO.HIGH)
    # relay off
    GPIO.output(relay_pin, GPIO.LOW)


def loop():
    relay = 0
    while True:
        GPIO.output(relay_pin, GPIO.HIGH if relay == 1 else GPIO.LOW)
        time.sleep(2)
        relay = int(input('0: Close, 1: Open'))


def destroy():
    GPIO.output(led_pin, GPIO.LOW)
    GPIO.output(relay_pin, GPIO.LOW)

    # Release resource
    GPIO.cleanup()


if __name__ == '__main__':
    setup()
    try:
        loop()
    except KeyboardInterrupt:
        # When 'Ctrl+C' is pressed,
        # the child program destroy() will be  executed.
        destroy()

逻辑很简单,当输入 1 时,继电器进入闭合状态,LED 会亮起来;当输入 0 时,继电器进入打开状态,LED 会关闭。

4 调试报警灯

链接报警灯:

当然这是初步连接,用于给大家展示接口,有需要尝试的小伙伴,一定要用电工胶布,把裸露的电线包好,避免出现意外事故。

连接好之后,插入电源,用下面的代码进行测试。

import RPi.GPIO as GPIO
import time

# GPIO 18
relay_pin = 12


def setup():
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(relay_pin, GPIO.OUT)
    GPIO.output(relay_pin, GPIO.LOW)


def loop():
    relay = 0
    while True:
        GPIO.output(relay_pin, GPIO.HIGH if relay == 1 else GPIO.LOW)
        time.sleep(2)
        relay = int(input('0: Close, 1: Open'))


def destroy():
    GPIO.output(relay_pin, GPIO.LOW)
    GPIO.cleanup()


if __name__ == '__main__':
    setup()
    try:
        loop()
    except KeyboardInterrupt:
        destroy()

报警灯可以正常的进行工作:

5 报警服务

这里用 Nginx + uwsgi + flask 来搭建一个 web 服务,当有报警请求过来时,触发打开报警灯。

5.1 Nginx 配置

在树莓派中执行以下命令:

cd /etc/nginx/sites-enabled/
sudo mv default marmot.conf

修改 marmot.conf 文件,内容如下:

server {
        listen 80;
        listen [::]:80;

        location / {
                include        uwsgi_params;
                uwsgi_pass     127.0.0.1:5051;
                uwsgi_param UWSGI_CHDIR /home/pi/marmot;
                uwsgi_param UWSGI_SCRIPT app:app;
        }
}

重新加载 nginx 配置文件:

sudo service nginx reload

5.2 uwsgi 配置

创建 uwsgi 配置文件 uwsgi_config.ini

[uwsgi]
socket = 127.0.0.1:5051
master = true
project = /home/pi/marmot
pythonpath = %(project)
module = app
wsgi-file = %(project)/app.py
callable = app
processes = 1
threads = 1
daemonize = %(project)/server.log
stats = %(project)/uwsgi/uwsgi.status
pidfile = %(project)/uwsgi/uwsgi.pid

5.3 报警服务

简单写一个 web 服务,有请求时,触发报警:

import time
import logging
import RPi.GPIO as GPIO
from flask import Flask


app = Flask(__name__, instance_relative_config=True)
app.logger.setLevel(logging.INFO)

# GPIO 18
relay_pin = 12


def setup_marmot():
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(relay_pin, GPIO.OUT)
    GPIO.output(relay_pin, GPIO.LOW)

    
def destroy_marmot():
    GPIO.output(relay_pin, GPIO.LOW)
    GPIO.cleanup()
    
    
@app.route('/')
def marmot():
    app.logger.info('what does the marmot say')
    setup_marmot()
    GPIO.output(relay_pin, GPIO.HIGH)
  	time.sleep(5)
    destroy_marmot()
    return 'Ahhhhhhhhhhhhhhh...'


if __name__ == '__main__':
    app.run()

启动服务:

uwsgi --ini uwsgi_config.ini

在浏览器里面,输入树莓派的地址,发送请求测试,报警成功。