项目详情
安眠科技 · 会聊天的哄睡设备
openvela AI 硬件开发者大赛 2026,队伍 485 小鸣TV。目标板 SF32LB52-DevKit-LCD。
它是干什么的
床头的设备。核心是能跟你聊天:到点它自己开口,你随口说什么它都接得住;
感觉到你慢下来了,它把声音慢慢收掉,不跟你说"晚安"。
为什么核心是"对话"(第一性原理)
睡不着这件事,每晚的原因都不一样 —— 今天脑子停不下来、明天要交东西、
或者就是闷。你没法在黑暗里按按钮,也不想睁眼看屏幕。
这意味着:信息的入口只能是说话,出口只能是声音和光。
固定流程覆盖不了"今天心里有事"这种情况,因为固定流程不会问、也接不住。
反过来说,如果核心是"定时器 + 传感器"(到点放白噪、30 分钟后停),
那这台设备不需要 LLM、不需要 Agent,任何一台几十块的白噪音机都能做。
AI 的价值全部在"能对话"上。
所以这台设备的架构是:Agent 是大脑,负责决策;入睡判定和光引导是它的两个端,
把对话这条回路闭合起来。三者不是并列的三个功能,是「一个核心 + 它的输入和输出」。
核心:Agent 语音对话
板子没有 WiFi(BLE 5.3),所以语音链路是:
MEMS MIC ──► 板子(openvela) ──串口 1Mbps──► PC 网关 ──WebSocket──► Agent(LLM)
▲ │ │
└──── DAC + Class-D 功放 ◄──── TTS ◄────────────────────┘PC 上的网关替板子说小智(xiaozhi-esp32)那套 WebSocket 协议,板子就等于一台小智设备。
一根串口线同时干两件事:烧录和说话。
链路本身有实测数据:20 秒上行 672→704 帧、丢帧 0,req4=39 与手册一致。
它一夜的行为,写在 3 个 Skill 里
skills/ 下是三个直接给 Agent 用的 Skill(标准格式:When to use / How to use /Important / Example,调用 get_current_time、music_play、read_file 等工具):
| Skill | 什么时候用 | 干什么 |
|---|---|---|
sleep-onset.md | 到睡前点、或用户说"我要睡了" | 轻声开场、放噪声、启动入睡监测、判定入睡后 60~90 秒淡出且不播报 |
night-wake.md | 夜里检测到体动/声音,或用户出声 | 不亮屏、不追问、不聊天,用最小声音把人接回去 |
sleep-review.md | 晨起首次互动、或用户问"昨晚睡得咋样" | 一句话简报 + 轻趋势关怀,只报观测不贴标签、不新造数据 |
这三个 Skill 不是文档,是这个设备"会哄睡"的实现方式 —— 哄睡的知识写在提示词里,
而不是硬编码成 if-else。改话术、换策略不用重新烧固件。
口径:Skill 文件本身已按运行时目录格式随仓提交(skills/→/data/agent/skills/)。
从 09-04 到 09-18,这里一直注着"真机 ai_agent 读到并调用这三个 Skill 这一步还没跑过、
状态待做"——2026-09-19 这一步在真机上跑通了,docs/测试记录表.md里该项也从"待做"
改成了"通过"。改这一段是为了记录新事实,不是把之前的待做抹掉:09-18 之前的所有
材料里写的"未验证"在当时都是真的。
它不等你喊唤醒词。 普通音箱你问它才答;这台设备到点自己开口,
半夜你出声它用最小音量接住。主动性由 openvela 的 cron 主动任务 + 3 类触发条件落地
(定时 / 阈值 / 事件),这是 ai_agent 主动任务能力的完整用法。
它记得你。 180 天滚动睡眠档案(入睡潜伏、夜醒次数、哪种手段最快入睡),
全在端侧,断网也能用。睡着后记录、晨起由 sleep-review 读出来 —— 记忆是 Agent 的一部分,
不是独立功能。
附加 1:入睡判定 —— 让它知道什么时候该闭嘴
这是核心回路的输入端。 没有它,Agent 只能靠计时器猜什么时候停;
有了它,Agent 说出口的是"我感觉到你慢下来了,我把声音收掉"这种真判断。
难点在于目标板主核没有独立 DSP,跑不动频域分析。所以走时域:
100ms 帧算 RMS 包络,降到 10Hz,在 30 秒窗里做归一化自相关,
在 0.15~0.5Hz(对应 9~30 次/分)的滞后范围找峰 —— 峰高就是呼吸规律度,峰位就是呼吸率,
再加迟滞状态机防抖。
- 算一次约 18000 次乘加,每 2 秒一回,**占空比 `
映射到 openvela 树里的packages/demos/contest2026_485_mianyu—— 所以包内的
相对路径(src/hal/ui/include/)和 CMakeLists 里的是同一套,改的时候别拆开。
| 路径 | 里面是什么 |
|---|---|
skills/ | 3 个 Agent Skill:sleep-onset / night-wake / sleep-review —— 核心对话逻辑 |
app/mianyu/ | 应用包:mianyu_app_main.c(主循环)+ src/(核心算法层 6 模块)+ include/ + hal/(两个后端)+ ui/(手表界面与字体)+ 构建文件 |
board/ | 板级集成源码(音频通路 bring-up + 串口语音链路)+ 云机构建集成存档;见 board/README.md |
tests/ | 465 条单元测试 + pc_build.py(无 make 环境下的构建驱动) |
demo/night_demo.c | 单晚压缩演示 |
docs/ | 以对话为核心的架构说明、真机运行证据、界面验证、版本迭代日记(36 版)、测试记录表、框图 |
logs/ | AI Coding 协作记录 + 板上启动日志原文 |
contest2026_485_xiaomingTV.xml | 专属仓 manifest:把本仓 app/mianyu 链到 openvela 的 packages 下 |
架构取舍的完整推导(含两个附加的接口设计与接线状态)见docs/以对话为核心的架构.md。
真机现在什么情况
过程和数据都在 docs/真机运行证据_20260914.md、docs/手表界面_真机验证_20260915.md
和 docs/测试记录表.md。
按固件版本顺序的完整调试流水在 docs/版本迭代日记.md,
36 版里跑通 6 版、失败 30 版,失败的也都留着(含每版的失败原文和根因)。
跑通的:核心算法和界面进了固件并在板上运行、手表界面两个页面都建起来了且触摸可用、
串口语音链路 20 秒零丢帧、板载麦克风采集(12 秒真人环境音)、
板子到网关到服务器的识别链路、整晚闭环模拟(9 小时压缩到 11.8 秒跑完)。
喇叭没出声。 声学回环对照算下来 B/C=0.83(功放开和关没区别),
说明麦克风收到的 1kHz 是板内电耦合而不是声波 —— 板上喇叭座 J0101 是空的,还没插喇叭。
这是硬件缺件,不是软件问题。
界面上还没做的:屏幕肉眼确认。串口能证明对象建好、渲染循环健康、触摸挂上,
证明不了"眼睛看到的是对的那一幅画"。另外板级日志里有一条[co5300][readback] ... NO MATCH -> pixel data is not landing,各版本固件都有;
大概率是 QSPI 模式下 GRAM 读回本来就不受支持导致的假警报(同一份日志里
面板 ID 在 4 个字节偏移上错位重复,是读通路有位移的典型样子),但我不靠猜把它写成
"屏是好的" —— 上电看一眼开机闪色就能定论,方法写在上面那份界面验证文档的第 5 节。
另外真人整夜的入睡判定标定还没做,现在的准确率数据只来自合成信号,报告里如实标了。
License
Apache-2.0