🖼️ ESP32 墨水屏实战:从点亮到低功耗物联网终端

📅 2026-05-31 · 📂 硬件编程 · ⏱ 阅读约 7 分钟

📺 B站推荐视频:[Mpy]全网最简单最易学的esp32驱动墨水屏的教程!

📖 概述

墨水屏(E-Paper / E-Ink)是一种基于电泳技术的反射式显示屏。它最大的特点是断电后图像仍然保持,零功耗维持显示内容。在阳光下清晰可读、无蓝光伤害,是电子价签、物联网信息终端、电子日历的首选显示方案。

本文将基于 ESP32 + Waveshare 2.9 寸墨水屏模块,带你从接线、驱动库安装到完整代码,实现图片显示、文字绘制和局部刷新三大核心技能。学完之后,你可以结合之前学过的 WiFi(5/6)和低功耗(5/17),打造一个用电池续航数月的无线信息终端

💡 墨水屏 vs TFT/LCD:墨水屏不需要背光,靠环境光反射显示,像纸一样。刷新一次后可以断电,图像永久保留。缺点是刷新速度较慢(全刷约2-3秒)、只有黑白(带红/黄的版本稍贵),不适合播放视频和快速动画。

📦 物料清单

物料型号/参数参考价格(¥)
主控板ESP32 DevKit V1 (38Pin)18 ~ 30
墨水屏模块Waveshare 2.9" E-Paper (B/W) 296×12855 ~ 75
墨水屏模块Waveshare 2.9" E-Paper (B/W/R) 296×128 三色65 ~ 85
杜邦线母对母 10cm × 8 根3 ~ 5
面包板830 孔5 ~ 10
USB 数据线Micro USB已有

推荐入门选择 Waveshare 2.9" 黑白版,性价比高、驱动的兼容性好。如果你确定需要红色标注功能(如温度超阈值标红),可以选三色版,但刷新时间是黑白版的2倍(约15秒)。

🔌 接线图

墨水屏采用 SPI 通信协议,需要连接 7 根信号线 + VCC/GND。以下接线适配 Waveshare E-Paper Driver HAT 的默认引脚:

Waveshare 2.9" E-Paper  →  ESP32 DevKit V1
═══════════════════════════════════════════
VCC   (红)              →  3.3V
GND   (黑)              →  GND
DIN   (蓝/MOSI)         →  GPIO 23  (VSPI MOSI)
SCLK  (绿/SCK)          →  GPIO 18  (VSPI SCK)
CS    (黄/片选)          →  GPIO 5
DC    (橙/数据指令)      →  GPIO 17
RST   (棕/复位)          →  GPIO 16
BUSY  (紫/忙检测)        →  GPIO 4
        
💡 关于电平:Waveshare 2.9" 墨水屏模块板载电平转换,支持 3.3V/5V。ESP32 的 3.3V GPIO 直接连接即可,不需要额外的电平转换模块。

💻 基础代码:显示文字与图片

Arduino IDE 中搜索安装 GxEPD2 库(作者:Jean-Marc Zingg),它支持市面上几乎所有主流墨水屏型号。

1. 环境配置

在 Arduino IDE 的库管理器中搜索 GxEPD2,安装最新版本(会自动安装依赖库 Adafruit GFX)。

2. 完整示例代码:显示文字、线条和位图

// ESP32 + Waveshare 2.9" E-Paper (B/W) 完整示例 // 功能:显示中文标题、绘制表格、显示自定义位图 #include <GxEPD2_BW.h> // 黑白墨水屏用 BW,三色用 3C // 根据型号选择对应的类 —— 2.9" 296×128 黑白屏 GxEPD2_BW<GxEPD2_290, GxEPD2_290::HEIGHT> display( GxEPD2_290(/*CS=*/5, /*DC=*/17, /*RST=*/16, /*BUSY=*/4) ); void setup() { Serial.begin(115200); Serial.println("墨水屏初始化中..."); display.init(115200); // SPI 通信初始化 display.setRotation(1); // 横屏显示(旋转90度) // ===== 第一页:标题与文字 ===== display.setFullWindow(); // 全屏刷新模式 display.firstPage(); do { display.fillScreen(GxEPD_WHITE); // 白色背景 // 标题栏 display.fillRect(0, 0, 296, 36, GxEPD_BLACK); display.setTextColor(GxEPD_WHITE); display.setFont(&FreeSansBold12pt7b); display.setCursor(10, 26); display.print("ESP32 E-Paper"); // 信息行 display.setTextColor(GxEPD_BLACK); display.setFont(&FreeSans9pt7b); display.setCursor(10, 66); display.print("Temp: 26.5 C"); display.setCursor(10, 86); display.print("Humi: 58 %"); // 分隔线 display.drawLine(0, 100, 296, 100, GxEPD_BLACK); // 页脚 display.setFont(&FreeMono9pt7b); display.setCursor(10, 120); display.print("2026-05-31 06:30"); } while (display.nextPage()); Serial.println("显示完成!进入深度睡眠..."); // 显示完成后进入深度睡眠,功耗低至 ~10uA display.hibernate(); esp_deep_sleep_start(); } void loop() { // 永远不会执行到这里(深度睡眠后重启) }
💡 代码解析
firstPage() / nextPage() 是 GxEPD2 特有的分页绘制模式,框架自动处理显存分配
hibernate() 让墨水屏进入超低功耗状态,配合 ESP32 deep_sleep() 实现电池长续航
• 如果要显示中文,需要搭配 U8g2_for_Adafruit_GFX 库渲染中文字体

