把 Muse 装进 ESP-Mosaico:做一个没用的东西,证明 Vibe Coding 也在硬件领域快速成长

💡 原文中文,约16100字,阅读约需39分钟。
📝

内容提要

作者用Claude Code在乐鑫ESP-Mosaico开发板上实验:先按官方提示词跑通贪吃蛇,再移植Meta开源的Muse固件并做成标准应用,保留Vibe Mode装机,解决环境、分区、网络、屏幕、中文字体、拍照、语音等问题;随后扩展板子能力,使Muse能调用灯、屏幕、语音等命令。作者认为AI正快速进入硬件领域,硬件需留冗余,未来AI产品将是软硬结合、高度定制化。

🔎

延伸解读

Vibe Mode 的隔离设计让硬件试错成本大幅降低

ESP-Mosaico 将前 2 MB Flash 固定为 Vibe Mode,负责装机、恢复和日志,应用写坏也不会变砖。作者移植 Muse 时选择不动 Vibe Mode,把 Muse 做成标准应用,并通过 system-update 安装。这种分区隔离让开发者可以反复刷写而不担心底层固件被覆盖,是硬件 Vibe Coding 能快速迭代的关键前提。

移植 Muse 的真正难点在网络与工具链,而非代码本身

作者遇到三个硬障碍:Muse 固件只认 ESP-IDF 6.0.1,而该版本不支持 ESP32-S31;官方刷机方式会覆盖 Vibe Mode;api.muse.ai 等域名在国内直连超时。最终通过固定工作区版本、改为标准应用安装、用 Mac 做旁路由转发外网流量和 DNS 来解决。这说明硬件移植的瓶颈往往在环境适配和网络可达性。

中文字体、语音和拍照的适配暴露了上游固件的默认假设

Muse 字幕字体 unscii 只有 ASCII,中文直接消失;作者加入 16 px 中文字体并处理基线、换行和字幕缓冲。语音方面,Muse 只回文字,作者接入板上 esp-sr 中文 TTS 和 Mac 上的 Qwen3-TTS 两条路径。拍照命令上游只对 SenseCAP Watcher 写死,作者改为任何注册摄像头的板子都能响应。这些改动说明通用固件在具体硬件上需要大量本地化修补。

硬件冗余是应对 AI 软件快速迭代的必要策略

作者在内存账中发现,加入字体、语音和问候功能后,Muse 就绪时空闲片内 RAM 从 74.7 KB 降到 49.0 KB,DMA 最低到 12 KB。通过把可挪动的缓冲移到 PSRAM、关闭从 PSRAM 执行代码,才恢复到 64.5 KB。作者据此认为,AI 硬件应保留能力冗余,以覆盖至少半年的 AI 软件发展,而非追求极致成本。

❓

Q&A

ESP-Mosaico 开发板有什么特别之处?它和普通开发板有什么不同?

ESP-Mosaico 是乐鑫推出的模块化开发板,主控为 ESP32-S31,带 480 方屏、喇叭麦克风,两侧可插扩展模块。它最大的不同是 Flash 前 2 MB 固定了一套 Vibe Mode 固件,负责装应用、恢复、看日志和截屏,用户用 mosaico.py 一条命令就能装机,不用碰 esptool;开机按住橙色 AI 键就进 Vibe Mode,应用写坏也不会变砖。上手方式也不是看引脚图,而是把一句提示词交给 Claude Code 这类编程 Agent。

作者为什么要把 Meta 的 Muse 固件移植到 ESP-Mosaico 上?遇到了哪些主要障碍?

作者想验证 Vibe Coding 在硬件领域的成长,并体验 Meta 开源的 Muse Gadgets 设备端。移植时遇到三个主要障碍:Muse 固件只认 ESP-IDF 6.0.1,而该版本不支持 ESP32-S31;官方刷机方式会覆盖前 2 MB 的 Vibe Mode;板子在国内连不上 api.muse.ai 和 hatch.metaaivm.com。作者的解决思路是 Vibe Mode 不动,把 Muse 做成标准 ESP-Mosaico 应用,用 Vibe Mode 装机,并通过 Mac 旁路由解决网络问题。

