星期一, 20 4月 2026 11:24

居家养老跌倒报警系统 - 家庭完整开源实现方案

开源、家庭部署、服务器端处理报警,两套成熟的开源方案参考。

 

 

一、方案对比与选择

对比维度 方案一:AI摄像头视觉方案 方案二:可穿戴蓝牙方案
核心原理 摄像头画面+AI识别摔倒姿态 手表加速度计+机器学习判断跌倒
老人需佩戴 ❌ 不需要 ✅ 需要戴手表
隐私影响 有摄像头,部分老人介意 无摄像头,隐私友好
安装复杂度 中等(固定摄像头) 低(手表+网关即用)
成本预估 约800-1500元 约400-800元
适合场景 客厅、走廊等公共区域 全屋活动,尤其适合独居老人
误报率 较低(视觉确认姿态) 中等(动作特征)

建议:如果你和老人都不介意摄像头,选方案一,识别最准;如果老人介意被“看着”或者需要全屋覆盖,选方案二。下面重点展开方案二(关注蓝牙手表方案),更符合“服务器端处理报警”的预期。

二、方案二:蓝牙可穿戴跌倒报警(完整开源实现)

这套方案来自 Edge Impulse 官方的开源项目,完整的客户端+服务器代码都公开在 GitHub 上。

2.1 系统架构图

┌─────────────────────────────────────────────────────────────┐
│ 老人端(佩戴) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Arduino Nano 33 BLE Sense(手表形态) │ │
│ │ ├── 6轴加速度计(LSM9DS1)采集运动数据 │ │
│ │ ├── Edge Impulse ML模型(本地判断跌倒) │ │
│ │ ├── RGB LED(绿灯正常/红灯报警) │ │
│ │ └── 低功耗蓝牙(BLE)广播报警 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ 蓝牙广播 │
│ "Fall-张三-1922" │
└──────────────────────────────│──────────────────────────────┘


┌─────────────────────────────────────────────────────────────┐
│ 家庭网关(Raspberry Pi) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Python 扫描脚本 │ │
│ │ ├── 持续监听蓝牙广播 │ │
│ │ ├── 解析跌倒报警信息 │ │
│ │ ├── 存入 SQLite 数据库 │ │
│ │ └── 触发多渠道推送 │ │
│ └─────────────────────────────────────────────────────┘ │
└──────────────────────────────│──────────────────────────────┘

┌────────────────────┼────────────────────┐
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ 微信通知 │ │ 短信通知 │ │ Web仪表板 │
│(企业微信)│ │(需SIM卡)│ │(本地查看)│
└───────────┘ └───────────┘ └───────────┘

 

2.2 硬件采购清单

组件 型号/规格 数量 参考价格 用途
可穿戴端        
主控板 Arduino Nano 33 BLE Sense 1块 ¥280-350 核心:自带加速度计+蓝牙
电池 3.7V 300mAh 锂电池 1个 ¥20-30 供电
充电模块 TP4056 1个 ¥5-10 锂电池充电管理
表带/外壳 3D打印或通用表带 1套 ¥30-50 固定成手表形态
网关端        
网关 Raspberry Pi 3B/4B(或Zero 2W) 1台 ¥300-500 蓝牙扫描+服务器
存储 MicroSD 16GB 1张 ¥30 系统盘+数据库
电源 5V/2.5A USB电源 1个 ¥20-30 供电
可选        
通知模块 4G USB上网卡 1个 ¥80-120 网关联网(如有WiFi则不需要)

总成本估算:约 ¥400-800(不含3D打印外壳)

2.3 软件架构详解

这套方案的核心是 “本地判断+蓝牙传输+服务器存储” 的分工架构:

层级 设备 做什么 为什么放这里
感知层 Arduino手表 采集加速度数据、跑ML模型判断跌倒 本地判断省电、隐私
传输层 Arduino手表 跌倒后通过BLE广播报警信息 蓝牙功耗低
汇聚层 Raspberry Pi 扫描蓝牙广播、接收报警 7x24小时在线
存储层 Raspberry Pi SQLite数据库记录报警日志 本地存储、可回溯
通知层 Raspberry Pi 触发微信/短信/本地告警 服务器端统一管理

