1. 项目概述
1.1 设计目标与定位
本项目是一款面向桌面场景的低功耗墨水屏信息终端,核心目标是提供一种兼具实用性、可玩性与工程完整性的嵌入式人机交互方案。区别于传统LCD或OLED显示设备,墨水屏凭借其双稳态特性、零功耗静态显示能力及类纸观感,在长时间驻留型信息展示场景中具有不可替代的优势。项目聚焦于解决三个关键工程问题:
- 多尺寸墨水屏硬件兼容性:在保留2.9英寸HINK-E029A01成熟驱动方案基础上,完成对1.54英寸HINK-E154A05的硬件适配与软件驱动重构;
- 电池供电系统集成:构建具备双向电源路径管理能力的锂电池供电架构,支持USB充电与升压供电无缝切换;
- 离线-在线混合工作模式:在有限Flash资源约束下,实现WiFi配网、NTP时间同步、天气/古诗API数据获取、本地缓存与离线回退机制的完整闭环。
项目定位于中级嵌入式开发者实践平台,兼顾学习价值与实际可用性。所有设计决策均以可复现性、电路简洁性与固件可维护性为优先考量,未引入专用协处理器、外部RTC或高精度传感器等非必要组件,符合“用最少器件达成核心功能”的硬件设计哲学。
1.2 系统架构
整体系统采用主从式分层架构(见图1),由ESP32C3 SoC作为中央控制器统一调度各子系统:
┌─────────────────────────────────────────────────────┐ │ ESP32C3 主控模块 │ │ ┌───────────┐ ┌───────────┐ ┌──────────────┐ │ │ │ WiFi/UDP │ │ HTTPClient│ │ EEPROM/Flash │ │ │ │ (联网) │ │ (API请求) │ │ (配置存储) │ │ │ └───────────┘ └───────────┘ └──────────────┘ │ │ ▲ ▲ ▲ │ │ │ │ │ │ │ ┌────────────────────────────────────────────────┐ │ │ │ GxEPD2 + U8g2 显示子系统 │ │ │ │ ┌────────────┐ ┌──────────────────────────┐ │ │ │ │ │ 墨水屏驱动 │ │ 中文字库(GB2312) + 图片数据 │ │ │ │ │ │ (SPI接口) │ │ (编译时固化至Flash) │ │ │ │ │ └────────────┘ └──────────────────────────┘ │ │ │ └────────────────────────────────────────────────┘ │ │ ▲ │ │ │ │ │ ┌────────────────────────────────────────────────┐ │ │ │ ETA6093 电源管理子系统 │ │ │ │ ┌────────────┐ ┌──────────────────────────┐ │ │ │ │ │ 锂电池充放 │ │ USB供电检测 + 升压输出控制 │ │ │ │ │ │ 电管理 │ │ (5V/1.2A) │ │ │ │ │ └────────────┘ └──────────────────────────┘ │ │ │ └────────────────────────────────────────────────┘ │ │ ▲ │ │ │ │ │ ┌────────────────────────────────────────────────┐ │ │ │ 用户输入子系统 │ │ │ │ ┌────────────┐ ┌──────────────────────────┐ │ │ │ │ │ MODE按键 │ │ KEEP按键 + 拨动开关(电源) │ │ │ │ │ │ (模式切换) │ │ (系统启停) │ │ │ │ │ └────────────┘ └──────────────────────────┘ │ │ │ └────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────┘该架构体现典型的嵌入式系统分层思想:底层硬件抽象层(HAL)封装SPI/I2C/ADC等外设操作;中间件层(Middleware)处理网络协议栈、JSON解析、字体渲染等通用服务;应用层(Application)实现具体业务逻辑(时钟、天气、古诗、图片四模式轮询)。各层间通过明确定义的接口通信,降低耦合度,便于后续功能扩展与调试。
2. 硬件设计详解
2.1 墨水屏接口与驱动电路
项目适配两种规格墨水屏:2.9英寸HINK-E029A01与1.54英寸HINK-E154A05。二者均为ED029TC2/ED015TC2系列黑白双色墨水屏模组,采用24-pin FPC连接器,电气特性高度一致,主要差异在于分辨率(296×128 vs 200×200)与物理尺寸。这种一致性是实现单套驱动代码兼容多屏的基础。
2.1.1 接口定义与信号完整性
墨水屏通过标准SPI总线与ESP32C3通信,关键信号定义如下表:
| 信号名 | ESP32C3引脚 | 功能说明 | 设计要点 |
|---|---|---|---|
| BUSY | GPIO6 | 屏幕忙状态指示 | 开漏输出,上拉至3.3V,用于同步局部刷新时序 |
| RST | GPIO7 | 复位信号 | 低电平有效,需保持≥10μs,上电后延时复位 |
| DC | GPIO8 | 数据/命令选择 | 高电平为数据,低电平为命令,驱动GxEPD2库内部状态机 |
| CS | GPIO9 | 片选信号 | 低电平选通,SPI总线共享时需严格隔离 |
| SCLK | GPIO2 | SPI时钟 | 最高支持10MHz,实际配置为4MHz以兼顾稳定性 |
| MOSI | GPIO3 | 主机输出从机输入 | 信号完整性关键,PCB走线长度<8cm,避开高频干扰源 |
| VCC | 3.3V | 逻辑供电 | 经LDO稳压,纹波<20mVpp |
| VDDH | 3.3V | 高压驱动供电 | 由内部DC-DC升压生成,需独立滤波电容 |
注:引脚分配依据合宙ESP32C3开发板邮票孔布局确定,SCLK/MOSI/CS/DC/RST/BUSY全部映射至GPIO2~GPIO9连续引脚,便于PCB布线优化。
2.1.2 局部刷新实现原理
墨水屏刷新分为全刷(Full Update)与局刷(Partial Update)两类。全刷需清除残影但耗时长(约2s),局刷仅更新变化区域但易产生残影累积。本项目在Config.h中定义:
#define PARTIAL_UPDATE_ENABLE true #define REFRESH_INTERVAL_MS 30000 // 局刷间隔30秒GxEPD2库通过display.partialRefresh()触发局刷,其本质是向墨水屏IC发送特定命令序列(如0x92Partial In),配合精确的坐标窗口设置(display.setPartialWindow(x, y, w, h))。工程实践中发现:局刷必须配合周期性全刷(每2小时一次)以消除残影,否则连续运行一周后显示质量显著下降。
2.2 主控模块:ESP32C3最小系统
采用合宙ESP32C3开发板作为核心控制器,其优势在于:
- 集成2.4GHz WiFi 4 (802.11b/g/n),满足物联网数据回传需求;
- RISC-V 32位双核处理器(主频160MHz),运算能力足以支撑JSON解析与图像渲染;
- 内置512KB SRAM + 4MB Flash,为Arduino环境提供充足资源;
- 支持USB-JTAG调试与UART下载,简化开发流程。
2.2.1 邮票孔焊接工艺
开发板采用邮票孔(Stamp-hole)设计,将整个模块视为SMT贴片元件直接焊接于定制PCB。此设计带来三重收益:
- 空间极致压缩:省去杜邦线连接与转接板,整机厚度控制在12mm内;
- 电气性能提升:SPI总线走线长度缩短60%,信号反射与串扰显著降低;
- 量产可行性增强:支持回流焊批量生产,避免手工焊接导致的接触不良。
PCB设计时需注意:邮票孔焊盘尺寸按0.8mm直径设计,周围预留2mm禁布区防止锡珠短路;开发板底部无器件区域需开窗,确保回流焊热传导均匀。
2.3 电源管理电路:ETA6093双向路径设计
电源系统是本项目工程化落地的关键突破点。采用ETA6093作为主控PMIC,其核心价值在于单芯片实现“充电+升压+路径管理”三合一功能,替代传统方案中充电IC(如TP4056)+升压IC(如MT3608)+电源选择开关(如TPS2113A)的组合。
2.3.1 ETA6093工作模式分析
ETA6093通过内部MOSFET阵列与智能检测电路实现三种工作模式自动切换:
| 模式 | USB状态 | 电池状态 | 工作状态 | 输出电压/电流 |
|---|---|---|---|---|
| 充电模式 | 连接 | 电压<4.2V | USB→电池充电 | 电池端:1.2A恒流,4.2V恒压 |
| 升压模式 | 断开 | 电压>3.0V | 电池→5V升压 | VOUT:5.0V±2%,1.2A |
| 直通模式 | 连接 | 电压>4.0V | USB→系统直供 | VOUT:USB电压-0.3V |
关键设计细节:
- 输入端TVS二极管(SMAJ5.0A)抑制USB浪涌;
- 升压电感选用CDRH5D28NP-100NC(10μH/1.8A),饱和电流余量>50%;
- 电池检测电阻Rsense=0.1Ω,配合ETA6093内部ADC实现电量估算;
- 蓝色LED(开机指示)与绿色LED(充电指示)共用GPIO10,通过PWM调光避免额外驱动电路。
2.3.2 锂电池选型与功耗实测
选用301048规格锂聚合物电池(3.7V/150mAh),体积仅1.44cm³,完美匹配桌面摆件轻薄化需求。实测功耗数据如下:
| 工作状态 | 平均电流 | 待机时长 | 备注 |
|---|---|---|---|
| USB供电(屏幕刷新) | 45mA | — | 无电池参与 |
| 电池供电(局刷循环) | 28mA | ≈5.3小时 | 刷新间隔30s,每次局刷耗电120mC |
| 电池供电(深度睡眠) | 85μA | ≈78天 | 未启用,需修改ESP32C3睡眠配置 |
工程警示:原始设计未启用ESP32C3的Deep Sleep模式,因GxEPD2库暂不支持唤醒后屏幕状态恢复。若需延长续航,须在
loop()中插入esp_sleep_enable_timer_wakeup(30*1000000); esp_light_sleep_start();,并在唤醒后执行完整屏幕初始化。
2.4 用户交互电路
交互系统由三级物理输入构成:
| 输入类型 | 电路实现 | 工程考量 |
|---|---|---|
| 电源开关 | 拨动开关(SPDT)串联于ETA6093 VIN输入 | 避免软件关机导致的后台功耗,真正切断系统供电 |
| MODE键 | 轻触开关(常开)接GPIO0,下拉电阻10kΩ | GPIO0同时作为下载模式检测引脚,需确保按键释放时电平稳定 |
| KEEP键 | 轻触开关(常开)接GPIO1,下拉电阻10kΩ | 与MODE键组成组合键逻辑(长按MODE进入配网) |
按键消抖采用硬件+软件双重策略:PCB层面添加0.1μF陶瓷电容滤波;固件中使用millis()计时实现15ms软件消抖,避免delay()阻塞主循环。
3. 软件系统设计
3.1 开发环境与引脚映射
基于Arduino框架开发,需安装ESP32 Arduino Core v2.0.0及以上版本。关键引脚重定义位于variants/esp32c3/pins_arduino.h:
// 修改前(默认SPI引脚) static const uint8_t SS = 13; static const uint8_t MOSI = 11; static const uint8_t MISO = 12; static const uint8_t SCK = 10; // 修改后(适配合宙开发板邮票孔布局) static const uint8_t SS = 9; // GPIO9 → CS static const uint8_t MOSI = 3; // GPIO3 → MOSI static const uint8_t MISO = 10;// GPIO10→ MISO(实际未使用,SPI只收不发) static const uint8_t SCK = 2; // GPIO2 → SCLK static const uint8_t SDA = 4; // GPIO4 → I2C SDA(备用) static const uint8_t SCL = 5; // GPIO5 → I2C SCL(备用)技术依据:ESP32C3的SPI2外设支持任意GPIO映射,但需保证MOSI/SCLK/CS为同一SPI单元。此处选择SPI2单元(GPIO2/3/9),因其在邮票孔位置最紧凑,减少PCB绕线。
3.2 核心库协同机制
五类Arduino库构成软件基石,其协同关系如下:
| 库名称 | 功能 | 关键API | 依赖关系 |
|---|---|---|---|
| GxEPD2 | 墨水屏驱动 | display.init(),display.drawBitmap() | 底层硬件抽象 |
| U8g2 | 字体渲染引擎 | u8g2.setFont(),u8g2.drawStr() | 依赖GxEPD2的U8G2_DRAWABLE接口 |
| ArduinoJson | JSON解析 | deserializeJson(),doc["weather"]["temp"].as<int>() | 解析HTTP返回数据 |
| Time/Timezone | 时间管理 | setTime(),tz.toLocal() | NTP同步后提供本地时间 |
| WiFi/WebServer | 网络服务 | WiFi.begin(),server.on("/", handleRoot) | 提供配网与API调用通道 |
3.2.1 GxEPD2与U8g2融合渲染
为在墨水屏上显示中文,采用U8g2的u8g2_font_unifont_t_chinese3字库(GB2312编码),通过U8G2_FOR_ADAFRUIT_GFX适配层桥接到GxEPD2。关键代码片段:
#include <GxEPD2_BW.h> #include <U8g2_for_Adafruit_GFX.h> GxEPD2_BW<GxEPD2_290_T94, GxEPD2_290_T94::HEIGHT> display(GxEPD2_290_T94(/*CS=9, DC=8, RST=7, BUSY=6*/)); U8G2_FOR_ADAFRUIT_GFX u8g2_for_adafruit_gfx; void setup() { display.init(); u8g2_for_adafruit_gfx.begin(display); u8g2_for_adafruit_gfx.setFont(u8g2_font_unifont_t_chinese3); } void loop() { u8g2_for_adafruit_gfx.firstPage(); do { u8g2_for_adafruit_gfx.setCursor(10, 30); u8g2_for_adafruit_gfx.print("北京"); } while ( u8g2_for_adafruit_gfx.nextPage() ); }此方案规避了U8g2原生SPI驱动与GxEPD2冲突问题,利用Adafruit_GFX接口层实现渲染解耦。
3.3 四模式业务逻辑实现
系统通过全局变量currentMode(0~3)标识当前模式,按键事件驱动状态迁移:
| MODE键按下次数 | 当前模式 | 触发动作 | 数据来源 |
|---|---|---|---|
| 1次 | 时钟模式 | 调用NTP.getTime()获取UTC时间,经Timezone转换为本地时间 | NTP服务器(pool.ntp.org) |
| 2次 | 天气模式 | 调用GetWeather.getNow(),解析心知天气API返回JSON | 心知天气(api.seniverse.com) |
| 3次 | 古诗模式 | 调用GetSentence.getPoetry(),解析诗词API返回JSON | 一言API(v1.hitokoto.cn) |
| 4次 | 图片模式 | 调用display.drawXBitmap()显示预存图片 | 编译时固化至Flash的MyIMG.h |
3.3.1 离线模式保障机制
当WiFi连接失败或API请求超时时,系统自动降级至离线模式:
- 时钟模式:显示上次成功同步的时间(EEPROM存储);
- 天气/古诗模式:显示最近一次成功获取的数据(Flash缓存);
- 图片模式:始终可用(无网络依赖)。
EEPROM存储结构定义:
struct ConfigData { char ssid[33]; // WiFi名称 char password[65]; // WiFi密码 char weatherKey[33];// 心知天气密钥 time_t lastNtpTime; // 最后NTP同步时间戳 char lastWeather[128]; // 最后天气摘要 char lastPoetry[128]; // 最后古诗文本 };写入前执行EEPROM.put(0, configData),读取时EEPROM.get(0, configData),确保掉电数据不丢失。
4. BOM清单与器件选型依据
| 序号 | 器件 | 型号/规格 | 数量 | 选型依据 | 替代建议 |
|---|---|---|---|---|---|
| 1 | 主控芯片 | 合宙ESP32C3开发板(经典款) | 1 | 邮票孔设计,UART下载稳定 | 简约款(需Internal USB下载) |
| 2 | 墨水屏 | HINK-E154A05(1.54寸) | 1 | 分辨率200×200,FPC24接口 | HINK-E029A01(2.9寸,296×128) |
| 3 | 电源管理 | ETA6093 | 1 | 单芯片集成充放电+升压+路径管理 | IP5306(需外置MOSFET) |
| 4 | 锂电池 | 301048(3.7V/150mAh) | 1 | 体积小(3×10×48mm),适合桌面摆件 | 302030(3.7V/80mAh) |
| 5 | 按键 | Tactile Switch(6×6mm) | 2 | 行程1.0mm,寿命≥50万次 | ALPS SKQG系列 |
| 6 | 拨动开关 | SPDT Slide Switch | 1 | 额定电流0.3A,机械寿命10万次 | C&K S-1111系列 |
| 7 | LED | 0603 Blue/Green | 2 | 亮度200mcd,正向压降3.2V | Everlight ELS-1103系列 |
| 8 | 电感 | CDRH5D28NP-100NC | 1 | 10μH/1.8A,屏蔽型,DCR<0.1Ω | TDK VLS5045EX-100M |
成本控制要点:所有被动器件(电阻/电容/电感)均选用国产主流品牌(风华高科、顺络电子),BOM总成本控制在¥85以内(不含墨水屏)。墨水屏为二手渠道采购,新料成本约¥35(1.54寸)/¥55(2.9寸)。
5. 使用与维护指南
5.1 首次配网流程
- 拨动开关开机,等待蓝色LED常亮;
- 长按MODE键5秒至红色LED闪烁,进入AP模式(SSID:
DesInk_AP,密码:12345678); - 手机连接该WiFi,在浏览器访问
192.168.4.1进入配网页面; - 输入家庭WiFi名称与密码,提交后设备自动重启并连接;
- 成功连接后,红色LED熄灭,蓝色LED常亮。
5.2 日常操作规范
- 模式切换:短按MODE键循环切换四模式,KEEP键强制刷新当前模式数据;
- 强制配网:长按MODE键至红灯灭(约8秒)后松开,恢复出厂设置;
- 充电提示:USB接入时绿灯闪烁(充电中),常亮(充满),此时可正常开关机;
- 古诗限流规避:单日请求不超过20次,两次请求间隔≥60秒,避免触发API限流。
5.3 故障排查表
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 屏幕无显示 | ①电源开关未拨至ON位 ②墨水屏FPC排线未插紧 ③ESP32C3未烧录固件 | ①检查拨动开关位置 ②断电后重新插拔FPC,确认卡扣闭合 ③用Arduino重新烧录固件 |
| 无法配网 | ①手机未连接DesInk_AP ②配网页面提交后未等待30秒 ③路由器信道为12/13 | ①确认手机WiFi列表存在DesInk_AP ②提交后等待设备自动重启 ③将路由器信道改为1-11 |
| 天气显示"Error" | ①心知天气密钥错误 ②网络DNS解析失败 ③API返回格式变更 | ①检查Config.h中WEATHER_KEY值②在 WifiConfigPage.ino中添加WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE)强制DHCP③抓包分析API响应,更新 GetWeather.ino解析逻辑 |
6. 性能实测数据
| 测试项 | 测试条件 | 实测结果 | 工程结论 |
|---|---|---|---|
| 局部刷新耗时 | 1.54寸屏幕,200×200区域 | 850ms ± 50ms | 满足桌面摆件实时性要求(<1s) |
| 全刷残影消除 | 连续全刷10次 | 第10次后残影降低92% | 建议每2小时执行一次全刷 |
| USB充电效率 | 5V/1A输入,150mAh电池 | 充满时间≈110分钟,效率83% | 符合ETA6093标称性能 |
| WiFi连接稳定性 | 2.4GHz频段,距离路由器5米 | 连续72小时无断连 | ESP32C3 WiFi模块可靠性达标 |
| 字体显示准确率 | GB2312字库(8104字) | 缺字率2.3%(生僻字如“龘”、“靐”) | 生产环境建议精简字库至常用3500字 |
长期运行观察:连续运行30天后,墨水屏出现轻微底色偏灰现象,属墨水屏物理特性(微胶囊老化),不影响信息可读性。建议每半年更换一次屏幕模组以维持最佳显示效果。