Matrix精选 2026年10月08日 30 分钟阅读

30 分钟阅读

Matrix 首页推荐

Matrix 是少数派的写作社区,我们主张分享真实的产品体验,有实用价值的经验与思考。我们会不定期挑选 Matrix 最优质的文章,展示来自用户的最真实的体验和观点。

文章代表作者个人观点,少数派仅对标题和排版略作修改。

AI 辅助创作声明(作者注):

本文记录的固件代码由 Anthropic 的 Claude Code(Claude 模型)编写,作者负责提出需求、在开发板上安装验证和做决定。文章初稿由 Claude 根据开发过程中的会话记录和交接文档整理成文,作者逐段改写并核对了其中的事实、数据和引用来源;文中「顺手想到」和「放大看」两类段落的观点为作者本人所写。示意图由 Claude 按作者要求绘制,实拍照片和截图为作者本人拍摄、截取。作者已对全文做了核查和修改,文责自负。

如果有人问我,我花时间,花 Token 来做这么一个没有用的东西有价值吗?我的回答是肯定的,最大的意义其实就在于,证明 Vibe Coding 在硬件领域正在快速成长,为什么呢?因为数字世界已经到了一定的瓶颈了,是需要物理世界来反哺数字世界。如果没有 AI Agent 发展到今天这个程度,我是完全不敢想象自己要能做这件事要花多少时间去学习硬件、嵌入式、软件、通信等知识,要去查多少资料,这都需要时间的积累,但这些积累在数字世界基本都有了,硬件的东西像乐鑫这样子专业的公司做了就行了。

先把几个词说清楚,方便没碰过硬件的读者往下读。

开发板是芯片厂商给工程师验证芯片、写固件用的一块电路板,把芯片、供电、USB 口和常用外设(屏幕、麦克风、喇叭、传感器)焊在一起,拿到手就能通电写程序,它不是面向消费者的成品。ESP32 是乐鑫的一个芯片系列,自带 Wi-Fi 和蓝牙,便宜、省电、资料多,创客圈和 AI 硬件玩具里用得最多的就是它。固件就是烧进这块板子里的程序,决定了板子开机后干什么。

模块化开发板的意思是主板只带最基本的东西,摄像头、人体感应、灯这些功能做成一块块小板,按需插在主板两侧的扩展槽上,想要什么能力就插什么模块。ESP-Mosaico 是乐鑫 2026 年 8 月发的一块这样的板子,特别之处是它从一开始就按「让 AI 编程工具来写固件」设计:板子里固定住一套叫 Vibe Mode 的底层固件,负责装程序、恢复和看日志,用户不用碰烧录工具;上手不是看引脚图,而是把一句提示词交给 Claude Code 这类编程 Agent。

乐鑫 8月19日 发的 ESP-Mosaico 是一块专门给 Coding Agent 用的模块化开发板。其实我知道它很粗糙,看到用户反馈说还是 3D 打印的部件,但我还是想看看现在 AI 硬件领域生态做的最好的 ESP32 系列到底是怎么做的,尤其是它现在的 Vibe Code 模式。它的上手方式和以前的开发板不一样:不给你看引脚图,先给你一句提示词,让你丢给 AI 编程工具。那句话是这样的:

第一个作品是贪吃蛇。我照做了,用 Claude Code 跑完这一句,板子上就能玩了。10月2日 Meta 开源了 Muse Gadgets 的设备 SDK,官方推荐的硬件也是 ESP32,于是接着往下做:当天这块板变成了一台 Muse 小设备,后面持续迭代了一下就能用中文对话、把回复念出来、按 Muse 的要求拍一张照片发回去、我走近的时候亮灯打招呼。

整个过程是我和 Claude Code 一起做的,前后开了四个会话,其中两个在同一块板子上并行干活。这篇按发生的顺序写,分五段,每段后面放一点做的时候顺手想到的,最后放大看。代码在这两个仓库:

ESP-Mosaico 的主控是 ESP32-S31,480 方屏、带喇叭麦克风、两侧能插扩展模块。它和普通开发板最大的区别是 Flash 前 2 MB 住着一套固定不动的固件,叫 Vibe Mode:装应用、恢复、看日志、截屏都走它,用 mosaico.py 一条命令就能装机,不用碰 esptool。开机按住橙色的 AI 键就进 Vibe Mode,所以应用写坏了也不会变砖。

那句提示词丢进去之后,AI 先花了一个晚上搭环境,坑都在环境这一层,不在游戏:

