适用于2026电赛C题的解决方案,因为一些原因今年电赛失利,但还是决定将项目开源出来,希望能帮到大家
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 |
星闪数字钥匙智能门锁系统
基于 BearPi-Pico H3863 的星闪(SLE)身份识别 + UWB 多锚点定位 + 智能门锁控制 本文档由AI辅助生成
一、项目背景
本项目为电赛 C 题方案,要求实现一套数字钥匙系统:钥匙端广播身份 ID,门锁端识别 ID 并通过测距判断钥匙位置,在授权范围内自动解锁。
核心挑战:
- 身份识别:需要低功耗、低延迟的无线通信方案
- 精准测距:需要厘米级定位精度判断钥匙是否在解锁范围内
- 实时响应:进入/离开区域需即时反馈(LED + 蜂鸣器 + OLED)
二、系统方案
2.1 整体架构
星闪 SLE 通信
┌────────────┐ ID 广播 + Notify ┌─────────────────────┐
│ │ ◄──────────────────────► │ │
│ 钥匙 KEY │ UUID: 0x2828/0x2929 │ 门锁 LOCK │
│ (H3863) │ │ (H3863) │
│ │ │ │
│ · DIP 设ID │ │ ┌─── SLE Client │
│ · SLE广播 │ │ ├── UART×2 测距 │
│ · ID Notify│ │ ├── OLED 显示 │
└────────────┘ │ ├── LED×3 指示 │
│ ├── 蜂鸣器提示 │
│ └── DIP 校验ID │
└─────────────────────┘
▲ ▲
UART1 │ │ UART2
115200bps │ │
▼ ▼
┌──────────┐ ┌──────────┐
│ 锚点 E │ │ 锚点 G │
│ 锚点 F │ │ 锚点 H │
│ STM32 + │ │ STM32 + │
│ DW1000 │ │ DW1000 │
└──────────┘ └──────────┘
2.2 技术选型
| 模块 | 方案 | 选型理由 |
|---|---|---|
| 主控芯片 | Hi3863 (RISC-V 240MHz) | 集成 Wi-Fi6/BLE/SLE,原生支持星闪 |
| 近距通信 | 星闪 SLE (SparkLink Edge) | 低延迟、低功耗,原生 SSAP 协议栈 |
| 测距定位 | UWB DW1000 + STM32 | 厘米级精度,4 锚点定位 |
| 数据回传 | UART 双串口 | 简单可靠,双通道并行接收 |
| 显示 | SSD1306 0.96" OLED | 软件 I2C,低功耗,信息密度高 |
2.3 工作流程
[钥匙端]
上电 → SLE 初始化 → 广播 "diansai2_key" → 等待连接
→ 配对成功 → 每 500ms Notify 发送 ID (0x0A)
[门锁端]
上电 → OLED 显示 "Scanning..." → SLE 扫描
→ 发现钥匙 → 连接 → 配对 → 服务发现
→ 接收 ID → 与 DIP 开关期望 ID 比对
[并行] UART 接收 4 锚点测距数据
→ 卡尔曼滤波 → 野值剔除
→ 计算径向距离 + 方位角
→ 判断区域 (感知/欢迎/解锁)
[综合判断]
ID 匹配 + 距离 < 1m → 解锁 (绿灯 + 蜂鸣)
ID 匹配 + 距离 < 2m → 欢迎 (黄灯 + 蜂鸣)
其他 → 锁定 (红灯)
三、硬件设计
3.1 器件清单
| 器件 | 型号 | 数量 | 角色 |
|---|---|---|---|
| 主控板 | BearPi-Pico H3863 | 2 | 钥匙 + 门锁 |
| UWB 模块 | DW1000 + STM32 | 4 | 测距锚点 E/F/G/H |
| 显示屏 | SSD1306 0.96" OLED | 1 | 门锁状态显示 |
| LED | 红/绿/黄 | 3 | 锁定/解锁/欢迎指示 |
| 蜂鸣器 | 有源蜂鸣器 | 1 | 进出区域提示 |
| 拨码开关 | 4 位 DIP | 2 | ID 设置 (钥匙/门锁各一) |
3.2 门锁端接线
BearPi-Pico H3863 (LOCK)
┌─────────────────────┐
GPIO 4 ────────►│ LED Red (锁定) │
GPIO 5 ────────►│ LED Green (解锁) │
GPIO 14 ────────►│ LED Yellow(欢迎) │
GPIO 6 ────────►│ Buzzer │
GPIO 13 ───┬────►│ OLED SCL (软件I2C) │
GPIO 12 ───┤ │ │
└────►│ OLED SDA │
GPIO 9~3 ──────►│ DIP Switch ×4 │
GPIO 15 ────────►│ UART1 TX → 锚点E/F │
GPIO 16 ────────►│ UART1 RX ← 锚点E/F │
GPIO 8 ────────►│ UART2 TX → 锚点G/H │
GPIO 7 ────────►│ UART2 RX ← 锚点G/H │
└─────────────────────┘
四、软件设计
4.1 任务架构
门锁端运行两个并行 RTOS 任务:
┌─────────────────────────────────────────────┐
│ LiteOS (liteos_v208) │
├─────────────────────────────────────────────┤
│ │
│ ┌─ Diansai2Lock (优先级 17) ──────────┐ │
│ │ · SLE Client 扫描/连接/配对 │ │
│ │ · 接收 ID + DIP 校验 │ │
│ │ · OLED 刷新 (200ms) │ │
│ │ · LED/蜂鸣器控制 │ │
│ │ · 区域判断 + 状态机 │ │
│ └────────────────────────────────────┘ │
│ │
│ ┌─ Diansai2LockDist (优先级 15) ──────┐ │
│ │ · UART1 接收锚点 E/F (115200) │ │
│ │ · UART2 接收锚点 G/H (115200) │ │
│ │ · 解析 "X D:距离" 协议 │ │
│ │ · 卡尔曼滤波 (每锚点独立) │ │
│ │ · 野值剔除 │ │
│ │ · 径向距离 + 方位角计算 │ │
│ │ · 更新全局距离/角度变量 │ │
│ └────────────────────────────────────┘ │
│ │
│ 栈大小: Lock 8KB / Dist 4KB │
└─────────────────────────────────────────────┘
4.2 SLE 通信流程
钥匙端 (Server) 门锁端 (Client)
│ │
│ ◄── 广播 "diansai2_key" ────── │ 扫描
│ │ 发现目标
│ ◄── 连接请求 ────────────────── │
│ ── 连接成功 ─────────────────► │
│ │
│ ◄── 配对请求 ────────────────── │
│ ── 配对完成 ─────────────────► │
│ │
│ ◄── MTU 交换 (520) ──────────── │
│ ── MTU 确认 ─────────────────► │
│ │
│ ◄── 服务发现 ────────────────── │
│ ── Property Handle ──────────► │
│ │
│ ── Notify ID (0x0A) ─────────► │ 每 500ms
│ ── Notify ID ────────────────► │
│ ── Notify ID ────────────────► │
│ ... │
SLE 参数:
- Service UUID:
0x2828 - Property UUID:
0x2929 - 广播间隔: 200ms (
0xC8) - 连接间隔: 100ms (
0x64) - MTU: 520 bytes
- ID 发送间隔: 500ms
4.3 OLED 显示界面
扫描中:
┌──────────────────┐
│ SLE: Scanning... │
│ │
│ Exp: b0000 │
│ │
│ Key ID: ---- │
│ Zone: ---- │
└──────────────────┘
已连接:
┌──────────────────┐
│ Key:b1010 Exp:b0000│ ← 接收ID / 期望ID
│ Ver: PASS │ ← ID 校验结果
│ Dist:1.23m A:+4.5 │ ← 距离 / 角度
│ Zone: WELCOME │ ← 当前区域
│ Event: Enter Welc │ ← 区域事件
│ Hrz:1.53m │ ← 水平距离
│ Status: WELCOME │ ← 门锁状态
└──────────────────┘
五、核心算法
5.1 UWB 多锚点定位
5.1.1 数据采集
4 个 STM32+DW1000 锚点各自测距,通过 UART 上报:
E D:0.56 ← 锚点E,距离 0.56m
F D:1.23 ← 锚点F,距离 1.23m
G D:0.89 ← 锚点G,距离 0.89m
H D:2.34 ← 锚点H,距离 2.34m
门锁端双 UART 并行接收:
- UART1 (GPIO 15/16): 锚点 E、F
- UART2 (GPIO 8/7): 锚点 G、H
5.1.2 卡尔曼滤波
每个锚点独立维护一个卡尔曼滤波器,平滑测距噪声:
预测:
p_pred = p_est + Q (Q = 0.05)
更新:
K = p_pred / (p_pred + R) (R = 0.1)
x_est = x_est + K × (测量值 - x_est)
p_est = (1 - K) × p_pred
5.1.3 野值剔除
当测量值与估计值偏差超过阈值时,拒绝该次测量:
if |测量值 - 估计值| > 50cm:
使用估计值替代,连续拒绝计数 +1
if 连续拒绝 > 5 次:
接受新测量值(强制重置)
else:
正常卡尔曼更新,重置计数器
5.1.4 位置解算
基于 4 锚点距离差分计算坐标和方位角:
锚点布局 (间距 L = 60cm):
E ─────── G
│ │
F ─────── H
坐标计算:
x = (d_G² - d_E²) / (2L) (L = 60, 2L = 120)
y = (d_H² - d_F²) / (2L)
径向距离:
avg = (d_E + d_F + d_G + d_H) / 4
r = (avg - 61.0) / 1.105 (零偏 + 缩放校准)
r_edge = r - 30.0 (边缘补偿)
方位角:
angle = -atan2(y, x) × (180/π) - 125°
(−125° 为锚点布局偏移,需根据实际安装标定)
角度平滑:
angle_smooth += 0.3 × (angle - angle_smooth)
(处理 360° 环绕)
5.2 区域状态机
距离 < 1m
┌──────────┐ ─────────────► ┌──────────┐
│ SENSING │ │ UNLOCK │
│ (红灯) │ ◄───────────── │ (绿灯) │
└──────────┘ 距离 >= 1m └──────────┘
│ │
│ 距离 < 2m │ 距离 >= 1m
▼ ▼
┌──────────┐ ┌──────────┐
│ WELCOME │ ──────────────►│ WELCOME │
│ (黄灯) │ 距离 < 2m │ (黄灯) │
└──────────┘ ◄──────────────└──────────┘
距离 >= 2m
蜂鸣器事件:
- 进入解锁区:短响 100ms
- 离开解锁区:短响 100ms
- 进入欢迎区:长响 200ms
- 离开欢迎区:长响 200ms
5.3 ID 验证
钥匙端:
KEY_ID = 0x0A (固定)
→ 每 500ms 通过 SLE Notify 发送
门锁端:
g_expected_id = DIP 开关读取 (4-bit)
g_received_id = SLE Notify 接收
if g_received_id == g_expected_id:
验证通过 (PASS) → 允许解锁
else:
验证失败 (FAIL) → 保持锁定
六、代码结构
diansai2/
├── README.md # 项目文档
├── LICENSE # CC BY-NC-SA 4.0
├── CMakeLists.txt # 构建配置 (KEY/LOCK 二选一)
├── Kconfig # 引脚可配置项
│
├── diansai2.h # 公共定义
│ # SLE UUID / 任务参数 / 区域阈值
│
├── diansai2_key.c # 钥匙端 (347 行)
│ # SLE Server / 广播 / 配对 / ID Notify
│
├── diansai2_lock.c # 门锁端 (716 行) -- 核心
│ # SLE Client / UART 测距接收
│ # 卡尔曼滤波 / 野值剔除
│ # 位置解算 / 方位角
│ # OLED 显示 / LED / 蜂鸣器
│ # 区域状态机 / ID 验证
│
├── diansai2_oled.c/.h # SSD1306 软件 I2C 驱动 (153 行)
├── diansai2_oled_font.h # 6x8 点阵字库 (95 字符)
七、创新点
-
星闪 SLE 通信:使用新一代短距通信技术 SparkLink Edge 替代传统 BLE,原生 SSAP 协议栈实现身份广播与通知,低延迟低功耗
-
4 锚点 UWB 定位:4 个 STM32+DW1000 锚点分布式测距,双 UART 并行接收,通过差分平方算法解算 2D 坐标和方位角
-
多级滤波融合:
- 每锚点独立卡尔曼滤波器平滑测距噪声
- 自适应野值剔除机制防止异常跳变
- 径向距离二次卡尔曼滤波
- 角度指数平滑(含 360° 环绕处理)
-
三级区域状态机:感知 → 欢迎 → 解锁,带事件驱动的蜂鸣器提示和 LED 状态指示
-
全引脚可配置:所有外设引脚通过 Kconfig 配置,适应不同硬件布局
八、校准说明
首次使用需根据实际环境校准以下参数(位于 diansai2_lock.c):
| 参数 | 默认值 | 校准方法 |
|---|---|---|
AVG_OFFSET_CM |
61.0 | 在已知距离处测量 avg 值,计算零偏 |
AVG_SCALE |
1.105 | 多点采样,线性拟合斜率 |
角度偏移 -125° |
-125 | 锚点正前方放置钥匙,记录角度偏差 |
锚点间距 /120.0f |
120 (60cm×2) | 修改为实际间距 ×2 |
九、许可证
CC BY-NC-SA 4.0 (署名-非商业性使用-相同方式共享 4.0 国际)
- 允许学习、研究、修改、分享
- 禁止任何形式的商业使用
- 衍生作品须采用相同许可证
详见 LICENSE 或 https://creativecommons.org/licenses/by-nc-sa/4.0/
十、致谢
- BearPi-Pico H3863 SDK -- 海思 Hi3863 开发板及 SDK
- LiteOS -- 华为轻量级实时操作系统
- Decawave DW1000 -- UWB 测距芯片 (锚点端,本仓库不含其驱动代码)