2.4 第一步:训练跌倒检测模型(Edge Impulse)

Edge Impulse 是一个免费的在线机器学习平台,不需要写训练代码,通过网页就能训练一个跌倒检测模型。

操作步骤

  1. 注册账号:访问 studio.edgeimpulse.com 注册免费账号
  2. 创建项目:点击 “Create new project”,命名为 Fall Detection
  3. 连接设备采集数据
    • 将 Arduino Nano 33 BLE Sense 通过 USB 连接电脑
    • 在 Edge Impulse 的 “Data acquisition” 页面,选择 “WebUSB”
    • 点击 “Connect”,选择你的 Arduino 设备
    • 设置标签,分别采集两类数据:
      • 标签 stand:正常站立、行走(采集2-3分钟)
      • 标签 fall:模拟摔倒动作(采集2-3分钟)
    • 点击 “Start sampling” 开始采集
  4. 设计Impulse(机器学习流水线)
    • 点击 “Impulse design” → “Add a processing block” → 选择 Spectral Analysis
    • 参数设置:Window size = 1500ms,Window increase = 150ms,Frequency = 100Hz
    • 勾选 3个轴:accX、accY、accZ
    • “Add a learning block” → 选择 Keras Classification
    • 输出类别:2个(Stand 和 Fall)
  5. 训练模型
    • 点击 “Classifier” 进入训练页面
    • 参数设置:Training cycles = 50,Learning rate = 0.0005
    • 勾选 “Autobalance dataset” 和 “20% validation”
    • 点击 “Start training”
    • 训练完成后查看准确率,通常可达 90%以上
  6. 导出Arduino库
    • 点击 “Deployment” 页面
    • 选择 “Arduino library”
    • 点击 “Build”,下载生成的 .zip 文件

2.5 第二步:编写手表端程序(Arduino IDE)

环境准备

  • 下载安装 Arduino IDE
  • 在IDE中安装 “Arduino Mbed OS Nano Boards” 开发板支持包
  • 安装 “ArduinoBLE” 库(通过库管理器)

完整代码(基于 Edge Impulse 官方示例修改):

#include <ArduinoBLE.h>
#include <Arduino_LSM9DS1.h>
#include "Fall_Detection_inferencing.h" // Edge Impulse导出的模型

// 常量定义
const int LED_GREEN = LED_BUILTIN;
const int LED_RED = LED_RED;
const float FALL_THRESHOLD = 0.8; // 跌倒置信度阈值

// 全局变量
int fallCounter = 0;
unsigned long lastFallTime = 0;
const unsigned long FALL_COOLDOWN = 30000; // 30秒防重复报警

// 跌倒检测回调函数
void onFallDetected() {
unsigned long now = millis();

// 防重复报警:30秒内不重复触发
if (now - lastFallTime < FALL_COOLDOWN) {
return;
}

lastFallTime = now;
fallCounter++;

// 红灯闪烁3次,提示报警已触发
for (int i = 0; i < 3; i++) {
digitalWrite(LED_RED, HIGH);
delay(200);
digitalWrite(LED_RED, LOW);
delay(100);
}

// 构造报警信息并广播
String workerId = "Grandpa"; // 可改为老人姓名
String fallMsg = "Fall-" + workerId + "-" + String(fallCounter);

BLEAdvertisementData advertisementData;
advertisementData.setLocalName(fallMsg.c_str());
BLE.setAdvertisingData(advertisementData);
BLE.advertise();

// 广播持续3秒后恢复
delay(3000);
BLE.stopAdvertise();

// 恢复绿灯常亮表示正常
digitalWrite(LED_GREEN, HIGH);
digitalWrite(LED_RED, LOW);
}

