当前位置: 首页 > news >正文

编写程序让智能门禁红外检测到人体逗留超10秒,自动提示“请勿逗留”,适配小区安防。

智能门禁红外检测系统 - 社区安防解决方案

一、实际应用场景描述

某老旧小区改造项目,原门禁系统仅支持刷卡/密码开门,存在以下问题:

- 外卖员/访客长时间在门口逗留,易引发盗窃或纠纷

- 物业无法实时获知异常停留情况

- 传统系统无智能提醒功能,依赖人工监控

本系统目标:在门禁区域安装红外热释电传感器,当检测到人体持续停留超过10秒时,通过声光报警+LED屏提示"请勿逗留",同时记录事件日志供物业追溯。

二、引入痛点

痛点类型 具体表现 本方案解决方式

安全隐患 陌生人在门口长时间徘徊,可能踩点或实施犯罪 实时检测+自动预警,形成威慑

管理滞后 物业需24小时人工监控,人力成本高 系统自动触发提示,减少人工依赖

证据缺失 发生事件后无数据记录,难以追溯 自动记录时间戳+事件类型,生成日志

三、核心逻辑讲解

graph TD

A[红外传感器初始化] --> B[持续监测人体信号]

B --> C{是否检测到人体?}

C -- 否 --> B

C -- 是 --> D[记录开始时间T0]

D --> E[持续检测是否保持存在]

E --> F{是否持续超过10秒?}

F -- 否 --> E

F -- 是 --> G[触发声光报警+LED显示"请勿逗留"]

G --> H[记录事件日志]

H --> I[持续检测是否离开]

I --> J{是否离开?}

J -- 是 --> K[停止报警,恢复待机]

J -- 否 --> G

关键逻辑点:

1. 防误触机制:采用"存在确认"模式,需连续3次采样(间隔200ms)均检测到信号才判定为有效进入

2. 时间计算:使用

"time.monotonic()"确保计时精度,避免系统时间调整影响

3. 状态机设计:定义4种状态(IDLE/DETECTED/TIMING/ALERT),确保流程清晰

4. 资源释放:程序退出时自动关闭GPIO和串口连接,防止硬件损坏

四、代码模块化实现

项目结构

smart_access_control/

├── main.py # 主程序入口

├── config.py # 配置文件

├── sensors/ # 传感器模块

│ ├── __init__.py

│ └── ir_sensor.py # 红外传感器驱动

├── alerts/ # 报警模块

│ ├── __init__.py

│ └── notifier.py # 声光报警+LED控制

├── logger/ # 日志模块

│ ├── __init__.py

│ └── event_logger.py # 事件记录

└── utils/ # 工具函数

├── __init__.py

└── time_utils.py # 时间处理工具

1. 配置文件 (config.py)

"""

智能门禁系统配置文件

包含传感器参数、报警设置、日志配置等

"""

# 传感器配置

SENSOR_PIN = 17 # 红外传感器连接的GPIO引脚 (BCM编号)

SAMPLE_INTERVAL = 0.2 # 采样间隔(秒)

CONFIRM_SAMPLES = 3 # 确认存在的连续采样次数

# 时间阈值(秒)

STAY_THRESHOLD = 10 # 触发警告的停留时间

CLEANUP_DELAY = 2 # 报警后持续检测离开的延迟

# 报警配置

ALERT_DURATION = 5 # 单次报警持续时间(秒)

BUZZER_PIN = 18 # 蜂鸣器GPIO引脚

LED_PIN = 23 # 状态LED GPIO引脚

LED_MESSAGE = "请勿逗留" # LED显示屏提示文字

# 日志配置

LOG_FILE = "access_events.log"

LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"

MAX_LOG_SIZE = 1024 * 1024 # 日志最大1MB,循环覆盖

2. 红外传感器模块 (sensors/ir_sensor.py)

"""

红外热释电传感器驱动模块

负责读取人体检测信号并进行有效性验证

"""

import RPi.GPIO as GPIO

import time

from config import SENSOR_PIN, SAMPLE_INTERVAL, CONFIRM_SAMPLES

class IRSensor:

def __init__(self):

"""初始化传感器GPIO设置"""

self.pin = SENSOR_PIN

self.last_state = False

self._setup_gpio()

def _setup_gpio(self):

"""配置GPIO为输入模式,启用上拉电阻"""

GPIO.setmode(GPIO.BCM) # 使用BCM编号