以上都是 Claude Code 自己执行完成的,我什么也没有做。游戏本身用 Raylib Lite 写,规则和画法分两个文件,同一份 C 代码在浏览器模拟器和板子上跑。20×18 的格子,吃一个苹果长一节、加一分,速度从每秒 6 格涨到 12.6 格,撞墙或撞自己结束,填满算赢。触屏上滑动转向,点一下开始或朝那边转,点分数栏暂停。8 个回放测试,每个场景存成回放再跑一遍,最终状态的哈希必须一致。

模拟器里顺手抓到一个模板的 bug:空白游戏模板只听触摸点 0,浏览器把鼠标报成点 1,所以点击没反应。改成跟着先按下的那根手指或鼠标走。

装上板子是第二天的事。板子第一次插上 Mac 认不到,换了根能传数据的线才出现。第一次用的板子先跑 recover 写 Vibe Mode 基础固件,再用 system-update 装贪吃蛇。装完核对三件事:设备 ID 不变、启动 ID 是新的、设备报告健康。板上实测 33.3 fps,没掉帧,触摸正常。

贪吃蛇做完,环境也就踩通了。接下来的 Muse 全部建立在这上面。

顺着这个看几个事情,自从 Anthropic 开源了 Claude Desktop Buddy、把自己的螃蟹装进 M5StickC 这块小板子里之后,多少人开始效仿,又有多少人去 Vibe Coding 自己的电子宠物,给个屏幕让它呈现出来,提供情绪价值,官方推荐的也是 ESP32 这个生态的东西,到这次 Muse 推荐的也是 ESP32 生态的,因为它足够简单,成长这么多年 AI 能在互联网上找到足够多的知识来帮助用户去实现他个人定制化的需求。

我买这块板子的时候预判到后面类似 GrokBot 这类产品肯定会接硬件设备的,方便我第一时间去玩,没想到 Muse 先干了,以开源项目的方式先干了。我之前也用手机模拟硬件设备接了 GrokBot。

Muse 是 Meta 做的个人 AI 助手。Muse Gadgets 开源的只有设备端:一套 ESP32 固件和一套树莓派用的 Linux SDK,Apache 2.0。助手本身不开源,设备要先去 gadgets.muse.ai 领一个 SDK token,再在 Muse App 里打开开发者模式配对。官方支持的板子里,带完整界面的是 Waveshare 1.75 寸圆屏 AMOLED 这一类。

初次使用,我发现 Muse 比 GrokBot 反应是要快很多的,应该是意图识别做的更好,GrokBot 说什么都要比较长的反应时间,GrokBot 本身没有做任何设备交互的工作,界面显示的内容和设备播报的内容不会完全一致,Muse 就好很多。

把 Muse 的固件直接编译给这块板,有三件事过不去:

如果是我本人没有 Claude 的情况下,我都看不出来这三个问题,现在有了,不妨碍我继续玩下去。我的决定是:Vibe Mode 不动,把 Muse 做成一个标准的 ESP-Mosaico 应用,用 Vibe Mode 装机。后面的 Flash 的分法是 Claude 做的,变成下面这样。

Muse 的配对信息、Wi-Fi 密码、设备凭证都在那块 64 KB 的 nvs 里,换固件不会清,所以后面十几次装机都没有重新配过对。这个点太重要了,如果不是做这个项目,我完全不知道还可以这样子操作。

代码分三层。Meta 的 SDK 只开了几个小口,板子相关的全部放在包装工程里,SDK 的 esp-mosaico 分支加起来 9 个提交,每一个默认都关着,其他板子的行为不变。

SDK 那边最早的两处改动是必须的:

路由器是普通家用的,改不了网关。最后的做法是把 Mac Studio 当旁路由,只让板子这一台走它,家里别的设备不动。

固件里加了两个配置项,默认为空:

Mac 这边本来以为要给 Clash 开局域网连接和 DNS 端口,查了才发现不用:它的 TUN 模式已经接管了全部公网流量,dns-hijack: any:53 会把经过它的 DNS 查询一并答掉。只需要打开 IP 转发:

这条重启会失效。

无屏版 Muse 装上板子之后,日志里蓝牙一直在广播 MuseGadget-F46F0A,等人来配对。卡了一晚上,两个问题最后都证明和板子无关。

