
1. 从一块圆形屏幕说起Eye Pendant V2 到底在做什么第一次看到 Eye Pendant V2 这个名字很多人会以为是个普通的挂坠装饰品。但如果你拆开来看它本质上是一个基于 ESP32-S3 的圆形 TFT 屏幕可穿戴设备核心玩法是在一块小尺寸圆形屏幕上渲染一只会动、会眨眼、会跟随状态变化的眼睛。V2 这个版本号说明它不是第一版而是经过迭代的产物——通常意味着第一版在硬件选型、屏幕驱动或者功耗上踩过坑第二版做了针对性修正。这类项目的吸引力在于它把几个看起来不相关的领域缝在了一起嵌入式硬件ESP32-S3 主控、图形渲染TFT_eSPI 驱动库、结构设计挂坠外壳、以及交互逻辑眼睛的状态机。它适合谁适合已经玩过 Arduino 基础例程、想找一个有视觉反馈、能戴在身上、又不至于太复杂的进阶练手项目的人。也适合做礼物、做展会小挂件、做桌面摆件的朋友。关键词里出现了Tinkercad这是个信号项目大概率包含 3D 建模环节外壳、边框、挂绳孔这些结构件是用 Tinkercad 这类在线工具画的然后 3D 打印出来。而Arduino IDE和TFT_eSPI则锁定了软件栈——用 Arduino 生态开发 ESP32-S3用 TFT_eSPI 这个老牌库驱动屏幕。热搜词里那一堆 arduino ide esp32离线包、arduino ide 启动时一直等待、mac arduino ide 说明很多人卡在了环境搭建这一步这恰恰是这类项目最劝退的环节也是我后面要重点拆的部分。所以这篇内容我会按真实做一遍的顺序来讲先搞清楚硬件怎么选、为什么这么选再解决 Arduino IDE 配 ESP32-S3 的各种坑然后讲 TFT_eSPI 的配置逻辑这个库的配置是新手最大的拦路虎接着是眼睛动画的实现思路最后是 Tinkercad 建模和组装。中间会穿插我自己踩过的坑和实测数据。2. 硬件选型为什么是 ESP32-S3 加圆形 TFT2.1 主控为什么锁定 ESP32-S3市面上能驱动 TFT 屏幕的单片机很多STM32、RP2040、ESP32 系列都能干。选 ESP32-S3 有几个很实际的理由。第一是算力和内存ESP32-S3 是双核 Xtensa LX7主频能到 240MHz自带 512KB SRAM还支持外挂 PSRAM。渲染眼睛动画需要频繁地往屏幕刷像素如果主控太弱帧率会掉到个位数眼睛看起来就是一顿一顿的。第二是价格和生态一块 ESP32-S3 开发板比如常见的 DevKitC 或者带屏的小板价格通常在二三十块人民币Arduino 生态支持成熟库多、教程多。第三是外设接口S3 的 SPI 控制器性能足够喂饱小尺寸 TFT而且 GPIO 数量够用接屏幕、接电池检测、接按键都不紧张。对比一下 RP2040RP2040 也很强双核 133MHz但它的 Arduino 支持在某些 TFT 库上不如 ESP32 顺滑尤其是 TFT_eSPI 对 ESP32 的优化是官方级别的。STM32 的话性能没问题但开发环境Keil、CubeMX对新手不如 Arduino IDE 友好而且成本通常更高。所以综合下来ESP32-S3 是这类小屏幕 动画 可穿戴项目的甜点区选择。2.2 圆形 TFT 屏幕的规格与驱动芯片Eye Pendant 用的是圆形屏常见尺寸是1.28 寸、1.38 寸、1.69 寸这几种。1.28 寸圆屏分辨率一般是 240x240驱动芯片多为 GC9A011.69 寸的可能是 240x280 的圆角矩形驱动芯片常见 ST7789。这里有个关键点驱动芯片决定了 TFT_eSPI 的配置配错了屏幕要么不亮要么花屏。我实测下来GC9A01 的 1.28 寸圆屏是这类项目最常用的因为它是真正的正圆形240x240 的分辨率对眼睛动画来说够用——眼睛占屏幕中间大概 180x180 的区域留出边缘做装饰。屏幕接口一般是 SPI需要接的线有SCLK、MOSI、CS、DC、RST有的还有 BLK背光控制。如果你买的是带 FPC 排线的裸屏还需要一个转接板把排线转成 2.54mm 排针否则没法直接插面包板。注意买屏的时候一定要确认驱动芯片型号别只看尺寸。同样是 1.28 寸圆屏有的用 GC9A01有的用 ST7789V配置完全不同。卖家页面通常会写没写就问客服。2.3 供电与可穿戴的取舍既然是挂坠供电就不能太笨重。常见方案是小容量锂聚合物电池比如 3.7V 150mAh 到 300mAh 的软包电池体积小、能塞进挂坠壳里。ESP32-S3 工作电压是 3.3V所以需要一路 LDO 或者 DC-DC 降压。这里有个坑ESP32-S3 在 WiFi 开启时峰值电流能到 300mA 以上但眼睛动画这个场景其实不需要 WiFi关掉射频后电流能降到几十毫安150mAh 电池撑几个小时没问题。如果你想让挂坠续航更久可以在代码里做动态帧率眼睛静止时降到 10fps眨眼或状态切换时升到 30fps。这个技巧后面讲代码时会展开。另外充电管理建议用 TP4056 这类成熟模块带过充过放保护别直接拿电池怼 USB容易出事。3. Arduino IDE 配 ESP32-S3那些让人抓狂的等待与离线包3.1 为什么启动时一直等待是高频问题热搜词里 arduino ide 启动时一直等待 出现频率很高这不是偶然。Arduino IDE 启动时会做几件事检查更新、加载已安装的板卡包索引、初始化串口列表。如果你装了 ESP32 板卡包IDE 启动时可能会去拉取在线索引网络一慢就卡在启动画面。解决办法有几个一是断网启动看是否能快速进入二是清理Arduino15目录下的缓存三是直接换用离线包安装板卡支持。离线包的做法是去 Espressif 的官方发布页下载esp32-x.x.x.zip这类离线包然后在 Arduino IDE 的首选项里把附加开发板管理器网址填上本地文件路径或者用从 ZIP 安装。这样就不依赖在线索引了。实测下来离线包安装比在线安装快得多而且不会因为网络波动失败。3.2 Mac 用户的额外注意事项mac arduino ide 这个热搜词说明 Mac 用户也不少。Mac 上装 ESP32 支持有两个额外坑第一是串口驱动CH340 和 CP2102 这两种 USB 转串口芯片在 Mac 上可能需要单独装驱动尤其是新版 macOS 对未签名驱动限制严格。第二是权限问题Mac 上访问串口设备可能需要给终端或者 IDE 授权。如果你在 Mac 上上传代码时报 port not found 或者 permission denied先检查驱动再检查/dev/cu.*下有没有对应设备。另外 Mac 的 Arduino IDE 有两个版本老的 Java 版1.8.x和新的 2.x 版。2.x 版界面现代但插件生态还在完善1.8.x 更稳。做 ESP32 项目我建议先用 1.8.x等 2.x 的板卡支持更成熟再迁移。3.3 板卡配置的完整清单装好 ESP32 支持后在工具菜单里要选对参数这些参数直接影响能不能跑起来配置项推荐值说明开发板ESP32S3 Dev Module对应 DevKitC 类板子USB CDC On BootEnabled让串口走 USB方便调试Flash Size4MB (32Mb)按实际板子选选大了会报错PSRAMOPI PSRAM 或 QSPI PSRAM按板子实际选选错会启动失败Partition SchemeDefault 4MB with spiffs常规够用Upload Speed921600快但线差的话降到 115200USB ModeHardware CDC and JTAG常规调试用这里最容易错的是PSRAM 选项。有些 ESP32-S3 板子带 PSRAM有些不带选错了要么编译过但运行崩要么直接不启动。如果你不确定板子有没有 PSRAM先选 Disabled 试能跑就说明不需要。提示上传时如果一直卡在 Connecting...按住板子上的 BOOT 键再点上传等出现 Writing 再松开。这是 ESP32 系列手动进下载模式的通用手法。4. TFT_eSPI 配置一个 User_Setup.h 决定生死4.1 这个库为什么让新手崩溃TFT_eSPI 是 Bodmer 大神写的库性能极好但它有个反人类的设计所有配置都写在一个头文件User_Setup.h里而不是通过构造函数传参。这意味着你改配置要直接编辑库文件而且这个文件在库目录里升级库的时候可能被覆盖。很多人第一次用屏幕不亮就是因为没改这个文件或者改错了地方。正确的做法是找到 Arduino 库目录下的TFT_eSPI/User_Setup.h把里面关于驱动芯片、引脚、SPI 频率的宏定义改成你实际的硬件配置。或者更优雅的做法是用User_Setup_Select.h来 include 一个自定义的 setup 文件这样升级库不会丢配置。4.2 GC9A01 圆屏的配置模板以 1.28 寸 GC9A01 圆屏、接在 ESP32-S3 默认 SPI 引脚为例User_Setup.h里关键几行是这样#define GC9A01_DRIVER #define TFT_WIDTH 240 #define TFT_HEIGHT 240 #define TFT_MOSI 11 #define TFT_SCLK 12 #define TFT_CS 10 #define TFT_DC 9 #define TFT_RST 8 #define TFT_BL 7 #define LOAD_GLCD #define LOAD_FONT2 #define LOAD_FONT4 #define LOAD_GFXFF #define SMOOTH_FONT #define SPI_FREQUENCY 40000000这里每个参数都有讲究。GC9A01_DRIVER是驱动芯片宏选错就花屏。引脚要和你实际接线一致ESP32-S3 的 SPI 引脚可以自定义但建议用默认的 IO11/IO12 这组性能最稳。SPI_FREQUENCY设 40MHz 是 GC9A01 的常见上限设太高会花屏设太低刷新慢。如果你屏幕有噪点或者闪烁先把频率降到 27MHz 试试。4.3 背光控制与省电TFT_BL这个引脚控制背光。如果你直接接 3.3V背光常亮省不了电。正确做法是接到一个 GPIO用analogWrite或者ledcWrite做 PWM 调光。眼睛动画在睡眠状态时可以把背光调到 10%既省电又有氛围感。ESP32-S3 的 LEDC 外设支持多通道 PWM用起来很方便ledcSetup(0, 5000, 8); ledcAttachPin(TFT_BL, 0); ledcWrite(0, 128); // 50% 亮度实测下来背光从 100% 降到 30%整体功耗能降 20mA 左右对 150mAh 电池来说就是多撑半小时。5. 眼睛动画的实现状态机加局部刷新5.1 眼睛的视觉构成拆解一只会动的眼睛看起来复杂拆开其实就几个元素眼白背景圆、虹膜彩色圆、瞳孔黑色圆、高光小白点、眼睑上下两条弧线。眨眼就是眼睑快速闭合再打开眼球转动就是虹膜和瞳孔整体偏移情绪变化就是虹膜颜色和眼睑开合度的组合。在 240x240 的屏幕上眼睛主体画在中心 180x180 的区域内。用 TFT_eSPI 的fillCircle画眼白和虹膜fillCircle画瞳孔fillCircle画高光。眼睑用fillRect或者fillArc来画覆盖在眼睛上方模拟闭合。5.2 为什么必须用局部刷新全屏刷新 240x240 是 57600 个像素按 16 位色算就是 115KB 的数据量。SPI 40MHz 下理论传输时间约 23ms加上绘制时间全屏刷新一次大概 30-40ms也就是 25-30fps。听起来还行但问题是眼睛大部分区域是不变的每次都全刷太浪费。TFT_eSPI 提供了Sprite精灵机制先在内存里创建一个离屏画布在画布上绘制然后只把变化的区域推送到屏幕。对于眼睛动画可以创建一个 180x180 的 Sprite每帧只重绘虹膜和瞳孔区域然后pushSprite时指定脏矩形。实测这样能把帧率提到 50fps 以上而且功耗更低。TFT_eSprite eyeSprite TFT_eSprite(tft); eyeSprite.createSprite(180, 180); // 绘制... eyeSprite.pushSprite(30, 30);注意Sprite 会占用内存180x180x2 字节 64.8KB。ESP32-S3 有 512KB SRAM够用但如果你还开了 WiFi 和蓝牙内存会紧张。必要时用 PSRAM 存 Sprite。5.3 眨眼与眼球运动的状态机眼睛的行为用一个简单的状态机管理就够了。状态包括IDLE静止、BLINK眨眼、LOOK转动、SLEEP睡眠。每个状态有持续时间和转移条件。比如 IDLE 随机持续 2-5 秒然后有 30% 概率进入 BLINK20% 概率进入 LOOK其余继续 IDLE。眨眼动画用缓动函数做才自然。线性闭合看起来像机械眼用easeInOutQuad这种缓动眼睑先慢后快再慢就像真人眨眼。眼球转动也是目标位置随机生成然后用插值慢慢移过去别瞬移。float easeInOutQuad(float t) { return t 0.5 ? 2*t*t : 1 - pow(-2*t2, 2)/2; }这套逻辑跑下来眼睛看起来就有生命感了。我试过纯随机眨眼和带缓动的眨眼后者明显更像活物。6. Tinkercad 建模与外壳组装6.1 为什么用 Tinkercad 而不是 Fusion 360Tinkercad 是浏览器里的免费 3D 建模工具拖拽式操作学习曲线几乎为零。对于挂坠外壳这种一个圆壳 一个屏幕开孔 一个挂绳孔的简单结构Tinkercad 完全够用而且不用装软件打开网页就能画。Fusion 360 功能强但重对只想做个壳的人来说是杀鸡用牛刀。外壳设计的关键尺寸内径要比屏幕 PCB 大 0.5mm留出装配余量屏幕开孔直径要比可视区小 1mm遮住屏幕边缘的黑边壁厚 1.5-2mm太薄容易断太厚浪费材料。挂绳孔直径 3mm位置在顶部正中。6.2 打印参数与后处理3D 打印用 PLA 就行层高 0.2mm填充 20%壁厚 3 层。如果外壳有悬空结构比如挂绳孔上方需要开支撑。打印完用砂纸打磨一下边缘尤其是屏幕开孔处毛刺会刮手。组装顺序是先把屏幕用双面胶或者热熔胶固定在前壳然后接好排线把电池和主控塞进后壳最后前后壳用螺丝或者卡扣合上。这里有个经验排线要留够长度别绷太紧否则合壳的时候容易扯断。我第一版就是排线太短合壳时把 FPC 扯裂了屏幕直接报废。6.3 佩戴与日常使用挂坠用挂绳或者钥匙扣挂在包上、脖子上都行。日常使用要注意防水——3D 打印的壳不防水洗手、下雨要摘下来。电池如果长期不用保持 50% 电量存放别满电或者空电放对锂电寿命好。7. 实测中的几个坑与排查思路7.1 屏幕不亮的三层排查屏幕不亮是最常见的问题按这个顺序查第一层供电——量一下屏幕 VCC 有没有 3.3V背光引脚有没有电压。第二层接线——SPI 的 MOSI 和 SCLK 有没有接反CS 和 DC 有没有接对。第三层配置——User_Setup.h里的驱动宏和引脚对不对。我遇到过最隐蔽的一次是 CS 引脚虚焊万用表量着通但一上电就接触不良折腾了半天才发现。7.2 花屏与颜色错乱的根因花屏通常是 SPI 频率太高或者驱动宏选错。颜色错乱比如红色显示成蓝色是RGB/BGR 顺序问题TFT_eSPI 里有个TFT_RGB_ORDER宏改成TFT_BGR或者反过来试试。还有一种是屏幕初始化序列不对GC9A01 和 ST7789 的初始化命令不同用错驱动宏就会花屏。7.3 上传失败与串口占用上传失败最常见的原因是串口被占用——你可能开着串口监视器或者另一个 IDE 窗口占着端口。关掉监视器再上传。如果还不行检查板子有没有进下载模式手动按 BOOT 键。Mac 上还要注意有没有其他程序比如某些串口工具占着/dev/cu.usbserial-*。8. 后续可以怎么玩眼睛动画跑通之后这个项目还有很多扩展方向。可以加陀螺仪比如 MPU6050让眼睛跟着挂坠的倾斜方向看转头的时候眼睛也跟着转互动感很强。可以加麦克风检测到声音时眼睛看过来像在回应你。还可以做多只眼睛用一块大点的屏或者多块屏拼一个多眼装置做艺术摆件。软件层面可以把眼睛的表情做成配置文件用 JSON 定义不同情绪的虹膜颜色、眨眼频率、瞳孔大小然后通过串口或者蓝牙切换。这样不用重新编译就能换性格。我试过给眼睛加了困倦模式——眨眼变慢、瞳孔缩小、背光变暗放在桌上当夜灯挺有意思。功耗优化也还有空间。ESP32-S3 支持light sleep眼睛静止时可以进轻睡眠靠定时器或者外部中断唤醒。实测 light sleep 下电流能降到 2mA 左右150mAh 电池理论能撑几十小时。不过唤醒有延迟眨眼这种快速响应可能会卡需要权衡。最后说个组装上的小技巧如果你想让挂坠看起来更精致可以在外壳表面喷一层哑光漆或者在屏幕周围加一圈导光条用几颗贴片 LED 做氛围光。这些不影响核心功能但成品质感会提升一个档次。