void setup() {
Serial.begin(115200);

// 初始化LED
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_RED, OUTPUT);
digitalWrite(LED_GREEN, HIGH);

// 初始化IMU传感器
if (!IMU.begin()) {
Serial.println("Failed to initialize IMU!");
while (1);
}

// 初始化BLE
if (!BLE.begin()) {
Serial.println("Failed to initialize BLE!");
while (1);
}

BLE.setDeviceName("FallDetector");
BLE.setLocalName("FallDetector");
BLE.advertise();

Serial.println("Fall Detection System Ready");
}

void loop() {
// 采集加速度数据
float accX, accY, accZ;
if (IMU.accelerationAvailable()) {
IMU.readAcceleration(accX, accY, accZ);

// 构建特征向量(Edge Impulse模型需要的格式)
float features[3] = {accX, accY, accZ};

// 运行推理
EI_IMPULSE_ERROR res = run_classifier(features, 3, false);

if (res != EI_IMPULSE_OK) {
return;
}

// 获取跌倒的置信度
float fallConfidence = result.classification[1].value; // Fall类别

// 如果置信度超过阈值,触发报警
if (fallConfidence > FALL_THRESHOLD) {
onFallDetected();
}
}

delay(50); // 20Hz采样频率
}

2.6 第三步:部署网关端服务器(Raspberry Pi)

网关需要持续扫描蓝牙广播,接收跌倒报警信息,存储到数据库,并发送通知。

步骤1:烧录Raspberry Pi系统

  • 下载 Raspberry Pi OS Lite
  • 使用 Raspberry Pi Imager 烧录到 MicroSD 卡
  • 启动 Pi,通过 ssh pi@raspberrypi 连接(默认密码 raspberry)

步骤2:安装依赖

# 更新系统
sudo apt update && sudo apt upgrade -y

# 安装Python和蓝牙工具
sudo apt install python3-pip bluez bluez-tools -y

# 安装Python库
pip3 install bluepy sqlite3 requests

步骤3:创建数据库结构

# 创建项目目录
mkdir ~/fall-detection
cd ~/fall-detection

# 创建数据库设置脚本
nano databaseSetup.py

databaseSetup.py 内容

import sqlite3

conn = sqlite3.connect('fall_events.db')
cursor = conn.cursor()

cursor.execute('''
CREATE TABLE IF NOT EXISTS fall_events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
worker_id TEXT,
event_counter INTEGER,
status TEXT DEFAULT 'pending'
)
''')

conn.commit()
conn.close()
print("Database created successfully!")

步骤4:蓝牙扫描脚本

nano scan.py

scan.py 完整内容

import bluetooth
import sqlite3
import time
import requests
from datetime import datetime

# 配置
FALL_DEVICE_PREFIX = "Fall-"
NOTIFICATION_WEBHOOK = "https://your-server.com/webhook" # 可改为微信/钉钉webhook

def send_alert(worker_id, event_time):
"""发送报警通知"""
message = f"⚠️ 跌倒报警!\n老人:{worker_id}\n时间:{event_time}\n请立即查看!"

# 方式1:通过webhook发送到企业微信/钉钉
try:
payload = {"msgtype": "text", "text": {"content": message}}
requests.post(NOTIFICATION_WEBHOOK, json=payload, timeout=5)
except:
pass

# 方式2:打印到控制台(调试用)
print(f"\n{'='*40}\n{message}\n{'='*40}\n")

def save_to_db(worker_id, counter):
"""保存跌倒事件到数据库"""
conn = sqlite3.connect('fall_events.db')
cursor = conn.cursor()
cursor.execute(
"INSERT INTO fall_events (worker_id, event_counter, status) VALUES (?, ?, ?)",
(worker_id, counter, 'pending')
)
conn.commit()
conn.close()
print(f"[DB] Saved: {worker_id} - Counter: {counter}")

def scan_bluetooth():
"""持续扫描蓝牙设备"""
print("Starting Bluetooth scan for fall detection...")