手机搜不到蓝牙。 iPhone 系统设置里的蓝牙列表只显示耳机、键盘这类设备,低功耗蓝牙的广播本来就不出现在那里。但 ESP-Mosaico 官方 BSP 的功能表里没有蓝牙,示例里一个用蓝牙的都没有,所以这块板的蓝牙到底能不能用,之前没人验证过。为了把 Muse 的因素排除掉,做了一个只做蓝牙收发的诊断固件 ble_diag:以 MosaicoBLE-DIAG 的名字广播,每 15 秒用板子自己的蓝牙扫 5 秒。结果每轮能听到 34 到 37 个设备,最强的信号 −37 dBm;手机装 nRF Connect 也看到了它。板子收发都正常。这个固件留在仓库里,以后怀疑蓝牙随时装上测一次。

Muse App 开了开发者模式,没有添加设备的入口。 查了套餐、地区、iOS 测试版,都没有定论。第二天它自己出现了,是 App 那边的问题。下面是正常时候的样子,右上角的加号就是入口,开发者模式的说明写得很直白:允许配对没经 Meta 验证的社区设备,这些设备对你的助手有完整权限。

配对本身很顺:App 里选设备,日志提示确认时短按 AI 键,填 Wi-Fi 密码,板子重启后连上 Muse。

带屏幕的 Muse 界面是 LVGL 画的,上游用的板子是圆屏。移植有两个选择:照着 Muse 已支持的 Waveshare 板写一套驱动,或者用 ESP-Mosaico 官方的 BSP。选了 BSP:它认识这块板的两个硬件版本(引脚从 eFuse 读),管着屏幕依赖的电源,还会接住 Vibe Mode 的开机画面,让屏幕一直显示到 Muse 画出第一帧。代价是关掉 BSP 自带的 LVGL 层,图形库只留 Muse 那一份,免得两份打架。

Muse 自带一个桌面模拟器,给它加了一档 480 方屏的配置。待机、聆听、思考、配网、出错五个状态先在模拟器里看过,没有越界,再上板。

上板之后调了三处:

8月底很火的 MicroDuck 是破圈了,399 美元,几天卖了一万多台,没有 Vibe Coding 的人都在说想买一个,想买一个干嘛呢?朋友说单纯做一个玩具也行。这个用的是瑞芯微的 RK3566,有比 ESP32 更强的本地能力,不少做机器人的都用了瑞芯微的芯片,说实话,我们自己在预研探索的产品用的也是 RK 系列的芯片,不过他们的芯片和 ESP32 系列不同的是做不小:我们现在已经遇到了想做小但散热解决不了的问题,甚至才用到它 CPU 的 20% 左右就烫得不行。再看看做 MicroDuck 的 Pollen Robotics,去年 4月被 Hugging Face 收了,今年 9月2日英伟达又宣布 129 亿美元收购 Hugging Face,LeRobot 和这些机器人背后站着的是英伟达,英伟达的模型和算力已经很牛逼,但虚拟世界再怎么模拟计算,再怎么解决 SIM2REAL 的 GAP,GAP 就是会存在,不如真实世界来的好。做这些产品,做不出来什么有用的东西,但能让团队/人了解开发具身智能这套工具链,就像我做这个没用的 Muse Gadget 一样,我知道他是怎么回事了,后面真想做有用的,或者一直跟他的技术进步,真能做出来有用的东西。

9月国内的安克也做了一件事情,搞首届黑客松(9月7日报名,10月中旬在深圳决赛),把自己公司成熟硬件产品的 SDK 开出来,邀请各位来一起构建应用。参赛的协议里面写的很清楚,参赛的设计、代码等都归安克所有。安克可以说是国内最近几年风头正劲的公司,AI NATIVE 推进也很靠前,人才济济的他为什么要做这样的事情呢?我相信他们也发现现在的 AI 除了在数字世界让 Human In The Loop 产生价值外,很难找到在消费品领域让用户买单的应用场景。他们类似 Plaud 的安克豆已经是目前 Agent 的极限状态,因为做个会议纪要,最后还是要我自己看一遍的。

配对成功后第一次用中文提问,屏幕上一片空白。Muse 的字幕字体是 unscii,只有 ASCII。固件会把弯引号、破折号这些转成英文符号,汉字直接没了。

做法是给板子加一套 16 px 的中文字体:从思源黑体 CN 里取 GB2312 的 6763 个汉字加中文标点,共 6953 个字形,转成 LVGL 的二进制字体,884 KB。它编进固件,界面启动时载入 PSRAM,实测用了 0.57 秒。文件叫 cjk_16.bin,不叫思源的名字,因为 OFL 规定改过的字体不能沿用保留名。

Muse 这边加了一个「宽字体回退」:主字体没有的字去宽字体里找。两个细节要处理:

