使用 Raspberry Pi 构建运动检测系统

设置一个廉价的家庭安全系统,在有人在你家附近徘徊时发出警报。
121 位读者喜欢这篇文章。
Houses in a row

27707 通过 Pixabay,CC0 许可。由 Jen Wike Huger 修改。

如果你想要一个家庭安全系统来告诉你是否有人在你家附近徘徊,你不需要从第三方供应商那里购买昂贵的专有解决方案。你可以使用 Raspberry Pi、被动红外 (PIR) 运动传感器和 LTE 调制解调器来设置自己的系统,该系统会在检测到移动时发送短信。

先决条件

你将需要:

  • 一台带有以太网连接和 Raspberry Pi OS 的 Raspberry Pi
  • 一个 HC-SR501 PIR 运动传感器
  • 1 个红色 LED
  • 1 个绿色 LED
  • 一个 LTE 调制解调器(我使用了 Teltonika TRM240
  • 一张 SIM 卡

PIR 运动传感器

当发出红外线的东西(例如,人、动物或任何发热的东西)在传感器的视野或范围移动时,PIR 运动传感器会感应到运动。PIR 运动传感器功耗低且价格便宜,因此它们被用于许多检测运动的产品中。它们无法判断该区域有多少人以及他们离传感器有多近;它们只能检测运动。

PIR 传感器有两个电位器,一个用于设置延迟时间,另一个用于设置灵敏度。延迟时间调整设置了在检测到运动后输出应保持高电平的时间长度;它可以是五秒到五分钟之间的任何时间。灵敏度调整设置了检测范围,可以是三米到七米之间的任何距离。

LTE 调制解调器

长期演进 (LTE) 是一种基于 GSM/EDGE 和 UMTS/HSPA 技术的无线宽带通信标准。我使用的 LTE 调制解调器是一个 USB 设备,可以为 Raspberry PI 计算机添加 3G 或 4G (LTE) 蜂窝网络连接。在这个项目中,我没有使用调制解调器进行蜂窝网络连接,而是用来在检测到运动时向我的手机发送消息。我可以使用串行通信和 AT 命令来控制调制解调器;后者将消息从调制解调器发送到我的电话号码。

如何设置您的家庭安全系统

步骤 1:安装软件

首先,在你的 Raspberry Pi 上安装必要的软件。在 Raspberry Pi 的终端中,输入

sudo apt install python3 python3-gpiozero python-serial -y

步骤 2:设置调制解调器

按照 TRM240 的这些 说明,将你的 SIM 卡插入你的 LTE 调制解调器。确保将天线安装在调制解调器上以获得更好的信号。

步骤 3:将调制解调器连接到 Raspberry Pi

将 LTE 调制解调器连接到 Raspberry Pi 的 USB 端口之一,然后等待设备启动。你应该在 /dev 目录中看到四个新的 USB 端口。你可以通过在终端中执行此命令来检查它们

ls /dev/ttyUSB*

你现在应该看到这些设备

你将使用 ttyUSB2 端口通过发送 AT 命令与设备进行通信。

步骤 4:将传感器连接到 Raspberry Pi

  1. 连接 PIR 传感器

    VCCGND 引脚连接到 Raspberry Pi 上相应的引脚,并将运动传感器的输出引脚连接到 Raspberry Pi 上的 8 号引脚。请参阅下面的原理图了解这些连接,你可以在 GPIO Zero 文档中了解更多关于 Raspberry Pi 引脚编号的信息。

  2. 连接 LED 灯

    如果你想要在检测到运动时指示灯 LED 亮起,请将 LED 的阴极(短腿,扁平侧)连接到接地引脚;将阳极(长腿)连接到限流电阻;并将电阻的另一侧连接到 GPIO 引脚(限流电阻可以放置在 LED 的任一侧)。将红色 LED 连接到板上的 38 号引脚,将绿色 LED 连接到 40 号引脚

请注意,此步骤是可选的。如果你不想要在检测到运动时有指示灯 LED,请从下面的示例代码中删除 LED 部分。

步骤 5:启动程序

使用终端(或任何文本编辑器),创建一个名为 motion_sensor.py 的文件,并将下面的 示例代码 粘贴进去。

查找并更改这些字段

  • phone_number
  • message

如果你使用了不同的引脚来连接传感器,请确保相应地更改代码。

当一切都设置好并准备就绪时,通过在终端中输入以下命令来启动程序

python3 motion_sensor.py

如果你没有启动程序所需的权限,请尝试此命令

sudo python3 motion_sensor.py

示例代码

from gpiozero import MotionSensor, LED
from time import sleep, time
from sys import exit
import serial
import threading


# Raspberry Pi GPIO pin config
sensor = MotionSensor(14)
green = LED(21)
red = LED(20)

# Modem configuration
device = '/dev/ttyUSB2'
message = '<message>'
phone_number = '<phone_number>'
sms_timeout = 120 # min seconds between SMS messages


def setup():
    port.close()

    try:
        port.open()
    except serial.SerialException as e:
        print('Error opening device: ' + str(e))
        return False

    # Turn off echo mode
    port.write(b'ATE0 \r')
    if not check_response('OK', 10):
        print('Failed on ATE0')
        return False

    # Enter SMS text mode
    port.write(b'AT+CMGF=1 \r')
    if not check_response('OK', 6):
        print('Failed on CMGF')
        return False

    # Switch character set to 'international reference alphabet'
    # Note: this still doesn't support all characters
    port.write(b'AT+CSCS="IRA" \r')
    if not check_response('OK', 6):
        print('Failed on CSCS')
        return False

    return True


def check_response(string, amount):
    result = ''

    try:
        result = port.read(amount).decode()
    except:
        return False

    if not string in result:
        try:
            # Write 'ESC' to exit SMS input mode, just in case
            port.write(b'\x1B \r')
        except:
            return False

    return string in result


def send_sms():
    global currently_sending, last_msg_time
    currently_sending = True

    try:
        port.write('AT+CMGS="{}" \r'.format(phone_number).encode())
        if not check_response('>', 6):
            print('Failed on CMGS')
            currently_sending = False
            return

        # Write the message terminated by 'Ctrl+Z' or '1A' in ASCII
        port.write('{}\x1A \r'.format(message).encode())

        while True:
            result = port.readline().decode()

            if 'OK' in result:
                print('> SMS sent successfully')
                last_msg_time = time() 
                currently_sending = False
                return

            if 'ERROR' in result:
                print('> Failed to send SMS [{}]'.format(result.rstrip()))
                currently_sending = False
                return
    except:
        # Initiate setup if the got while the program was running
        setup()
        currently_sending = False


def on_motion():
    print('Motion detected!')
    green.off()
    red.on()

    if time() - last_msg_time > sms_timeout and not currently_sending:
        print('> Sending SMS...')
        threading.Thread(target=send_sms).start()


def no_motion():
    green.on()
    red.off()


print('* Setting up...')
green.on()
red.on()

port = serial.Serial()
port.port = device
port.baudrate = 115200
port.timeout = 2

last_msg_time = 0
currently_sending = False

if not setup():
    print('* Retrying...')
    if not setup():
        print('* Try restarting the modem')
        exit(1)

print('* Do not move, setting up the PIR sensor...')
sensor.wait_for_no_motion()

print('* Device ready! ', end='', flush=True)
green.on()
red.off()

sensor.when_motion = on_motion
sensor.when_no_motion = no_motion
input('Press Enter or Ctrl+C to exit\n\n')

 

接下来阅读什么
标签
User profile image.
我是一名来自立陶宛的程序员/管理员。我感兴趣的领域是:Linux 嵌入式 Linux 网络编程 其他嵌入式系统,如 Arduino 和许多其他系统

评论已关闭。

Creative Commons License本作品根据 Creative Commons 许可协议 4.0 国际许可协议获得许可。
© . All rights reserved.