# 用于记录已处理的设备,防止重复报警
processed_devices = {}

while True:
try:
# 扫描蓝牙设备(持续8秒)
devices = bluetooth.discover_devices(
duration=8,
lookup_names=True,
flush_cache=True
)

for addr, name in devices:
if name and name.startswith(FALL_DEVICE_PREFIX):
# 解析设备名称:格式 "Fall-{worker_id}-{counter}"
parts = name.split('-')
if len(parts) >= 3:
worker_id = parts[1]
counter = parts[2]

# 去重:同一个counter只处理一次
device_key = f"{addr}_{counter}"
if device_key in processed_devices:
continue

processed_devices[device_key] = time.time()

# 记录事件
event_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"[ALERT] Fall detected! {worker_id} at {event_time}")

# 保存到数据库
save_to_db(worker_id, counter)

# 发送通知
send_alert(worker_id, event_time)

# 清理超过1小时的缓存记录
current_time = time.time()
to_remove = [k for k, t in processed_devices.items()
if current_time - t > 3600]
for k in to_remove:
del processed_devices[k]

except Exception as e:
print(f"Scan error: {e}")
time.sleep(5)

if __name__ == "__main__":
scan_bluetooth()

步骤5:启动服务

# 初始化数据库
sudo python3 databaseSetup.py

# 启动扫描(建议使用screen或systemd保持后台运行)
sudo python3 scan.py

使用 systemd 开机自启(可选):

# 创建服务文件
sudo nano /etc/systemd/system/fall-detection.service

内容:

[Unit]
Description=Fall Detection Scanner
After=bluetooth.service

[Service]
ExecStart=/usr/bin/python3 /home/pi/fall-detection/scan.py
Restart=always
User=pi

[Install]
WantedBy=multi-user.target

# 启用服务
sudo systemctl enable fall-detection
sudo systemctl start fall-detection
sudo systemctl status fall-detection # 查看运行状态

2.7 第四步:Web仪表板(可选)

如果想在本地查看跌倒记录和统计,可以添加一个简单的 Flask Web 界面。

# 安装Flask
pip3 install flask

# 创建Web应用
nano web_dashboard.py

web_dashboard.py

from flask import Flask, render_template_string, jsonify
import sqlite3
from datetime import datetime, timedelta

app = Flask(__name__)

HTML_TEMPLATE = '''
<!DOCTYPE html>
<html>
<head>
<title>跌倒报警监控系统</title>
<meta http-equiv="refresh" content="10">
<style>
body { font-family: Arial; padding: 20px; }
.alert { background: #ff4444; color: white; padding: 15px; margin: 10px 0; border-radius: 5px; }
.normal { background: #4CAF50; padding: 10px; color: white; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
</style>
</head>
<body>
<h1>? 居家跌倒报警系统</h1>
<div class="normal">✅ 系统运行中 | 最后更新: {{ now }}</div>

<h2>? 最近报警记录</h2>
<table>
<tr><th>时间</th><th>老人</th><th>状态</th></tr>
{% for event in events %}
<tr class="{% if event.status == 'pending' %}alert-row{% endif %}">
<td>{{ event.timestamp }}</td>
<td>{{ event.worker_id }}</td>
<td>⚠️ 待处理</td>
</tr>
{% else %}
<tr><td colspan="3">暂无报警记录 ✅</td></tr>
{% endfor %}
</table>

<h2>? 统计</h2>
<p>今日报警: {{ today_count }} 次 | 累计报警: {{ total_count }} 次</p>
</body>
</html>
'''

@app.route('/')
def dashboard():
conn = sqlite3.connect('fall_events.db')
cursor = conn.cursor()

# 获取最近20条记录
cursor.execute("SELECT timestamp, worker_id, status FROM fall_events ORDER BY timestamp DESC LIMIT 20")
events = [{'timestamp': row[0], 'worker_id': row[1], 'status': row[2]} for row in cursor.fetchall()]

