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

 

一、方案对比与选择

对比维度 方案一: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 和外壳

登陆