电赛C题:我用星闪+UWB做了一个数字钥匙门锁系统,开源了
电赛C题我用星闪UWB做了一个数字钥匙门锁系统开源了前言今年电赛C题要求做一套数字钥匙系统——钥匙能自动识别身份门锁能判断钥匙距离在范围内自动解锁说实话这题不算难但要做得好不容易。身份识别用什么通信方案测距怎么保证精度怎么滤掉噪声区域判断的状态机怎么设计我的方案是星闪SLE做身份识别 4锚点UWB做厘米级定位 卡尔曼滤波平滑数据 三级区域状态机控制门锁最终效果钥匙靠近2米黄灯欢迎1米内绿灯解锁离开自动上锁全程OLED实时显示距离和角度。距离误差均为5cm内角度误差7度内很遗憾今年电赛我们因为一些原因失利了但是还是决定将项目分享出来希望能够帮助到大家代码已开源https://gitcode.com/gcw_rVSV2mp6/diansai-C下面分享一下整体思路和踩过的坑系统架构先放一张整体架构图星闪 SLE 通信 ┌────────────┐ ID 广播 Notify ┌─────────────────────┐ │ 钥匙 KEY │ ◄──────────────────────► │ 门锁 LOCK │ │ (H3863) │ UUID: 0x2828/0x2929 │ (H3863) │ │ │ │ SLE / UART×2 / OLED │ └────────────┘ │ LED×3 / 蜂鸣器 │ └─────────────────────┘ ▲ ▲ UART1 │ │ UART2 ▼ ▼ ┌──────────┐ ┌──────────┐ │ 锚点 E │ │ 锚点 G │ │ 锚点 F │ │ 锚点 H │ │ STM32 │ │ STM32 │ │ DW1000 │ │ DW1000 │ └──────────┘ └──────────┘整套系统分三部分钥匙端一块BearPi-Pico H3863通过星闪广播身份ID一块STM32最小系统板加DWM1000模块当作标签门锁端一块BearPi-Pico H3863接收ID 双UART收测距数据 OLED显示 LED/蜂鸣器UWB锚点4个STM32DWM1000模块分布在不同位置做测距测完通过串口把距离发给门锁为什么不用H3863直接驱动DWM1000一开始我也试过但H3863的SPI跟DW1000配合时序有问题我一直没有移植成功。后来改成STM32专门负责UWB测距通过串口把结果发给H3863处理效果稳定多了身份识别星闪SLE为什么选星闪题目要求身份识别传统方案是BLE蓝牙。但BearPi-Pico H3863原生支持星闪SLESparkLink Edge这是华为主推的新一代短距通信技术比BLE延迟更低、功耗更低而且SDK里自带SSAP协议栈开发起来跟BLE GATT很像上手很快通信流程钥匙端 (Server) 门锁端 (Client) │ │ │ ◄── 广播 diansai2_key ────── │ 扫描 │ ── 连接成功 ─────────────────► │ │ ── 配对完成 ─────────────────► │ │ ── MTU 交换 (520) ────────────► │ │ ── 服务发现 ──────────────────► │ │ ── Property Handle ──────────► │ │ │ │ ── Notify ID (0x0A) ─────────► │ 每500ms │ ── Notify ID ────────────────► │钥匙端做Server注册一个ServiceUUID 0x2828和一个PropertyUUID 0x2929配对完成后每500ms通过Notify推送一次ID。门锁端做Client扫描发现钥匙后连接、配对、服务发现然后等着收NotifyID校验钥匙发送的ID是4-bit0~15门锁端用拨码开关设置期望ID收到后比对if (received_id expected_id): 验证通过 - 允许解锁 else: 验证失败 - 保持锁定OLED上会实时显示接收ID和期望ID以及PASS/FAIL结果UWB测距4锚点DS-TWRDS-TWR双向测距原理UWB测距用的是DS-TWRDouble-Sided Two-Way Ranging算法分三步Tag (标签) Anchor (锚点) │ │ │── Poll 包 ──────────────────────►│ T1 发送, T2 接收 │◄── Response 包 ──────────────────│ T3 发送, T4 接收 │── Final 包 (含T1,T4,T5) ────────►│ T5 发送, T6 接收 │ │ │ 锚点根据6个时间戳计算TOF │飞行时间计算公式Ra T4 - T1 (Round 1) Rb T6 - T3 (Round 2) Da T5 - T4 (Reply 2) Db T3 - T2 (Reply 1) TOF (Ra×Rb - Da×Db) / (Ra Rb Da Db) 距离 TOF × 光速这个公式巧妙地消除了时钟偏移误差不需要双方时钟同步4锚点轮询标签端不是只跟一个锚点测距而是轮询4个锚点E→F→G→H→E…每个锚点独立测距通过串口输出E D:0.56 F D:1.23 G D:0.89 H D:2.34门锁端用两个UART并行接收UART1 收锚点E、FUART2 收锚点G、H锚点布局60cm E ┌──────────┐ G │ │ │ │ 60cm │ │ F └──────────┘ H定位算法从测距到坐标卡尔曼滤波UWB测距有噪声直接用会跳得很厉害。每个锚点独立维护一个卡尔曼滤波器预测: 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_predQ越大越相信测量值R越大越相信预测值。0.05和0.1是我反复调试出来的参数野值剔除卡尔曼滤波能平滑小噪声但对大跳变无能为力。所以加了一层野值剔除if |测量值 - 估计值| 50cm: 用估计值替代连续拒绝计数1 if 连续拒绝 5次: 接受新值强制重置防止卡死 else: 正常卡尔曼更新50cm阈值和5次限制是经验值太小会误杀正常值太大会让噪声通过。坐标解算有了4个锚点的滤波后距离怎么算位置用的是差分平方法不需要解非线性方程计算量小x (d_G² - d_E²) / (2L) (L60cm, 2L120) y (d_H² - d_F²) / (2L)原理很简单如果G和E距离相等x0如果离G更近x0。平方差正好消了距离的常数项径向距离坐标x,y算出来后径向距离avg (d_E d_F d_G d_H) / 4 r (avg - 61.0) / 1.10561.0和1.105是实测校准值——在已知距离点采样拟合出来的零偏和缩放系数。不同硬件需要重新标定方位角angle -atan2(y, x) × (180/π) - 125°-125°是锚点布局的安装偏移跟实际摆放方向有关。角度也做了指数平滑α0.3并且处理了360°环绕问题diff new_angle - old_angle if diff 180: diff - 360 if diff -180: diff 360 smooth 0.3 × diff区域状态机距离算好了接下来是区域判断。分三级距离 1m ┌──────────┐ ─────────────► ┌──────────┐ │ SENSING │ │ UNLOCK │ │ (红灯) │ ◄───────────── │ (绿灯) │ └──────────┘ 距离 1m └──────────┘ │ │ 距离 2m ▼ ┌──────────┐ │ WELCOME │ │ (黄灯) │ └──────────┘区域距离LED蜂鸣器解锁区 1.0m绿灯短响100ms欢迎区 2.0m黄灯长响200ms感知区 2.0m红灯-关键细节只有ID验证通过才会解锁。如果ID不匹配不管多近都是红灯锁定。事件驱动蜂鸣器蜂鸣器不是一直响而是区域变化时才响进入解锁区 → 短响离开解锁区 → 短响进入欢迎区 → 长响离开欢迎区 → 长响这样不会太吵但每次状态变化用户都能感知到。OLED显示门锁端有一块0.96寸SSD1306 OLED用软件I2C驱动因为硬件I2C被占用了显示内容扫描中SLE: Scanning... Exp: b0000 Key ID: ---- Zone: ----已连接Key:b1010 Exp:b0000 Ver: PASS Dist:1.23m A:4.5 Zone: WELCOME Event: Enter Welc Hrz:1.53m Status: WELCOME第一行同时显示接收ID和期望ID的二进制第二行PASS/FAIL第三行距离和角度第四行区域第五行事件第六行水平距离第七行状态。6x8字体8行显示信息密度刚刚好字库字库是自己做的6x8点阵95个ASCII字符每个6字节一共570字节。直接写在头文件里编译时写死到FlashRTOS任务架构门锁端跑LiteOS两个并行任务┌─ Diansai2Lock (优先级 17) ──────────┐ │ · SLE Client 扫描/连接/配对 │ │ · 接收 ID DIP 校验 │ │ · OLED 刷新 (200ms) │ │ · LED/蜂鸣器控制 │ │ · 区域判断 状态机 │ └────────────────────────────────────┘ ┌─ Diansai2LockDist (优先级 15) ──────┐ │ · UART1 接收锚点 E/F (115200) │ │ · UART2 接收锚点 G/H (115200) │ │ · 解析 X D:距离 协议 │ │ · 卡尔曼滤波 (每锚点独立) │ │ · 野值剔除 │ │ · 径向距离 方位角计算 │ └────────────────────────────────────┘Lock任务优先级高一点17因为身份识别和状态控制的实时性要求更高。Dist任务优先级15测距数据有一定的容忍度晚几十毫秒没关系。两个任务通过全局变量通信g_distance_cm、g_angle等简单粗暴但有效踩过的坑1. H3863直接驱动DW1000时序不稳一开始想用H3863的SPI直接驱动DW1000但是SPI程序一直没有移植成功解决方案改用STM32专门驱动DW1000测距完成后串口把距离发给H38632. UWB测距跳变DW1000测距偶尔会跳一下比如实际1米突然报5米。卡尔曼滤波能平滑小波动但对这种大跳变没用解决方案加了野值剔除层偏差超过50cm的测量值直接丢弃用上一次的估计值替代。连续丢弃5次后才强制接受新值防止滤波器卡死3. 角度跳变角度在±180°附近会突然跳变比如从179°跳到-179°普通的指数平滑会把这个跳变放大解决方案做平滑前先处理环绕diff new - old if diff 180: diff - 360 if diff -180: diff 360 smooth α × diff硬件清单器件数量角色BearPi-Pico H38632钥匙 门锁STM32F103 DW10005标签UWB锚点 E/F/G/HSSD1306 0.96 OLED1门锁显示LED 红/绿/黄3状态指示有源蜂鸣器1事件提示4位拨码开关2ID设置主控是Hi3863RISC-V 32bit240MHz集成Wi-Fi6/BLE/星闪SLE606KB SRAM4MB Flash。跑LiteOS实时操作系统代码结构diansai2/ ├── README.md # 项目文档 ├── LICENSE # CC BY-NC-SA 4.0 ├── diansai2.h # 公共定义 ├── diansai2_key.c # 钥匙端SLE广播 ID Notify ├── diansai2_lock.c # 门锁端SLE接收 UART测距 卡尔曼 OLED 状态机 ├── diansai2_oled.c/.h # SSD1306软件I2C驱动 ├── diansai2_oled_font.h # 6x8点阵字库 ├── CMakeLists.txt # 构建配置 ├── Kconfig # 引脚配置 └── stm32_uwb/ # STM32 UWB测距固件 ├── 标签/ # Tag固件轮询4锚点 └── 基座/ # Anchor固件测距UART输出开源项目地址https://gitcode.com/gcw_rVSV2mp6/diansai-C硬件开源地址2026电赛C题-小熊派解决方案 - 立创开源硬件平台包含H3863钥匙端门锁端完整固件STM32 UWB标签锚点完整固件含DW1000驱动README文档 项目介绍许可证CC BY-NC-SA 4.0署名-非商业性使用-相同方式共享可以学习、研究、修改、分享但不能商用衍生作品也要用同样的许可证总结这个项目几个关键设计决策星闪SLE替代BLE新技术尝鲜延迟更低SDK好用STM32H3863架构分离UWB测距交给STM32H3863专注通信和逻辑多级滤波卡尔曼野值剔除两层防护差分平方定位计算量小不需要解非线性方程事件驱动状态机蜂鸣器只在区域变化时响不吵做电赛最大的收获不是最后的结果而是踩坑的过程。UWB时序、卡尔曼调参、角度环绕、OLED花屏……每个坑都花了不少时间但解决之后对整个系统的理解会深很多希望这篇分享对大家有帮助代码已经开源欢迎交流本文项目开源地址https://gitcode.com/gcw_rVSV2mp6/diansai-C许可证CC BY-NC-SA 4.0禁止商用