# 统计今日
today = datetime.now().strftime('%Y-%m-%d')
cursor.execute("SELECT COUNT(*) FROM fall_events WHERE date(timestamp) = ?", (today,))
today_count = cursor.fetchone()[0]

# 统计总数
cursor.execute("SELECT COUNT(*) FROM fall_events")
total_count = cursor.fetchone()[0]

conn.close()

return render_template_string(HTML_TEMPLATE,
events=events,
today_count=today_count,
total_count=total_count,
now=datetime.now().strftime('%Y-%m-%d %H:%M:%S'))

if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)

启动Web仪表板:

python3 web_dashboard.py

然后在家庭局域网内访问 http://树莓派IP:5000 即可查看。

三、方案一备选:AI摄像头视觉方案(隐私不敏感时选用)

如果你不介意摄像头,这套基于 YOLOv8 的视觉方案识别精度更高。

硬件需求

  • 普通电脑 或 NVIDIA Jetson 边缘设备
  • USB摄像头(或RTSP网络摄像头)

快速部署步骤

# 1. 克隆项目
git clone https://github.com/ultralytics/ultralytics.git
cd ultralytics

# 2. 安装依赖
pip install ultralytics opencv-python torch

# 3. 运行跌倒检测(使用预训练模型)
python -c "
from ultralytics import YOLO
import cv2

model = YOLO('yolov8n-pose.pt')
cap = cv2.VideoCapture(0)

while True:
ret, frame = cap.read()
results = model(frame, stream=True)
for r in results:
# 姿态检测 + 摔倒判断逻辑
annotated_frame = r.plot()
cv2.imshow('Fall Detection', annotated_frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
"

如果需要完整的训练代码+数据集+UI界面,可以参考这个开源项目:阿里云开发者社区的人体跌倒识别项目,包含完整的YOLOv8训练代码和PyQt5界面。

四、常见问题与优化建议

4.1 误报问题

误报原因 解决方案
快速坐下被误判 增加静止时间判断(需保持低姿态>2秒)
弯腰捡东西 结合陀螺仪角度变化,过滤垂直方向速度不高的动作
扔抱枕等物体 只检测佩戴者自身的加速度变化

可以在 onFallDetected() 函数中加入 防误报逻辑:检测到冲击后,等待3秒再判断是否真的无法起身。

4.2 续航优化

Arduino Nano 33 BLE Sense 默认功耗约30mA,300mAh电池理论续航10小时。优化方法:

  • 降低采样频率(从100Hz降到50Hz)
  • 使用深度睡眠模式,每100ms唤醒一次检测
  • 优化后可达24-48小时

4.3 扩展功能建议

  1. 一键SOS按钮:长按手表上的按钮3秒主动报警
  2. 心率监测:MAX30102传感器可集成到手表,监测心率异常
  3. 多老人管理:数据库支持多设备ID,区分不同老人
  4. 位置追踪:增加蓝牙RSSI测距或UWB定位,知道老人在哪个房间跌倒

五、完整资源清单

资源类型 链接/获取方式
Edge Impulse教程 https://docs.edgeimpulse.com/projects/expert-network/bluetooth-fall-detection-arduino-nano-33
完整GitHub代码 项目内包含客户端+服务器完整代码
Arduino Nano购买 淘宝/立创商城 ¥280-350
Raspberry Pi购买 树莓派官方授权店 ¥300-500
YOLOv8视觉方案 https://github.com/ultralytics/ultralytics

下一步建议:如果想先快速验证可行性,可以按这个顺序:

  1. 买一块 Arduino Nano 33 BLE Sense(约300元)
  2. 用 Edge Impulse 免费训练模型(1小时内完成)
  3. 烧录代码,手动模拟摔倒测试
  4. 确认可行后再配 Raspberry Pi 和外壳
查看 10055
 

瑞驰车友会微信公众号

qrcode for gh 673928177533 258

Please support our site by viewing this advertisement.

Please support our site by viewing this advertisement

Free Content