1. 从Token焦虑说起为什么我决定自己做一个墨水屏看板用大模型API的人大概都有过这种体验月初信心满满地写代码调接口月中突然发现额度快见底了赶紧去后台查用量结果页面加载半天数据还藏在二级菜单里。更别提同时用着好几家服务的时候得挨个登录、挨个查光切换账号就够烦的。我自己的情况是日常要跑一些自动化脚本调API有时候是批量处理文本有时候是定时任务。Token消耗忽高忽低心里完全没数。有次一个循环写错了半夜跑了几个小时第二天醒来发现一个月的额度烧掉大半。从那以后我就想能不能有个东西抬眼就能看到当前用量不用打开浏览器、不用登录后台像看电子钟一样自然。市面上的桌面看板方案不少但要么得一直开着电脑跑个网页要么得买个成品小屏幕动辄两三百。后来刷到有人用墨水屏做桌面摆件我突然意识到这东西简直完美断电还能显示、不发光不刺眼、刷新一次管很久。关键是一块4.2寸的墨水屏模块几十块钱就能买到配上手头吃灰的ESP8266开发板总成本控制在百元以内。这篇内容就是把我从选型、接线、刷固件到写服务端接口的完整过程整理出来。适合有基础动手能力、想低成本搞一个桌面信息屏的朋友。不需要你懂嵌入式开发但需要你会用电脑、能看懂基本的命令行操作。整个方案的核心思路是墨水屏负责显示ESP8266负责联网和驱动屏幕一台常开的设备NAS、树莓派或者旧笔记本跑一个轻量服务去拉取API用量数据三者通过HTTP协议串起来。提示这个方案不涉及任何网络代理或特殊网络配置所有请求都走正常的公网HTTP/HTTPS接口请确保你的网络环境可以正常访问对应的API服务。2. 硬件选型为什么是4.2寸墨水屏加ESP82662.1 墨水屏模块的规格对比与选择逻辑市面上常见的墨水屏模块按尺寸分主要有1.54寸、2.13寸、2.9寸、4.2寸和7.5寸几种。我选的是4.2寸、分辨率400x300的型号型号里带E042A13字样的那种。为什么是这个尺寸1.54寸和2.13寸太小显示几行数据就满了而且字体缩小后墨水屏的颗粒感很明显。7.5寸又太大太贵一块屏就顶我整个预算了。4.2寸刚好能放下标题、几个数据项和更新时间放在桌面上不占地方字号也够看清楚。分辨率400x300意味着横向能显示大约50个英文字符按8像素宽字体算中文大概25个字。这个信息密度对于显示今日用量本月累计剩余额度这类数据绰绰有余。刷新方式上墨水屏分全刷和局刷全刷会有明显的黑白闪烁大概2秒左右局刷快很多但残影会累积。我的策略是数据变化时用局刷每隔一段时间做一次全刷清残影。接口方面这类模块通常提供SPI接口引脚包括VCC、GND、CLK、DIN、CS、DC、RST、BUSY。SPI的好处是速度快、占用IO少ESP8266的硬件SPI跑起来很稳。工作电压3.3V正好和ESP8266匹配不需要额外的电平转换。2.2 ESP8266开发板便宜但够用的联网方案ESP8266这颗芯片出来很多年了现在一块NodeMCU或者Wemos D1 mini开发板也就十几块钱。它内置WiFi有完整的TCP/IP协议栈跑HTTP客户端完全没问题。Flash通常有4MB存个固件和少量配置绰绰有余。GPIO数量虽然不多但驱动一块SPI墨水屏只需要6到7个引脚够用。有人会问为什么不选ESP32。ESP32性能更强、支持蓝牙、价格也就贵几块钱。我的考虑是这个项目对算力几乎没有要求ESP8266的80MHz主频和80KB RAM处理一个HTTP请求加屏幕刷新绰绰有余。而且ESP8266的Arduino核心库非常成熟社区资料多遇到问题好查。如果你手头正好有ESP32直接用也没问题代码基本兼容只需要改一下引脚定义。供电方面ESP8266峰值电流大概在300mA左右墨水屏刷新时也有瞬时电流。我用的是一个普通的5V/1A USB充电头通过开发板上的Micro USB口供电实测稳定。如果你要做得更紧凑可以用AMS1117-3.3稳压模块从5V降压但要注意散热ESP8266加墨水屏的总电流不大问题不大。2.3 接线方案与注意事项接线这块我踩过坑这里详细说一下。墨水屏模块的引脚标号可能因厂家不同略有差异但功能定义是一致的。以我手头这块为例墨水屏引脚ESP8266引脚说明VCC3.3V供电千万别接5VGNDGND共地CLKD5 (GPIO14)SPI时钟DIND7 (GPIO13)SPI数据CSD8 (GPIO15)片选低电平有效DCD1 (GPIO5)数据/命令选择RSTD2 (GPIO4)复位BUSYD6 (GPIO12)忙状态检测注意ESP8266的GPIO15在启动时有特殊要求必须为低电平才能正常启动。CS接在GPIO15上正好满足这个条件但如果你用其他引脚方案务必确认启动电平。另外GPIO16没有中断功能不建议用来接BUSY。接线时尽量短尤其是SPI的时钟和数据线长了容易受干扰导致花屏。我用的是10cm的杜邦线实测没问题。如果你要焊板子建议用排针加排母方便更换。3. 固件烧录从Arduino IDE到成功点屏3.1 开发环境搭建与库依赖我用的开发环境是Arduino IDE版本2.x。首先要在首选项里添加ESP8266的开发板管理器地址然后在开发板管理器里搜索安装esp8266平台包。这个过程需要联网下载如果网络环境不好可能会失败多试几次或者换个时间段。库方面驱动墨水屏需要两个核心库一个是底层SPI通信和屏幕初始化另一个是图形绘制库。我用的组合是GxEPD2加Adafruit GFX。GxEPD2专门针对各种墨水屏做了适配支持局刷和全刷切换Adafruit GFX提供画线、画矩形、显示文字的基础函数。在库管理器里直接搜索安装即可。安装完库之后打开GxEPD2的示例代码找到对应你屏幕型号的那个示例。我的屏幕对应GxEPD2_420_GDEY042T81这个类。如果你不确定自己的屏幕型号可以看模块背面的丝印或者问卖家要资料。选错驱动类的后果是屏幕完全没反应或者显示错乱。3.2 烧录过程中的常见报错与解决第一次烧录大概率会遇到连接失败的问题报错信息通常是failed to connect to esp8266: timed out waiting for packet header。这个问题的原因有几个一是串口驱动没装好CH340或者CP2102的驱动要去对应官网下载二是开发板没进入下载模式需要按住FLASH键再按RST键或者某些板子自动进入三是串口被其他程序占用了比如你同时开着串口监视器。我的经验是先在设备管理器里确认串口能识别然后在Arduino IDE里选对端口和开发板型号。上传时如果一直卡在Connecting...就手动按一下板子上的FLASH按钮。烧录成功后串口监视器会输出IP地址说明WiFi连接正常。还有一个坑是Flash大小选错。NodeMCU通常选4MB (FS:2MB OTA:~1019KB)如果选成1MB编译出来的固件可能放不下报错text section exceeds available space。这个错误提示很明确改一下配置就行。3.3 屏幕初始化与第一个测试画面烧录成功后屏幕应该会显示示例代码里的图案。如果没有显示先检查接线再检查GxEPD2的初始化参数。我遇到过一次屏幕全白的情况后来发现是BUSY引脚接错了导致程序一直等待屏幕就绪。用万用表量一下BUSY引脚在刷新时的电平变化能快速定位问题。第一个测试画面我建议显示Hello World加一个矩形框确认基本绘制功能正常。然后测试局刷先画一个数字等几秒改成另一个数字观察刷新速度和残影情况。局刷的残影在显示数字时比较明显可以通过定期全刷来清除。我的设置是每20次局刷做一次全刷实际使用中残影控制得不错。4. 服务端数据接口用Docker跑一个轻量聚合服务4.1 为什么需要一个中间服务ESP8266直接去请求大模型平台的API行不行技术上可以但有几个问题。第一API密钥要存在ESP8266的固件里一旦设备丢了或者固件被提取密钥就泄露了。第二不同平台的API返回格式不一样ESP8266的JSON解析能力有限处理起来很吃力。第三HTTPS请求在ESP8266上开销较大多个请求串行执行会明显变慢。所以我的架构是ESP8266只负责向本地服务发一个简单的HTTP GET请求本地服务去处理所有复杂的逻辑——调用各个平台的API、解析JSON、计算汇总数据最后返回一个极简的JSON给ESP8266。这样ESP8266的代码可以写得很简单密钥也安全地存在服务端。这个本地服务我用Docker来跑好处是环境隔离、部署方便、迁移容易。一台常开的NAS或者树莓派就能跑资源占用极低。4.2 Docker环境准备与镜像加速配置如果你还没装DockerWindows和macOS直接下载Docker Desktop安装包一路下一步就行。Linux上用包管理器安装Ubuntu的话执行sudo apt install docker.io docker-compose。安装完记得把当前用户加入docker组否则每次都要sudo。Docker Desktop在Windows上启动时可能会报virtualization support not detected这是因为BIOS里的虚拟化功能没开。重启进BIOS找到Intel VT-x或者AMD-V选项设为Enabled。如果是Windows家庭版还需要确认WSL2已经安装Docker Desktop会提示你装。拉取镜像时如果遇到request canceled while waiting for connection或者net/http: request canceled这类错误通常是网络问题。可以配置国内镜像加速器在Docker Desktop的设置里找到Docker Engine在daemon.json里加上registry-mirrors配置。改完重启Docker服务生效。4.3 服务端代码结构与核心逻辑服务端我用Python写因为处理HTTP请求和JSON解析最方便。核心是一个Flask应用暴露一个/usage接口。代码结构大致如下from flask import Flask, jsonify import requests import json from datetime import datetime app Flask(__name__) # 各平台的API配置 PLATFORMS [ { name: 平台A, url: https://api.example-a.com/v1/usage, headers: {Authorization: Bearer YOUR_KEY_A} }, { name: 平台B, url: https://api.example-b.com/v1/quota, headers: {Authorization: Bearer YOUR_KEY_B} } ] app.route(/usage) def get_usage(): result [] for p in PLATFORMS: try: resp requests.get(p[url], headersp[headers], timeout10) data resp.json() # 根据各平台返回格式提取关键字段 used data.get(used_tokens, 0) total data.get(total_tokens, 0) result.append({ name: p[name], used: used, total: total, percent: round(used / total * 100, 1) if total else 0 }) except Exception as e: result.append({name: p[name], error: str(e)}) return jsonify({ updated: datetime.now().strftime(%m-%d %H:%M), items: result }) if __name__ __main__: app.run(host0.0.0.0, port5000)这个代码的关键点每个平台的API地址和密钥单独配置解析逻辑根据实际返回格式调整。异常处理很重要某个平台挂了不能影响其他平台的数据展示。返回的JSON结构要尽量扁平方便ESP8266解析。4.4 用Docker Compose编排服务为了管理方便我写了一个docker-compose.ymlversion: 3 services: usage-api: build: . ports: - 5000:5000 restart: unless-stopped environment: - TZAsia/ShanghaiDockerfile也很简单FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple COPY . . CMD [python, app.py]requirements.txt里就三行flask、requests、gunicorn。生产环境建议用gunicorn跑比Flask自带的开发服务器稳定。启动命令改成gunicorn -w 2 -b 0.0.0.0:5000 app:app。构建镜像时如果pip下载慢加上国内源。如果Docker Hub拉取基础镜像失败可以换成国内镜像仓库的地址。这些配置一次弄好后面就不用管了。5. ESP8266端的数据获取与屏幕刷新逻辑5.1 HTTP请求的编写与超时处理ESP8266端用ESP8266HTTPClient库发请求代码很简洁#include ESP8266WiFi.h #include ESP8266HTTPClient.h #include ArduinoJson.h const char* ssid 你的WiFi名称; const char* password 你的WiFi密码; const char* apiUrl http://192.168.1.100:5000/usage; void fetchAndDisplay() { if (WiFi.status() ! WL_CONNECTED) { WiFi.begin(ssid, password); // 等待连接最多10秒 int retry 0; while (WiFi.status() ! WL_CONNECTED retry 20) { delay(500); retry; } } HTTPClient http; http.begin(apiUrl); http.setTimeout(5000); // 5秒超时 int code http.GET(); if (code 200) { String payload http.getString(); DynamicJsonDocument doc(1024); deserializeJson(doc, payload); // 解析并显示 displayData(doc); } else { displayError(HTTP String(code)); } http.end(); }这里有几个细节WiFi重连逻辑要加因为ESP8266偶尔会掉线。HTTP超时设5秒太短了容易失败太长了屏幕半天不更新。JSON文档大小根据实际返回数据量调整1024字节通常够用不够的话会解析失败。注意ESP8266的HTTPClient默认不支持HTTPS如果你的服务端是HTTPS需要用WiFiClientSecure并加载证书会消耗更多内存。所以本地服务用HTTP就够了反正只在局域网内通信。5.2 JSON解析与数据映射到屏幕布局解析完JSON后要把数据映射到屏幕上的固定位置。我的布局是这样的顶部一行显示标题API用量看板和更新时间中间分两列左边显示各平台名称右边显示用量百分比底部显示一个进度条直观反映消耗比例用Adafruit GFX的setCursor和print函数定位文字用drawRect和fillRect画进度条。字体用FreeSans9pt或者FreeMono12pt前者好看但占空间后者等宽适合对齐数字。我最终选了FreeSans9pt中文用U8g2库的字体但要注意中文字库很占Flash只加载需要的字。进度条的计算宽度乘以百分比注意整数运算的精度问题。比如int barWidth (int)(percent * maxWidth / 100.0)先乘后除避免精度丢失。5.3 局刷与全刷的时机控制墨水屏的刷新策略直接影响使用体验。我的做法是每次数据更新时先比较新旧数据如果没变化就不刷新省电省屏幕寿命有变化时用局刷局刷区域只覆盖数据变化的区域不是全屏累计局刷20次后下一次强制全刷清除残影每小时整点做一次全刷不管局刷次数GxEPD2库支持setPartialWindow函数指定局刷区域。比如只更新右下角的百分比数字就设置那个矩形区域。这样刷新速度快闪烁也小。实测局刷一次大概0.5秒全刷2秒左右。残影的控制是个经验活。如果发现数字有重影就增加全刷频率。如果屏幕开始发灰说明全刷太频繁了墨水屏的全刷次数是有限的大概几十万次正常使用一天刷几十次用几年没问题。6. 外壳与摆放让看板融入桌面6.1 简易外壳方案与散热考虑裸板放桌上容易短路也难看。我用3D打印了一个简单的外壳如果没有打印机用亚克力板裁切加铜柱固定也行。外壳设计要注意几点屏幕开窗要精确大了漏边小了遮挡背面留散热孔ESP8266和稳压模块会发热底部留USB口的位置方便供电。我第一版外壳没留散热孔夏天连续运行几天后摸上去有点烫。后来在背面开了几排小孔温度降下来了。墨水屏本身不发热主要热源是ESP8266的WiFi模块和LDO稳压器。6.2 摆放位置与视角调整墨水屏的可视角度很大但对比度会随角度变化。最佳观看角度是正对或者稍微俯视。我把它放在显示器下方稍微倾斜15度看起来最舒服。如果你要挂在墙上注意环境光要充足墨水屏本身不发光暗处看不清。供电线我用了一根白色的细USB线沿着桌边走线用理线夹固定。看起来还算整洁。如果你追求无线可以用锂电池加充电模块但续航是个问题WiFi常连的话一天一充跑不掉。7. 实际运行中的问题与优化经验7.1 WiFi断连与自动重连机制ESP8266的WiFi稳定性是出了名的看运气。我遇到过连续运行一周后突然掉线屏幕一直显示旧数据。后来加了看门狗逻辑每次刷新前检查WiFi状态如果断开就重连连续三次重连失败就重启ESP8266。用ESP.restart()函数重启后自动重新连接。另外路由器如果开了双频合一ESP8266只支持2.4G可能会连不上。建议在路由器里把2.4G和5G的SSID分开让ESP8266连2.4G的那个。7.2 服务端接口的容错与降级显示服务端某个平台接口挂了怎么办我的处理是单个平台失败不影响其他平台失败的平台在屏幕上显示ERR而不是空白。如果整个服务端都连不上ESP8266显示上次成功获取的数据并在角落标注离线。服务端这边每个平台的请求加try-except记录错误日志但不中断。如果所有平台都失败返回一个包含错误信息的JSONESP8266解析后显示错误提示。这样你一眼就能看出是网络问题还是某个平台的问题。7.3 长期运行的稳定性观察连续跑了三个月总结几个经验一是定期重启有好处我设了每天凌晨4点自动重启一次ESP8266避免内存泄漏累积二是墨水屏避免阳光直射紫外线会加速屏幕老化三是Docker容器设了restart策略宿主机重启后服务自动起来不用手动干预。还有个小技巧在服务端加一个/health接口返回简单的OK配合uptime监控能及时发现服务是否存活。ESP8266端也可以定期ping一下服务端确认网络通路正常。这个墨水屏看板从构思到落地大概花了一个周末总成本算下来不到八十块。现在它就在我显示器下面安静地显示着各平台的用量抬眼就能看到再也不用担心Token悄悄跑光了。如果你也想做一个建议先从点亮屏幕开始一步步来遇到问题查查社区基本都能解决。