Muse 固件移植后,Flash 分区是怎么安排的?配对信息为什么能保留?

16 MB Flash 中,前 2 MB 留给 Vibe Mode,Muse 住在后面。Muse 的配对信息、Wi-Fi 密码、设备凭证都放在一块 64 KB 的 nvs 分区里,换固件不会清空,所以后续十几次装机都没有重新配过对。后来为了放语音数据,应用分区从 14 MB 缩到 11 MB,腾出 3 MB 给 voice_data,用 system-update 重装后配对信息依然保留。

为了让 Muse 显示中文,作者做了哪些字体和排版上的处理?

Muse 原字幕字体 unscii 只有 ASCII,汉字会消失。作者从思源黑体 CN 取 GB2312 的 6763 个汉字加中文标点,共 6953 个字形,转成 LVGL 二进制字体 cjk_16.bin(884 KB),编进固件并在启动时载入 PSRAM,实测耗时 0.57 秒。Muse 侧加了宽字体回退,并处理了基线(把中文字形抬到主字体基线上)和换行(按字换行、闭合标点不落行首、开引号不落行尾)。还修复了字幕缓冲 400 字节导致一页中文只能放半页的旧 bug,改为 800 字节,并去掉了字幕中的 Markdown 符号。

作者如何让 Muse 能够调用板子的灯、屏幕和语音等能力?

Muse 和板子之间不是 MCP,而是 Meta 的 Home Link 协议:板子连上时报一份命令清单,每条带描述和参数,Muse 看着清单决定何时调用。上游清单只有健康、发现、画网址图、放动画、拍照五条。作者在 SDK 里加了四条通用命令:voice.say、voice.configure、display.show_text、display.configure;在包装工程里加了三条交互模块专属命令:presence.read、lights.set、ir.send_nec。注册的 JSON 从 1.9 KB 涨到 5.5 KB,Muse 服务端返回 200。实测中 Muse 成功用 Mac 的声音说“你好”,并控制六颗灯亮起和变色。

作者在开发过程中遇到了哪些棘手的稳定性问题?最后是怎么解决的?

主要有两个。一是语音播放时板子复位,core dump 显示断言 s_task_stack_is_sane_when_cache_frozen,原因是对话任务栈在 PSRAM,映射 voice_data 分区时 flash 缓存冻结,不允许访问 PSRAM 上的栈;改成开机时在主任务(栈在片内 RAM)里映射后解决。二是对话中随机崩溃,5 份 core dump 都指向 PSRAM 只读区与可读写区分界线后 46 KB 以内,根因未找到,但通过关闭 CONFIG_SPIRAM_XIP_FROM_PSRAM(代码不从 PSRAM 执行)绕开,锤子测试 10 分钟零崩溃,副作用是 ESP-Iris 的 PSRAM 配置失效,但片内空闲内存持平,PSRAM 反而多出约 4 MB。

作者对 AI 硬件产品的未来有什么判断?为什么强调硬件要留冗余?

作者认为未来很长一段时间的 AI 产品一定是软硬结合、高度定制化的,硬件能力一定会有冗余。因为硬件开发有物理周期,而 AI 软件发展很快,只有冗余的硬件设计才能填补这个时间差,同一款硬件至少要覆盖半年以上的 AI 软件发展。追求极致成本管控很难做好 AI 硬件;只有量级超过一定数量后才会做 Cost Down,或者 AI 能力发展要求硬件能力更低之后成本才会降低。未来不会有一家公司做出极致成本的 AI 硬件解决所有场景问题,而是极客用户在某个场景开发应用,帮助更多人解决同样问题,需求会更细分垂直,但可能都用同一款硬件。

🏷️

标签

➡️

继续阅读