构建一个基于 ESP32-S3 的开源、支持 WiFi 的虚拟宠物项目
这次我带来了 TamaFi V2,这是对我的开源 WiFi 感知型虚拟宠物的全面重做,几乎所有的原始代码在这一过程中都已不复存在。
TamaFi 最初只是一个简单的构想:一只口袋宠物,它因 WiFi 活动而饥饿,而不是通过喂食按钮。它运行成功,但面部是精灵图,反应瞬间且略显呆板,而且没有配套的陪伴应用。
这一次,我只有一个目标:将它重新设计成真正有生命感的存在,同时要适应硬件上存在的实际限制。
TamaFi 实际是什么?
TamaFi 是一款安装在定制 ESP32-S3 板上的口袋宠物。它追踪六项数据:饥饿度、能量、快乐值、健康值、好奇心和舒适度,并将周围 WiFi 和蓝牙活动作为传感器输入。在本次构建中,这些数据仅用于读取,不进行传输,也不保存 SSID 或 MAC 地址。
它完全独立运行,无需任何应用程序。现在还附带了一个桌面版陪伴应用——TamaFi Lab,我将在下文详细介绍,包括开发过程中遇到的 USB 问题。
硬件配置
该电路板采用 ESP32-S3-WROOM-1 芯片运行。双核处理器,内置WiFi和蓝牙,原生USB接口。
这块电路板最重要的限制因素是内存。它没有可用的PSRAM,因此显示屏只能使用一个内存缓冲区,覆盖整个屏幕,尺寸为240×240像素。第二个缓冲区也无法分配,完全无法使用。
原始的TamaFi使用精灵图(sprite sheet)作为屏幕显示,通过预先制作好的位图进行切换。这种方式需要比本板更多的内存空间。因此,这个版本直接在代码中构建屏幕内容,每帧重新绘制,而不是加载存储的位图。正是由于这一内存限制,整个屏幕系统不得不被重新设计。
其余部分:
•显示屏:ST7789,240×240像素,SPI接口
•麦克风:INMP441,用于检测附近语音
•扬声器:MAX98357A放大器驱动真实扬声器,取代了旧的简易蜂鸣器。当可用内存过低时,声音会自动关闭
•运动感应:MPU6050加速度计与陀螺仪,支持倾斜、手势、震动、轻触、翻转等操作
•LED灯:四个WS2812可寻址RGB LED,用于状态反馈
•按钮:共六个,其中三个用于菜单选择,另外三个用于快速跳转至宠物状态、环境信息以及简短活动日志
•电源:单节锂电池通过TP4056充电控制器供电,经LF33稳压器降压至3.3V
•背光控制:SI2302 MOSFET,由固件控制切换
•连接性:USB-C接口用于充电和刷机
电路板上还配备了一个OV2640摄像头接口,通过24针FPC连接器连接,该摄像头与ESP32-CAM板相同。目前无法正常工作,原因并非固件跳过该接口。在Altium中搭建好库文件并按照摄像头文档操作后,设备仍无响应。经过数小时对硬件的调试,仔细检查原理图与实际OV2640模块对比后发现,连接器引脚排列顺序错误。这是电路板层面的错误,固件无法修复,因此该接口暂时未使用,直到后续版本修正连接器布局。此外,该摄像头的多个信号线与三个按钮共享了部分GPIO,即使引脚配置得到修正,摄像头和这些按钮也无法同时运行。
未来版本计划加入LDR光感传感器和电容式触摸引脚,但当前电路板上均未配备。
面部识别背后的“大脑”
原始TamaFi直接响应输入信号。WiFi数量增加,饥饿感降低。简单,但说实话,有点平淡。
这个版本优先考虑先行动。
年龄以分钟为单位追踪,并根据阶段判断生命状态:婴儿、青少年、成人、老年人。阶段变化会触发属性提升和特定动画。属性会随着时间自然衰减,设备还会周期性地在四种行为中随机选择:狩猎、探索、休息或闲置,采用加权概率而非固定规则。系统避免连续两次执行相同行为,且大约有五分之一的概率在决策中途改变主意,而不是立即执行。
搜索附近的Wi-Fi和蓝牙活动,并根据发现的内容调整饥饿感和情绪。发现功能专门用于寻找隐藏或开放的网络。休息模式为定时小睡,此时各项数据恢复,面部保持完全睡眠状态。
面部
首次开机时,设备会运行一个开启动画,随后面部开始活跃。此后每次启动都会直接跳过简短的介绍画面。
面部每一帧都从代码中实时绘制,不会加载任何预存的位图图像。每种情绪都会分阶段呈现:初始动作、主要表情、暂停状态,然后回到该情绪的休息状态。这种设计在旧的精灵系统中并不实用,因为每个情绪的每个阶段都需要单独的图像。
三种情绪与无线电活动密切相关:脱授权事件会触发一种类似漏洞的反应;大量探测请求会引发更警觉、快速闪动的表情;接近开放网络则会触发一种明显的警惕眼神。整个移动过程、眼睑变化、过渡和反应均采用弹簧式运动,而非固定的时间点动画。
读取房间
原始版本仅使用一个数值——Wi-Fi数量——作为整体环境输入。此版本根据Wi-Fi和蓝牙扫描结果,将周围无线电活动分为五种状态之一:平静、繁忙、开放、嘈杂或敌对。两种信号交替使用,以控制内存占用。
当检测到超过阈值的脱认证(deauth)或断开连接行为时,就会触发“敌对”状态。一旦触发,该状态会持续一段时间,舒适度与幸福感下降,界面切换为故障反应模式,并且该状态会优先于其他正在运行的活动。
所有这些功能在当前固件中均保持只读。
自原版以来的新内容
原版TamaFi中原本不存在以下两个系统。
成就系统:追踪了11个里程碑,包括首次连接、首次狩猎、首次休息、阶段变化、在敌对环境中存活、被麦克风探测、达到特定年龄阈值等。
事件日志:后台持续滚动记录活动、狩猎、休息以及重要无线电事件,并附带时间戳。
TamaFi实验室
原版计划开发一款桌面配套应用程序,但最终未能实现。此版本已包含该功能。
TamaFi Lab 可通过 USB 连接设备,并实时镜像显示设备的面部信息、状态、无线电读数、成就、日志、设置,甚至可以直接刷写新的固件。
要实现稳定的 USB 连接,需要付出大量努力。在 Windows 系统上,ESP32-S3 的 USB 实现开发过程中存在多个问题:
- 串行写入阻塞会导致超时
- 在连接期间切换某些控制线,可能意外将设备进入下载模式
- 打开 COM 端口会自动重置芯片,因此在短时间内重试连接会阻止设备完成启动流程
- USB CDC 启动默认处于禁用状态,若未启用该设置,串行输出会被静默地路由到其他位置
- 同一系统中的其他串行端口(包括蓝牙端口)可能干扰设备发现
- 同时运行多个 Lab 实例可能导致端口被完全锁定
上述大部分问题已得到解决:实现了非阻塞写入、避免了特定控制线的切换、优先检查正确的硬件端口,并限制 Lab 仅限单个实例运行。
但仍有其中一个问题尚未解决。成功连接后,状态请求有时仍可能超时,导致应用断开连接并尝试重新连接。这是已知问题,尚未解决。
故障排除
设备通过USB无响应:请确认USB CDC On Boot已启用且PSRAM已禁用,然后重新上传,并确保其他设备未占用该端口。
崩溃或显示问题:检查是否仍有PSRAM处于启用状态,或固件试图创建第二个面部缓冲区,而此板无法支持。
按钮行为异常:如果您修改了固件以开启摄像头接口,请注意,根据设计,三个按钮与摄像头信号线共享GPIO,此外还存在接口原有的引脚布局问题。
下一步
一旦引脚布局问题得到修复,摄像头接口将在未来的电路板版本中得到改进。这引发了一个实际问题:固件接下来的去向如何?
一个能正常工作的摄像头足以将其转变为小型AI代理平台,调用云端模型处理所见内容。它也足以直接在芯片上运行小型模型,无需API,无需网络。
计划是第二步。本地设备行为,而不是另一个项目将摄像头画面传送到他人服务器。
最终思考
TamaFi V2 是一款真正让人感觉像宠物而不是数据统计的版本。它拥有从零构建的脸部、先思考再行动的大脑,以及通过真正的 USB 调试才得以完善的配套应用。
相机仍然有故障,我并不隐瞒这一点。未来的新版本会修复这个问题。
本文编译自hackster.io