GPIO.setup(self.pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

def read_raw(self) -> bool:

"""

读取原始传感器信号

返回: True-检测到人体, False-未检测到

"""

return GPIO.input(self.pin) == GPIO.LOW # 低电平表示检测到人体

def is_person_present(self) -> bool:

"""

带防误触的存在检测

通过连续多次采样确认,避免瞬间干扰

返回: 确认存在为True

"""

confirm_count = 0

for _ in range(CONFIRM_SAMPLES):

if self.read_raw():

confirm_count += 1

else:

confirm_count = 0 # 一旦失败重置计数

time.sleep(SAMPLE_INTERVAL)

return confirm_count >= CONFIRM_SAMPLES

def cleanup(self):

"""清理GPIO资源"""

GPIO.cleanup(self.pin)

3. 报警通知模块 (alerts/notifier.py)

"""

声光报警与LED显示模块

控制蜂鸣器、状态灯和LED屏幕

"""

import RPi.GPIO as GPIO

import time

import serial

from config import BUZZER_PIN, LED_PIN, ALERT_DURATION, LED_MESSAGE

class AlertNotifier:

def __init__(self):

"""初始化报警设备"""

self.buzzer_pin = BUZZER_PIN

self.led_pin = LED_PIN

self.serial_port = None

self._setup_devices()

def _setup_devices(self):

"""配置蜂鸣器和LED的GPIO,初始化串口连接LED屏"""

GPIO.setmode(GPIO.BCM)

GPIO.setup(self.buzzer_pin, GPIO.OUT)

GPIO.setup(self.led_pin, GPIO.OUT)

# 初始化LED串口连接 (假设使用9600波特率)

try:

self.serial_port = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)

time.sleep(2) # 等待串口稳定

except serial.SerialException as e:

print(f"LED串口连接失败: {e}")

def trigger_alert(self):

"""

触发声光报警

蜂鸣器响+LED闪烁+屏幕显示提示

"""

start_time = time.time()

while time.time() - start_time < ALERT_DURATION:

# 蜂鸣器响

GPIO.output(self.buzzer_pin, GPIO.HIGH)

# LED亮

GPIO.output(self.led_pin, GPIO.HIGH)

# 更新LED屏幕

self._update_led_display(LED_MESSAGE)

time.sleep(0.5)

# 蜂鸣器停

GPIO.output(self.buzzer_pin, GPIO.LOW)

# LED灭

GPIO.output(self.led_pin, GPIO.LOW)

time.sleep(0.5)

def _update_led_display(self, text: str):

"""发送文本到LED显示屏"""

if self.serial_port and self.serial_port.is_open:

try:

self.serial_port.write(f"DISP:{text}\n".encode('utf-8'))

except Exception as e:

print(f"LED更新失败: {e}")

def stop_alert(self):

"""停止所有报警设备"""

GPIO.output(self.buzzer_pin, GPIO.LOW)

GPIO.output(self.led_pin, GPIO.LOW)

if self.serial_port and self.serial_port.is_open:

self.serial_port.close()

def cleanup(self):

"""清理所有设备资源"""

self.stop_alert()

GPIO.cleanup([self.buzzer_pin, self.led_pin])

4. 事件日志模块 (logger/event_logger.py)

"""

事件日志记录模块

记录所有检测事件,用于事后追溯和分析

"""

import logging

import os

from logging.handlers import RotatingFileHandler

from config import LOG_FILE, LOG_FORMAT, MAX_LOG_SIZE

class EventLogger:

def __init__(self):

"""初始化日志系统,使用滚动文件处理"""

self.logger = logging.getLogger("AccessControl")

self.logger.setLevel(logging.INFO)

# 创建日志目录(如果不存在)

log_dir = os.path.dirname(LOG_FILE)

if log_dir and not os.path.exists(log_dir):

os.makedirs(log_dir)

# 配置滚动日志处理器(达到MAX_LOG_SIZE后自动备份)

handler = RotatingFileHandler(

LOG_FILE,

maxBytes=MAX_LOG_SIZE,

backupCount=5,

encoding='utf-8'

)

formatter = logging.Formatter(LOG_FORMAT)

handler.setFormatter(formatter)

self.logger.addHandler(handler)

def log_entry(self, event_type: str, details: str):

"""

记录一条事件日志

event_type: 事件类型 (ENTRY/EXIT/ALERT/NORMAL)

details: 详细描述信息

"""

self.logger.info(f"{event_type}: {details}")

def get_recent_logs(self, lines: int = 10) -> list:

"""获取最近的日志条目"""

try:

with open(LOG_FILE, 'r', encoding='utf-8') as f:

return f.readlines()[-lines:]

except FileNotFoundError:

return []

5. 工具函数模块 (utils/time_utils.py)

"""

时间处理工具模块

提供高精度计时和时间格式化功能

"""

import time

def get_monotonic_time() -> float:

"""

获取单调递增的时钟时间(不受系统时间调整影响)

适用于精确计时场景

"""

return time.monotonic()

def format_duration(seconds: float) -> str:

"""将秒数转换为可读的时间字符串"""

if seconds < 60:

return f"{seconds:.1f}秒"

elif seconds < 3600:

minutes = int(seconds // 60)

secs = int(seconds % 60)

return f"{minutes}分{secs}秒"

else:

hours = int(seconds // 3600)

minutes = int((seconds % 3600) // 60)

return f"{hours}小时{minutes}分"

class Timer:

"""简易计时器类"""

def __init__(self):

self.start_time = None

self.elapsed = 0.0

def start(self):

"""开始计时"""

self.start_time = get_monotonic_time()

def stop(self):

"""停止计时并计算耗时"""

if self.start_time:

self.elapsed = get_monotonic_time() - self.start_time

self.start_time = None

return self.elapsed

def reset(self):

"""重置计时器"""

self.start_time = None

self.elapsed = 0.0

6. 主程序入口 (main.py)

#!/usr/bin/env python3

"""

智能门禁红外检测系统主程序

实现人体停留检测、超时预警、日志记录全流程

"""

import sys

import signal

from sensors.ir_sensor import IRSensor

from alerts.notifier import AlertNotifier

from logger.event_logger import EventLogger

from utils.time_utils import get_monotonic_time, Timer

from config import STAY_THRESHOLD, CLEANUP_DELAY

class AccessControlSystem:

"""智能门禁控制系统主类"""

# 系统状态枚举

STATE_IDLE = "IDLE" # 空闲状态,无人检测

STATE_DETECTED = "DETECTED" # 检测到有人进入

STATE_TIMING = "TIMING" # 计时中,等待超时判断

STATE_ALERT = "ALERT" # 触发警报状态

def __init__(self):

"""初始化所有子系统"""

print("正在初始化智能门禁系统...")

self.sensor = IRSensor()

self.notifier = AlertNotifier()

self.logger = EventLogger()

self.current_state = self.STATE_IDLE

self.timer = Timer()

self.alert_active = False

# 注册信号处理,确保优雅退出

signal.signal(signal.SIGINT, self._signal_handler)

signal.signal(signal.SIGTERM, self._signal_handler)

print("系统初始化完成,开始运行...")

self.logger.log_entry("SYSTEM", "智能门禁系统启动")

def _signal_handler(self, signum, frame):

"""处理终止信号,确保资源正确释放"""

print("\n接收到终止信号,正在清理资源...")

self.shutdown()

sys.exit(0)

def run(self):

"""主运行循环"""

try:

while True:

current_time = get_monotonic_time()

# 状态机处理

if self.current_state == self.STATE_IDLE:

self._handle_idle_state(current_time)

elif self.current_state == self.STATE_DETECTED:

self._handle_detected_state(current_time)

elif self.current_state == self.STATE_TIMING:

self._handle_timing_state(current_time)

elif self.current_state == self.STATE_ALERT:

self._handle_alert_state(current_time)

# 短暂休眠降低CPU占用

time.sleep(0.05)

except Exception as e:

print(f"运行时错误: {e}")

self.logger.log_entry("ERROR", f"运行时异常: {str(e)}")

self.shutdown()

def _handle_idle_state(self, current_time):

"""空闲状态处理:检测是否有人体进入"""

if self.sensor.is_person_present():

self.current_state = self.STATE_DETECTED

self.timer.reset()

print("检测到人体进入...")

self.logger.log_entry("ENTRY", "检测到人员进入检测区域")

def _handle_detected_state(self, current_time):

"""检测到人体后的状态处理"""

# 再次确认人体仍然存在

if self.sensor.is_person_present():

# 开始计时

self.timer.start()

self.current_state = self.STATE_TIMING

print("开始计时停留时间...")

else:

# 误检,返回空闲状态

self.current_state = self.STATE_IDLE

print("误检,返回空闲状态")

def _handle_timing_state(self, current_time):

"""计时状态处理:判断是否超过阈值"""

elapsed = self.timer.stop()

if not self.sensor.is_person_present():

# 人员已离开,记录正常停留

if elapsed > 0:

self.logger.log_entry("NORMAL", f"人员短暂停留 {elapsed:.1f}秒后离开")

self.current_state = self.STATE_IDLE

self.timer.reset()

print("人员已离开,计时结束")

elif elapsed >= STAY_THRESHOLD:

# 超过阈值,触发警报

self.current_state = self.STATE_ALERT

self.alert_active = True

print(f"⚠️ 警告:人员停留超过{STAY_THRESHOLD}秒!")

self.logger.log_entry("ALERT", f"检测到人员异常停留 {elapsed:.1f}秒,触发警报")

self.notifier.trigger_alert()

def _handle_alert_state(self, current_time):

"""警报状态处理:持续检测人员是否离开"""

if not self.sensor.is_person_present():

# 人员离开,停止警报

self.notifier.stop_alert()

self.alert_active = False

self.current_state = self.STATE_IDLE

self.timer.reset()

print("人员已离开,警报解除")

self.logger.log_entry("EXIT", "警报解除,人员离开")

else:

# 人员仍在,持续报警

print("持续报警中... 请尽快处理")

time.sleep(0.5) # 降低报警频率

def shutdown(self):

"""系统关闭,释放所有资源"""

print("正在关闭系统...")

if self.alert_active:

self.notifier.stop_alert()

self.sensor.cleanup()

self.notifier.cleanup()

self.logger.log_entry("SYSTEM", "智能门禁系统正常关闭")

print("系统已安全关闭")

if __name__ == "__main__":

system = AccessControlSystem()

system.run()

五、README文件

# 智能门禁红外检测系统

## 项目简介

基于Python的智能门禁安防系统,通过红外热释电传感器检测人体停留,超过设定时间自动触发声光报警,适用于小区、办公楼等场所的安全防护。

## 功能特性

- ✅ 人体存在检测(带防误触机制)

- ✅ 10秒停留阈值判断

- ✅ 声光报警 + LED屏提示

- ✅ 事件日志记录与追溯

- ✅ 优雅的资源管理

## 硬件要求

| 组件 | 型号/规格 | 数量 |

|------|----------|------|

| 树莓派 | 3B+/4B | 1 |

| 红外传感器 | HC-SR501 | 1 |

| 蜂鸣器 | 有源蜂鸣器 | 1 |

| LED指示灯 | 红色LED | 1 |

| LED显示屏 | 串口LCD1602 | 1 |

| 杜邦线 | - | 若干 |

## 接线示意图

红外传感器 VCC → 树莓派 5V

红外传感器 GND → 树莓派 GND

红外传感器 OUT → 树莓派 GPIO17

蜂鸣器 VCC → 树莓派 5V

蜂鸣器 GND → 树莓派 GND

蜂鸣器 IN → 树莓派 GPIO18

LED指示灯 正极 → 树莓派 GPIO23

LED指示灯 负极 → 220Ω电阻 → GND

LED显示屏 RX → 树莓派 TX (GPIO14)

LED显示屏 GND → 树莓派 GND

## 软件依赖

bash

pip install RPi.GPIO pyserial

## 安装与使用

### 1. 克隆仓库

bash

git clone "https://github.com/yourusername/smart-access-control.git" (https://github.com/yourusername/smart-access-control.git)

cd smart-access-control

### 2. 配置修改

根据实际接线修改 `config.py` 中的GPIO引脚定义

### 3. 运行程序

bash

sudo python3 main.py

## 日志查看

事件日志保存在 `access_events.log`,可通过以下命令查看:

bash

tail -f access_events.log

## 注意事项

1. 必须使用`sudo`运行以获取GPIO访问权限

2. 首次运行前确保传感器处于稳定环境(预热30秒)

3. 如需修改停留阈值,编辑`config.py`中的`STAY_THRESHOLD`

## 贡献指南

欢迎提交Issue和Pull Request,请遵循PEP8编码规范。

## 许可证

MIT License

六、核心知识点卡片

卡片1:GPIO输入模式配置

GPIO.setmode(GPIO.BCM) # 使用BCM引脚编号(而非物理引脚)

GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) # 上拉电阻配置

关键点:HC-SR501传感器输出低电平表示检测到人体,因此需配置上拉电阻使默认状态为高电平。

卡片2:防误触采样算法

def is_person_present(self):

confirm_count = 0

for _ in range(CONFIRM_SAMPLES): # 连续3次采样

if self.read_raw():

confirm_count += 1

else:

confirm_count = 0 # 失败则重置

time.sleep(SAMPLE_INTERVAL) # 200ms间隔

return confirm_count >= CONFIRM_SAMPLES

作用:消除环境干扰(如宠物、飘动物体)导致的误判,提高系统可靠性。

卡片3:状态机设计模式

STATE_IDLE = "IDLE"

STATE_DETECTED = "DETECTED"

STATE_TIMING = "TIMING"

STATE_ALERT = "ALERT"

# 根据条件转换状态

if self.current_state == self.STATE_IDLE:

if person_detected:

self.current_state = self.STATE_DETECTED

优势:将复杂逻辑分解为离散状态,使代码更易维护和理解,避免深层嵌套if-else。

卡片4:单调时钟计时

import time

start = time.monotonic() # 单调递增时钟

# ... 执行操作 ...

elapsed = time.monotonic() - start # 精确计时

区别:

"time.time()"受系统时间调整影响,

"time.monotonic()"保证单调递增,适合精确计时场景。

卡片5:优雅的资源管理

def shutdown(self):

if self.alert_active:

self.notifier.stop_alert()

self.sensor.cleanup() # 清理GPIO

self.notifier.cleanup() # 关闭串口

重要性:确保程序异常退出时仍能正确释放硬件资源,避免GPIO锁死或串口占用。

七、总结

本系统通过红外传感+状态机+声光报警的组合,实现了智能门禁的异常停留检测功能,核心价值在于:

1. 安全性提升:10秒阈值可配置,及时预警潜在安全风险

2. 管理效率优化:自动化检测减少人工监控成本

3. 可扩展性:模块化设计便于添加人脸识别、手机APP通知等功能

4. 可靠性保障:防误触机制+资源清理确保系统稳定运行

技术亮点:

- 采用状态机模式管理复杂流程

- 使用单调时钟保证计时精度

- 实现完整的资源生命周期管理

- 模块化设计支持功能扩展

未来优化方向:

- 增加WiFi模块实现远程通知

- 添加数据库存储历史数据

- 集成机器学习算法识别行为模式

- 开发Web管理界面

本方案不仅适用于小区门禁,还可扩展至银行、实验室等需要人员管控的场所,具有广泛的应用前景。

利用AI解决实际问题,如果你觉得这个工具好用,欢迎关注长安牧笛!

http://www.jsqmd.com/news/517475/

相关文章:

  • 手把手教你用Python+Django打造免费的城市定位API(附完整代码)
  • Flutter桌面端开发避坑指南:Visual Studio 2022兼容性问题全解析(附CMake解决方案)
  • 手把手教你用Simulink搭建IEEE5节点潮流仿真模型(附MATLAB源码)
  • i.MX6ULL的FEC驱动避坑指南:为什么uboot网络正常而Linux下eth1总‘Link is down’?
  • 树莓派硬件接口全解析:从GPIO到高速总线的实战指南
  • Ubuntu 20.04外接硬盘挂载失败?一招解决ntfs-3g Device or resource busy报错
  • PCB设计全流程检查清单:从输入验证到文件归档
  • 2026年AI Agent爆发:从“会聊天“到“能办事“,抓住这波红利,你还在等什么?
  • 老旧服务器跑不动MongoDB 5.0?三招教你低成本解决AVX兼容问题
  • 深入解析STM32F407通过FSMC与DMA高效访问外部SRAM的配置技巧
  • 从固件升级到模式切换:一次完整的Mellanox ConnectX-3网卡性能调优实录
  • EmbeddingGemma-300m多GPU并行推理配置教程
  • 避坑指南:PyQt5播放视频时QTimer卡顿、图像拉伸?手把手教你优化显示效果
  • C语言经典算法解析---例003--- 完全平方数的数学之美
  • 编写程序实现智能耳机佩戴检测,摘下耳机自动暂停播放,戴上继续播放,省电便捷。
  • HTTPS业务系统下,通过Nginx反向代理实现H5Player播放海康HTTP视频流的WebSocket配置全解
  • LangGraph:大模型智能体编排的图计算革命
  • 跨平台串口通信实战:VMware虚拟机与Windows主机的无缝对接
  • 手把手教你获取HC6800-EM3 V30原理图:全网最全资源汇总
  • 从握手信号到数据计数:拆解Xilinx FIFO的跨时钟域‘安全墙’是如何筑成的
  • C语言直驱存内计算单元的5层抽象设计(含LLVM IR级插桩代码):某TOP3自动驾驶厂商已落地验证
  • 文墨共鸣在企业内部知识库的应用:智能问答与文档摘要
  • 模糊PID控制PMSM仿真:探索高效电机驱动之路
  • Qt与QCustomPlot实战:打造高效实时波形可视化工具
  • Python 3.12 MagicMethods - 78 - __getattribute__
  • iPerf3实战:如何用-M参数优化TCP吞吐量(附真实网络测试数据)
  • C++实战:如何用max_element和min_element简化你的代码(附完整示例)
  • 【高效科研】Overleaf与LaTeX入门:从零开始打造学术论文
  • 微电网逆变器孤岛下垂控制:打造完美波形输出
  • 告别肤色检测!用OpenPose手部关键点实现更鲁棒的手势识别(Python+OpenCV保姆级教程)