公司动态

基于ESP32的哔哔小子手表:低功耗可穿戴设备的DIY实践

📅 2026/7/29 0:24:34
基于ESP32的哔哔小子手表:低功耗可穿戴设备的DIY实践
1. 项目缘起从游戏到现实的“哔哔小子”之梦如果你和我一样是《辐射》系列游戏的忠实粉丝那么对“哔哔小子”这个装备一定不会陌生。它不仅是游戏主角手腕上的多功能个人终端更是废土生存的象征集成了状态监控、地图导航、物品管理、电台广播等一系列功能其复古的绿色CRT显示风格和标志性的“哔哔”音效早已成为游戏文化的一部分。每次在游戏中打开哔哔小子界面那种沉浸感都让人着迷。于是一个念头自然而生能不能把这份来自虚拟废土的浪漫带到现实世界戴在自己的手腕上这就是“PiP Watch”哔哔小子手表项目的初衷。它不是一个简单的游戏周边而是一个融合了硬件DIY、嵌入式开发、UI设计和情怀的综合性创客项目。我们想复刻的不仅仅是那个绿色的界面更是那种将复杂信息集成于方寸之间的极客精神。市面上虽然有一些基于树莓派Zero或更高性能SBC单板计算机的哔哔小子手表方案但它们往往体积较大、功耗较高续航是硬伤。而我们的目标是打造一款更贴近“手表”形态能够日常佩戴、拥有不错续航的轻量化版本。经过一番选型DFRobot的Firebeetle ESP32-E进入了我的视野。这款板子集成了ESP32主控、锂电池充电管理、丰富的GPIO更重要的是它极其紧凑的尺寸和低功耗特性完美契合了可穿戴设备的需求。用ESP32来驱动一块小屏幕实现动态的哔哔小子界面并整合一些基础传感器这个想法让我跃跃欲试。2. 核心硬件选型与设计思路解析一个可穿戴项目硬件是骨架。选型不仅决定了功能上限更直接关系到成品的外观、佩戴舒适度和续航能力。我的核心思路是在有限的体积和功耗预算内最大化“哔哔小子”的感官体验。2.1 主控板为什么是Firebeetle ESP32-E在众多ESP32开发板中选择Firebeetle ESP32-E以下简称ESP32-E是基于以下几个关键考量极致的尺寸与集成度ESP32-E的PCB尺寸仅为25.4mm x 38.1mm比一张SD卡还小。它板载了CP2102 USB转串口芯片、锂电池充电管理电路最大充电电流500mA和3.3V稳压器。这意味着你不需要额外焊接任何模块只需接上电池和屏幕一个最小系统就搭建完成了极大简化了手表内部的堆叠设计。专为低功耗优化ESP32本身支持多种低功耗模式Deep Sleep, Light Sleep等。ESP32-E在设计上进一步考虑了功耗例如其AMS1117稳压器的静态电流较低。对于手表这类需要长时间待机的设备每一微安的电流都至关重要。实测中在深度睡眠模式下整机电流可以控制在10μA左右这意味着一块400mAh的电池纯待机时间可以长达数年。足够的性能与接口ESP32双核240MHz的主频驱动一块分辨率不高的TFT屏幕进行UI动画渲染绰绰有余。它拥有34个可用的GPIO虽然部分被板载功能占用如LED、按键但剩余引脚足够连接屏幕、传感器和震动马达。内置的Wi-Fi和蓝牙虽然在本项目中可能不是核心功能为了省电通常会关闭但为未来扩展如无线同步数据、接收通知留下了可能。良好的生态与社区支持DFRobot提供了完善的Arduino库支持并且其引脚布局清晰相关资料易于查找。这对于快速原型开发至关重要。注意ESP32-E有两个版本区别在于引脚引出方式。推荐使用“Firebeetle ESP32-E IoT MicrocontrollerV1.0”版本它的所有GPIO都以排针形式引出更便于连接外设。2.2 显示核心屏幕的抉择哔哔小子的灵魂在于那块绿色的屏幕。为了还原神韵屏幕选择需要满足尺寸适中1.3英寸到1.54英寸是手表比较合适的尺寸。圆形或方形更符合手表外观方形屏显示信息面积更大。驱动方式SPI接口屏幕是首选因为它占用引脚少通常只需4-6个驱动效率高对ESP32的GPIO压力小。色彩与风格虽然哔哔小子是单色绿但使用一块全彩屏如ST7789驱动可以通过软件模拟绿色调未来还能切换其他主题如琥珀色可玩性更高。我最终选择了一块1.54英寸的IPS TFT液晶屏驱动芯片为ST7789分辨率为240x240。理由如下240x240分辨率在这个尺寸下像素密度足够能显示比较细腻的字体和图标。IPS材质可视角度极佳无论从哪个方向看手表内容都清晰可见。SPI接口仅需占用ESP32的5个引脚SCK, MOSI, DC, CS, RST背光控制可以单独接一个PWM引脚实现亮度调节。有现成的Arduino库如TFT_eSPI库对ST7789支持非常好性能优化到位。2.3 能源与交互电池、充电与外壳电池选择一款3.7V、300-500mAh的锂聚合物电池。容量太小续航不足太大则增加体积和重量。电池需要配备标准的2.0mm间距PH2.0连接器以便与ESP32-E的电池接口对接。厚度最好在3-4mm左右便于放入表壳。充电ESP32-E板载了Micro USB接口用于编程和充电非常方便。你可以直接通过这个口为手表充电充电时板载的红色LED会亮起充满熄灭。交互与反馈按键除了ESP32-E板载的一个用户按键GPIO0我额外添加了两个轻触开关作为“选择”和“返回”键。这三个按键构成了最基础的人机交互。震动马达一个小型的扁平震动马达约3mm厚是必不可少的。它用于提供通知、闹钟和界面交互的触觉反馈。通过一个NPN三极管或MOSFET如2N2222或SI2302由ESP32的GPIO控制其开关。外壳这是让项目从“开发板堆叠”变成“手表”的关键。我使用Fusion 360进行3D建模设计。设计要点包括紧凑堆叠将ESP32-E主板、屏幕、电池、震动马达在三维空间内合理布局计算好所有连接线和排线的走线空间。人体工学表壳背面需要有一定弧度以贴合手腕表耳用于安装表带20mm通用生耳。按键开孔为三个按键预留孔位并设计合适的按键帽保证手感。屏幕保护设计一个窗口并考虑是否增加一层亚克力面板或钢化玻璃膜来保护屏幕。充电口开孔为Micro USB口开孔方便充电而不必打开后盖。我将设计好的模型用光固化3D打印机如Anycubic Photon打印出来以获得更精细的表面纹理和更准确的孔位。后期经过打磨、喷漆哑光黑或军绿色质感就上来了。3. 软件架构与核心功能实现硬件搭好了接下来就是注入灵魂的软件部分。整个软件系统围绕“低功耗”和“流畅的复古UI”两个核心目标构建。3.1 开发环境与核心库搭建我使用Arduino IDE进行开发因为它对ESP32和各类显示库的支持非常成熟。必须安装和配置的库ESP32 Board Support在Arduino IDE的 boards manager 中添加ESP32支持。TFT_eSPI这是驱动屏幕的核心库。需要手动配置其用户设置文件User_Setup.h。打开TFT_eSPI库文件夹下的User_Setup.h。根据你的屏幕型号注释掉其他驱动取消注释ST7789_DRIVER。正确设置TFT_WIDTH,TFT_HEIGHT, 以及你连接ESP32的引脚定义例如#define TFT_CS 15 // Chip select control pin #define TFT_DC 2 // Data Command control pin #define TFT_RST 4 // Reset pin (could connect to ESP32 RST) #define TFT_MOSI 23 // Data out #define TFT_SCLK 18 // Clock out设置SPI_FREQUENCY为4000000040MHz以获得更快的刷新速度。Button2一个优秀的按键库支持单击、双击、长按等事件检测能简化我们的按键逻辑。WiFi NTPClient用于时间同步可选开启时会增加功耗。PreferencesESP32的非易失性存储库用于保存手表设置如亮度、主题色等。3.2 低功耗策略设计对于手表不能让ESP32一直全速运行。我的策略是状态机设计将手表运行状态分为几个等级活跃状态屏幕亮起处理器全速运行响应所有操作。一段时间无操作后如30秒进入休眠状态。休眠状态关闭屏幕背光CPU降频或进入Light Sleep模式但保持对按键中断的监听。此时功耗在几毫安级别。深度睡眠状态在休眠状态持续一段时间后或由用户主动触发进入Deep Sleep。此时仅RTC模块和少数GPIO配置为EXT0唤醒保持极低功耗运行电流降至10μA级。通过按键连接至EN引脚或配置为EXT0唤醒的GPIO可以唤醒系统。中断唤醒将三个按键都连接到支持外部唤醒的GPIO如GPIO0, GPIO33等。在深度睡眠前配置其中某个按键如主页键为唤醒源。当按下该键时ESP32会从深度睡眠中复位重启程序从头开始执行并在初始化后立即显示主界面体验上就像“点亮屏幕”。外设电源管理在代码中进入休眠前主动将屏幕的背光引脚拉低并将屏幕置于睡眠模式。对于震动马达确保其控制引脚处于确定的高阻态或低电平防止误触发耗电。3.3 哔哔小子UI绘制与动画这是最有趣也最具挑战的部分。我们需要用代码“画”出那个熟悉的界面。字体与图形哔哔小子使用的是等宽字体。我找到了一个名为“Fixedsys”风格的像素字体将其转换为.vlw格式Arduino位图字体并使用TFT_eSPI的setFreeFont函数加载。对于小字号也可以使用库内置的等宽字体。界面上的图标、边框、辐射标志等可以先用电脑上的绘图工具如Aseprite绘制成单色或有限色的位图然后使用Img2Code之类的工具转换为C语言数组直接嵌入代码中通过drawBitmap函数绘制。界面框架设计一个简单的UI框架管理不同的“页面”App如主时钟页面、健康数据页面、设置页面等。每个页面是一个函数或一个类负责绘制自己的静态元素和更新动态数据。使用一个状态变量记录当前页面索引按键操作用于切换页面。动态效果与“绿噪点”页面切换动画可以模拟CRT的扫描线效果或简单的滑入滑出。在TFT_eSPI中可以通过分步重绘矩形区域来实现。绿噪点滤镜为了更逼真可以在绘制完一帧后在整个屏幕随机绘制一些半透明的绿色或黑色像素点模拟CRT的噪点。但要注意控制密度和频率避免影响主要信息阅读。滚动文字在信息栏模拟缓慢的横向滚动文字这是哔哔小子的经典元素。可以通过计算文字位置并定期重绘来实现。代码结构示例主循环#include TFT_eSPI.h #include Button2.h TFT_eSPI tft TFT_eSPI(); Button2 btnHome(0); // GPIO0 enum AppState { CLOCK, STATUS, SETTINGS }; AppState currentApp CLOCK; unsigned long lastActiveTime 0; const unsigned long SLEEP_TIMEOUT 30000; // 30秒无操作休眠 void drawClockApp() { // 绘制时钟界面绿色背景复古边框大号时间字体小号日期 tft.fillScreen(TFT_GREEN); // ... 绘制边框和装饰 ... // ... 获取并显示时间 ... } void drawStatusApp() { // 绘制状态界面模拟健康数据可连接心率传感器 tft.fillScreen(TFT_BLACK); // ... 绘制状态栏和虚拟数据 ... } void setup() { Serial.begin(115200); tft.init(); tft.setRotation(1); // 根据手表佩戴方向调整 tft.fillScreen(TFT_BLACK); btnHome.setPressedHandler([](Button2 b) { lastActiveTime millis(); // 重置活动计时器 wakeFromSleep(); // 唤醒函数点亮背光等 // 短按切换App长按进入深度睡眠 }); // 初始化其他外设... lastActiveTime millis(); } void loop() { btnHome.loop(); // 必须持续调用以检测按键 // 根据当前状态更新对应App的UI switch (currentApp) { case CLOCK: updateClock(); break; case STATUS: updateStatus(); break; // ... } // 检查休眠超时 if (millis() - lastActiveTime SLEEP_TIMEOUT) { enterLightSleep(); } // 添加少量延时控制刷新率节省功耗 delay(50); }4. 功能扩展与传感器集成基础的时间显示和UI复刻完成后可以为其添加一些“实用”功能让它更像一个真正的个人终端。4.1 环境传感器感知废土现实世界温湿度计使用一颗DHT11或更精确的SHT30传感器可以测量环境温湿度。在状态页面上显示这些信息甚至可以根据温度给出“辐射区高温警告”之类的趣味提示。气压计/高度计BMP280或BME280传感器可以测量气压和估算海拔。虽然精度有限但为手表增加了一层环境感知维度。连接方式这些传感器大多支持I2C接口。ESP32-E有多个GPIO支持I2C你可以将它们连接到同一组I2C总线GPIO21-SDA GPIO22-SCL上通过不同的设备地址来访问。4.2 生物传感器监测“幸存者”状态心率血氧MAX30102是一款集成了心率与血氧检测的传感器模块。虽然其算法相对复杂且对佩戴位置要求较高但集成后可以为“健康”页面提供真实的生物数据极大提升项目的科技感和可玩性。你需要处理其产生的原始光电容积脉搏波PPG数据或使用现成的算法库来估算心率和血氧饱和度。计步器ESP32本身内置了加速度计不它没有。你需要外接一个MPU6050或更便宜的LIS3DH三轴加速度计。通过分析加速度数据可以实现基本的步数统计功能。这需要编写或移植一些计步算法如峰值检测。4.3 无线功能与数据同步蓝牙通知让手表通过蓝牙低功耗BLE连接到你的手机接收来电、短信或App通知。这需要编写一个BLE客户端角色Peripheral的程序并开发一个手机端App或利用现成的开源项目如BLE Notify来转发通知。当收到通知时手表屏幕点亮、震动并显示通知摘要。Wi-Fi时间同步在手表连接充电器或手动触发时可以开启Wi-Fi连接到预设网络使用NTP协议从互联网同步精确时间。同步完成后立即关闭Wi-Fi以省电。实操心得功能扩展要循序渐进。建议先完成核心的显示和基础交互稳定后再逐一添加传感器。每添加一个外设都要重新评估功耗和代码复杂度。I2C总线上的设备多了要注意上拉电阻的阻值通常4.7kΩ并处理好地址冲突。生物传感器的数据滤波和算法是难点初期可以先用厂家提供的示例代码获取数据显示出来就算成功后续再优化准确性。5. 电源管理、续航测试与优化实战“能不能用一整天”这是可穿戴设备的终极拷问。我们需要对整机功耗进行量化分析和优化。5.1 各状态功耗测量你需要一个万用表电流档或更专业的功耗分析仪。将设备串联在电池供电回路中测量不同工作状态下的平均电流。工作状态屏幕背光ESP32模式外设状态预估平均电流续航估算 (400mAh)深度睡眠关闭Deep Sleep仅唤醒电路~10 μA约4.5年(理论值)休眠 (屏熄)关闭Light Sleep / CPU降频按键监听开启~2 mA约8天活跃 (低亮度)50% PWM全速 (80MHz)传感器采样UI刷新~60 mA约6.5小时活跃 (高亮度)100%全速 (240MHz)BLE广播频繁刷新~120 mA约3小时表1基于典型配置的功耗估算实际值因具体元件和代码效率而异5.2 关键优化措施根据上表提升续航的核心在于尽可能让设备处于深度睡眠或低功耗休眠状态。屏幕背光是耗电大户这是最有效的优化点。将背光控制引脚连接到ESP32的PWM输出引脚如GPIO12。在代码中设置一个较低的默认亮度例如30%并提供设置菜单让用户调整。实现自动亮度调节虽然成本略高但可以增加一个环境光传感器如BH1750根据环境光线自动调整背光PWM值在暗处大幅降低亮度。优化CPU工作模式在活跃状态下如果不进行复杂计算如动画渲染可以将CPU频率从240MHz降至80MHz使用setCpuFrequencyMhz(80)能显著降低功耗。在loop()循环中如果没有紧急任务使用delay()或vTaskDelay()让CPU有机会进入IDLE状态而不是忙等待。外设精细化管理传感器不要持续采样。例如温度每分钟读取一次即可。在两次读取之间通过GPIO控制其电源或将其置于睡眠模式。震动马达震动时间要短通常100-200ms足矣驱动后立即关闭控制引脚。无线模块Wi-Fi和蓝牙在不需要时彻底关闭。连接成功后立即断开并关闭射频。避免让设备处于持续的广播或扫描状态。软件逻辑优化减少屏幕刷新只刷新需要变化的区域局部刷新而不是整个屏幕全屏刷新。TFT_eSPI库的setAddrWindow和pushColor函数支持局部更新。使用更高效的图形绘制预计算并存储常用的界面元素避免在循环中重复计算坐标和颜色。5.3 续航实测与调整搭建一个初步的原型后进行24小时续航测试。记录设备在不同使用强度下的实际耗电量。根据测试结果回头调整你的休眠超时时间、默认亮度、传感器采样频率等参数。一个理想的目标是在每天查看时间、通知数十次的中度使用下能够坚持2-3天以上的续航这会让佩戴体验好很多。6. 外壳制作、组装与最终调试当所有代码功能稳定功耗也达到满意水平后就可以进行最终组装了。6.1 3D打印与后处理打印参数使用光固化树脂打印层高选择0.05mm或0.03mm以获得光滑表面。表壳通常需要拆分打印前盖、后盖注意设计好卡扣或螺丝柱。清洗与固化打印完成后用酒精彻底清洗模型去除残留树脂然后放入UV固化箱进行二次固化使其达到最大强度。打磨与上色用细砂纸如800目、1000目打磨掉支撑残留和层纹。喷涂水补土检查并填补可能存在的瑕疵。选择哑光黑、军绿色或做旧的银色进行喷涂。可以尝试渍洗或干扫等模型技法做出废土风格的磨损效果。最后喷涂一层哑光保护漆增加耐用性。6.2 内部组装“排雷”这是最容易出问题的环节需要耐心和细心。焊接与连线使用细的硅胶线或FFC排线进行内部连接它们更柔软便于在狭小空间内弯曲。为所有连接点点上热熔胶或使用Kapton胶带固定防止在佩戴过程中因晃动导致脱焊或短路。特别注意电池的正负极绝对不能短路在焊接电池线时最后连接正极或者使用带保护板的电池。堆叠顺序通常的顺序是后盖 - 电池粘贴在后盖内 - 主板用尼龙柱垫高 - 屏幕通过排线连接 - 前盖。在主板和电池、屏幕之间可以贴一层绝缘胶带或麦拉片防止刮擦短路。确保所有排线都有足够的弯曲空间不会被外壳挤压。按键与密封轻触开关的按键帽需要精心调整长度确保能从外壳内部正好顶到外壳的按键孔手感清脆。如果希望有一定的防水防尘能力可以在屏幕与前盖、前后盖接合处使用薄泡棉胶条或橡胶密封圈。充电口可以使用硅胶防尘塞。6.3 最终上电与综合测试组装完成后不要急于拧紧所有螺丝。先连接电池进行上电测试基本功能测试按键能否正常唤醒、操作屏幕显示是否正常背光能否调节充电测试连接USB线检查充电指示灯是否正常测量电池电压是否在上升。功耗复测再次测量组装后的整机在睡眠和活跃状态下的电流与之前裸板测试对比看是否有异常漏电。压力测试连续运行几个小时频繁操作观察是否有死机、重启、发热异常等情况。佩戴体验装上表带实际佩戴感受重量、厚度是否合适表冠是否硌手。一切正常后就可以拧紧螺丝你的专属废土风格哔哔小子手表就正式诞生了。这个项目从构思到实现充满了硬件选型的权衡、代码调试的枯燥和最终点亮屏幕那一刻的喜悦。它不仅仅是一个手表更是一个承载着游戏情怀和个人技术探索的实体作品。当你抬起手腕看到那抹熟悉的绿色荧光亮起耳边仿佛响起了避难所熟悉的广播声那一刻所有的努力都值了。