还顺手抓到一个老 bug:字幕缓冲 400 字节,一个汉字占 3 字节,一页中文只能放半页,后半页被跳过。改成 800 字节,补了一条测试,旧代码跑这条会挂。后来又把 Markdown 从字幕里去掉了:行首的井号、列表号、引用号,行内的加粗、代码、删除线,链接只留文字。Muse 写回复很爱用这些符号,在 16 px 的字幕里只会碍事。

Muse 的设备协议里,拍照是 Muse 主动叫设备拍:设备启动时向 Muse 声明自己支持 camera.capture,你问「看看我面前是什么」,Muse 判断需要看画面就调用它,设备拍一张 JPEG 传回去。官方 SDK 里只有 SenseCAP Watcher 实现了这个命令,而且写死了。改成任何板子只要注册了摄像头就会声明并响应,Watcher 的路径不动。

板子这边,摄像头子板插左槽。第一版按 BSP 文档里的 OV3640 写,让传感器直接出 JPEG。装上去一试,Muse 说拍了两次都失败:

日志里是 format=JPEG is not supported。我手上这块子板的传感器是 SC101IOT,不是 OV3640,它没有 JPEG 模式。第二版改成取原始的 UYVY 画面,在板上用 esp_new_jpeg 编码,顺手逆时针转 90°,因为传感器在子板上是横着装的。拍完的照片在屏幕上显示 4 秒,能看到 Muse 收到的是什么。

两个额外的处理:

第二版实测:

Muse 只回文字,不回语音。日志里那句「reply audio」只是按字幕节奏留出的静音,官方文档的说法是想要语音就自己接一个文字转语音服务。两条路:云端语音服务音质好,但每条回复多一次网络请求,还要经过 Mac 出网;板上离线合成音质偏机械、只会中文,但不联网、免费。先选了后者,乐鑫 esp-sr 的中文 TTS,小乐音色。第二天又补了前者的一个变体:不走云端,走我自己 Mac 上的 Qwen3-TTS。两条路现在都在固件里。

语音数据 2.9 MB,单独占一块分区:应用分区从 14 MB 缩到 11 MB,腾出 3 MB 放 voice_data。改了分区表就要用 system-update 重装一次,配对信息所在的 nvs 不在包里,装完配对还在。

esp-sr 只认汉字、数字和中文标点,Muse 的回复里有 Markdown、表情、链接和零星英文,念之前要先清理一遍:

喇叭开着时,字幕跟着语音走;喇叭关着时按阅读节奏翻页,和上游一样。

装上去第一次说话,板子复位了。从板上留存的 core dump 读到断言 s_task_stack_is_sane_when_cache_frozen。原因是我在 Muse 的对话任务里映射 voice_data 分区,映射会改 flash 的 MMU,期间 flash 缓存被冻结,而这个任务的栈在 PSRAM,缓存冻结时不允许访问 PSRAM 上的栈。改成开机时在主任务里映射,主任务的栈在片内 RAM。这条规则后来写进了接口的注释:栈在 PSRAM 的任务不能做 mmap、不能写 NVS、不能读写 flash。

修好之后的数据:

小乐只会中文,Muse 的回复经常中英混着。我家里那台 Mac Studio 上本来就跑着一个 Qwen3-TTS 服务,OpenAI 风格的接口,中英都念。于是固件里加了第二条路:回复先交给 Mac 念,Mac 连不上时中文退回板上的小乐。

这条路第一版就把板子搞崩了。服务端按合成速度往板子灌 PCM,板子只开了 1 秒的下载缓冲,读不完的语音堆在网络协议栈里,占住 Wi-Fi 的接收缓冲,片内 DMA 内存被吃到 1 KB 以下。改成两头都收着:服务端先发 1 秒,之后不超过实时的 1.5 倍;板子把整条语音先存进 PSRAM 再播。试过把 Wi-Fi 的缓冲挪去 PSRAM,这颗芯片上进不去,反而多出一批常驻的发送缓冲,撤回了。

接着是一个更难的:对话中随机崩,空闲时也崩过一次。板上留下的 5 份 core dump 全是读内存出错,地址都是合法的 PSRAM 数据,而且全部落在 PSRAM 里只读区和可读写区的分界线之后 46 KB 以内。读了两个核的内存保护寄存器,都是对的。能稳定复现:同时跑一个内存锤子测试和边下载边播放,4 分钟左右崩一次。

… Trimmed for readability. Visit the source for the full article.

Extracted and lightly reformatted for readability. · Source: zh