🚀 进阶应用

1. 局部刷新(Partial Update)

全屏刷新约 2-3 秒且有闪烁。GxEPD2 支持局部刷新,只更新屏幕的一部分,速度更快且无闪烁:

// 局部刷新示例 —— 只更新温湿度数字区域 display.setPartialWindow(10, 50, 200, 40); // 局部窗口 x,y,w,h display.firstPage(); do { display.fillRect(10, 50, 200, 40, GxEPD_WHITE); // 清空区域 display.setCursor(10, 78); display.print("Temp: 27.1 C"); } while (display.nextPage());
⚠️ 局部刷新的"鬼影"问题:频繁局部刷新会在屏幕留下淡淡的残影。建议每 10-20 次局部刷新后,执行一次全屏刷新来清除残影。GxEPD2 提供了 display.powerOff() + 延时 + display.init() 的清理技巧。

2. 显示自定义位图

使用 image2cpp 在线工具(javl.github.io/image2cpp),将 PNG/JPG 图片转换为 Arduino 位图数组,然后用 drawBitmap() 方法显示:

// 墨水屏显示自定义 Logo(296×128 黑白位图) static const unsigned char logo_bitmap[] PROGMEM = { // image2cpp 生成的数组 —— 296*128/8 = 4736 字节 0xff, 0xff, 0xff, /* ... 4736 bytes total ... */ }; void showLogo() { display.setFullWindow(); display.firstPage(); do { display.drawBitmap(0, 0, logo_bitmap, 296, 128, GxEPD_BLACK); } while (display.nextPage()); }

3. 无线更新显示内容

结合之前学过的 WiFi(5/6)+ HTTP(5/7)知识,可通过 HTTP GET 请求获取天气/新闻数据,刷新到墨水屏上:

// 伪代码:WiFi 获取天气 → 墨水屏显示 connectWiFi("SSID", "PASSWORD"); String weather = httpGet("http://api.weatherapi.com/v1/current.json?...&q=Shanghai"); display.setPartialWindow(0, 40, 296, 80); display.firstPage(); do { display.setCursor(10, 65); display.print(weather); // 天气数据直接输出到屏幕 } while (display.nextPage()); display.hibernate(); // 显示完休眠,等着下次唤醒 esp_deep_sleep(600 * 1000000); // 10分钟后唤醒刷新

🏗️ 实战场景

场景一:桌面天气预报站

功能描述:每天早上自动更新当日天气,墨水屏持续显示,零功耗维持。整机电池供电,一次充电用3个月以上。

物料组合:ESP32 + Waveshare 2.9" E-Paper + 18650 电池 + TP4056 充电模块

联动已学模块

功能使用模块对应教程
联网获取天气WiFi + HTTP Client5/6、5/7
低功耗长续航Deep Sleep + 墨水屏休眠5/17
温湿度本地监测DHT22 传感器5/16
显示输出墨水屏(本文)5/31

场景二:电子墨水价签 / 办公桌牌

功能描述:通过手机 BLE 连接 ESP32,发送文字或二维码到墨水屏显示。适合会议室桌牌、仓库货架标签、展览展品说明牌。

物料组合:ESP32 + 2.9" E-Paper + (可选)3D打印外壳

联动已学模块

功能使用模块对应教程
手机无线控制BLE 蓝牙通信5/10、5/11
图形化显示墨水屏 + 中文字库5/31
二维码生成qrcode 库(Arduino)扩展自学

⚠️ 常见问题

⚠️ 屏幕白屏无任何显示
这是最常见的入坑问题。排查顺序:① 检查 BUSY 引脚接线(最容易被忽略的一根线);② 确认 SPI 引脚是否与代码中一致(CS=5, DC=17, RST=16, BUSY=4);③ 确认库中选用的型号类是否正确(GxEPD2_290 是 2.9" 黑白版,三色版要用 GxEPD2_290_3C)。
⚠️ 显示内容模糊或有很多横纹
通常是供电不足。墨水屏刷新时峰值电流可达 40mA。务必使用 ESP32 的 3.3V 引脚供电而非 5V + 面包板分压。如果你的 ESP32 板载 3.3V LDO 功率不足(如某些 Mini D1 板),改用独立 3.3V 稳压模块供电。
⚠️ 长时间显示不动后出现残影/"烧屏"
墨水屏并不是真的"烧屏",而是长时间保持同一画面后电荷残留。处理方法:① 代码中先全屏显示白色再刷新内容;② 不要超过 24 小时不刷新;③ 如果已出现残影,连续全屏黑白交替刷新 5-10 次可恢复。
⚠️ 不支持在阳光下暴晒
墨水屏的工作温度通常在 0°C ~ 50°C 之间。阳光直射导致屏幕温度超过 50°C 时,黑色会变灰甚至永久损伤。户外使用建议加遮阳罩,或者选用宽温墨水屏模组。

📚 小结与下期预告

今天你解锁了 ESP32 驱动墨水屏的完整技能链:SPI 接线 → GxEPD2 库 → 全屏/局部刷新 → 自定义位图 → 低功耗休眠。结合 WiFi + BLE + 低功耗,你可以做出真正可落地的物联网终端产品

下一期,我们将深入工业通信领域,学习 RS485 总线——如何在一条双绞线上挂载上百个设备,并实现千米级的可靠数据传输。别错过!