相关新闻

短剧翻译流程简化实测:跟传统译制片比省了哪几步

短剧翻译流程简化实测:跟传统译制片比省了哪几步

短剧翻译流程跟传统译制片比,哪里做了简化?先给结论:省掉的不是翻译、配音、画面修复和质检,而是三类低效动作——跨供应商反复交接、等待真人录制与逐帧修图、为每种语言重复建项。以一部多集竖屏短剧为例,传统方式常…

2026/10/18 5:25:01 阅读更多 →
基于线性延时模型的晶体管尺寸优化:原理、实战与PPA权衡

基于线性延时模型的晶体管尺寸优化:原理、实战与PPA权衡

1. 项目概述:从“差不多就行”到“精打细算”的转变在超大规模集成电路(VLSI)设计的漫长流程里,逻辑综合和物理实现之后,我们常常会面对一个看似简单、实则充满玄学的问题:这个反相器(Inverter&…

2026/10/16 1:50:02 阅读更多 →
C++核心语法与函数编程速查手册:从基础到现代特性实战指南

C++核心语法与函数编程速查手册:从基础到现代特性实战指南

1. 为什么你需要一份C速查手册?干了这么多年C,我电脑里一直存着几个自己写的“小抄”文件。每次新开一个项目,或者隔段时间回头维护老代码,总会遇到那么几个语法细节突然想不起来——比如constexpr和const在函数声明里到底怎么组合…

2026/10/17 23:49:45 阅读更多 →

最新新闻

2026互联网大厂职级薪资全解析:AI测试开发面试与晋升指南

2026互联网大厂职级薪资全解析:AI测试开发面试与晋升指南

1. 从一份薪资爆料帖说起:为什么大家都在盯着这套职级表最近技术圈里聊得最热的话题之一,就是某头部视频平台流出的2026年职级与薪资体系对照表。我前后翻了好几份不同渠道的版本,也跟几位在不同业务线待过的朋友交叉验证了一下,发…

2026/10/18 6:35:53 阅读更多 →
ZooKeeper SSL/TLS加密配置实战:从证书生成到客户端接入

ZooKeeper SSL/TLS加密配置实战:从证书生成到客户端接入

有一次帮内部中间件平台做上线前安全自查,评审的人指着监控面板问了一句:你们的协调服务,客户端和服务端之间是明文还是加密?我当时心里咯噔一下——因为不止是客户端到服务端,集群节点之间也一直在裸奔。回去翻了翻配…

2026/10/18 6:35:53 阅读更多 →
PyTorch深度学习框架:动态图、性能优化与训练管道实战

PyTorch深度学习框架:动态图、性能优化与训练管道实战

如果你打开招聘网站随便翻一圈深度学习的岗位描述,十份里至少有七八份都写着"熟悉 PyTorch,有独立训练模型的经验"。这句话在 2025 年几乎成了行业标配,背后是一个比较直白的现实:PyTorch 已经不只是一个深度学习框架&a…

2026/10/18 6:35:53 阅读更多 →
网络自动化实战:从手工运维到批量配置与智能决策

网络自动化实战:从手工运维到批量配置与智能决策

1. 网络自动化到底是什么:先从一个加班夜说起我到现在还记得那个晚上。凌晨两点,某公司机房的空调嗡嗡响着,我蹲在工位上,对着十几个机柜里的交换机,一台一台地敲命令。原因特别简单——业务要扩容,全网设备…

2026/10/18 6:35:53 阅读更多 →
102道Cypress面试题深度解析:从原理到实战的知识体系梳理

102道Cypress面试题深度解析:从原理到实战的知识体系梳理

102道Cypress面试题整理完之后,回头再看这份资料,它远不只是一份背诵手册。去年我花了两周时间梳理这些题目,本意是为了准备面试,但真正做完之后,反而对自己的Cypress知识体系做了一次全面体检。这篇博文就把我整理这1…

2026/10/18 6:35:53 阅读更多 →
AI论文写作工具实测:从SCI到会议论文的适配指南

AI论文写作工具实测:从SCI到会议论文的适配指南

把AI写论文这件事聊透之前,我先说个结论:真正好用的AI论文写作工具,从来不是那种一键生成全文的“黑箱”,而是能针对不同类型期刊论文,把你从文献整理、结构搭建、语言润色、格式校对这几座大山里逐个捞出来的那几款。…

2026/10/18 6:34:53 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →