《Arduino 手册(思路与案例)》栏目介绍:
在电子制作与智能控制的应用领域:广泛涉及了Arduino BLDC、Arduino CNC、Arduino ESP32 SPP、Arduino FreeRTOS、Arduino FOC、Arduino GRBL、Arduino HTTP、Arduino HUB75、Arduino IoT Cloud、Arduino JSON、Arduino LCD、Arduino OLED、Arduino LVGL、Arduino PID 及 Arduino TFT 等方面的相关拓展思路和众多参考案例。本专栏目前博客近2300篇。
https://blog.csdn.net/weixin_41659040/category_12422453.html
Arduino是一个开放源码的电子原型平台,它可以让你用简单的硬件和软件来创建各种互动的项目。Arduino的核心是一个微控制器板,它可以通过一系列的引脚来连接各种传感器、执行器、显示器等外部设备。Arduino的编程是基于C/C++语言的,你可以使用Arduino IDE(集成开发环境)来编写、编译和上传代码到Arduino板上。Arduino还有一个丰富的库和社区,你可以利用它们来扩展Arduino的功能和学习Arduino的知识。
Arduino的特点是:
1、开放源码:Arduino的硬件和软件都是开放源码的,你可以自由地修改、复制和分享它们。
2、易用:Arduino的硬件和软件都是为初学者和非专业人士设计的,你可以轻松地上手和使用它们。
3、便宜:Arduino的硬件和软件都是非常经济的,你可以用很低的成本来实现你的想法。
4、多样:Arduino有多种型号和版本,你可以根据你的需要和喜好来选择合适的Arduino板。
5、创新:Arduino可以让你用电子的方式来表达你的创意和想象,你可以用Arduino来制作各种有趣和有用的项目,如机器人、智能家居、艺术装置等。
Arduino E-Ink(电子墨水屏) 是近年来在低功耗嵌入式显示系统中广泛应用的一种新型显示技术。它与传统 TFT、OLED 等屏幕有着本质区别,特别适用于需要长时间静态显示、低刷新频率、节能的场景。
一、主要特点
- 超低功耗
E-Ink 屏幕仅在刷新画面时消耗电力,显示内容保持不变时几乎不耗电。
非常适合电池供电设备或太阳能供电系统,可显著延长续航时间。 - 阳光下可视性强
借助环境光反射原理,E-Ink 屏幕在强光下依旧清晰可见,优于 OLED 和 LCD。
无背光设计使其更适合户外或高亮度环境下的使用。 - 黑白/灰阶显示为主
大多数 E-Ink 屏幕为单色(黑白)或有限灰阶(如 3bit),色彩表现能力弱于 TFT 或 OLED。
这使得其更适用于文字、图标、仪表等简洁信息的展示。 - 刷新率低,不适合动态内容
刷新一次通常需要几百毫秒至数秒,且频繁刷新会导致残影问题。
不适合播放视频、动画或实时图形更新类应用。 - 驱动复杂度较高
相比普通字符型 LCD,E-Ink 屏幕需要精确控制波形驱动(Driver Waveform),否则容易出现残影或老化现象。
通常依赖专用库(如 GxEPD2、Adafruit_EPD)进行图像缓冲和刷新控制。 - 寿命长,耐久性好
E-Ink 屏幕具有很高的耐久性,理论上可支持数十万次刷新,不易老化。
对比 OLED 的“烧屏”风险,E-Ink 更加稳定可靠。
二、应用场景
- 智能标签(Smart Label)
应用于零售行业,作为货架价格标签、库存管理标签等,可远程更新商品信息。
示例:超市电子价签系统。 - 智能家居显示终端
显示温湿度、空气质量、日程提醒、门锁状态等信息。
可作为壁挂式低功耗家庭信息中心。 - 便携式电子设备
如电子书阅读器(Kindle)、智能手表辅助显示界面、户外导航设备等。
特别适合需要长时间待机、无需频繁刷新的设备。 - 农业与环境监测
在温室大棚、气象站、水质检测点部署低功耗显示屏,展示传感器数据。
示例:太阳能供电的空气污染监测站显示模块。 - 工业与物流追踪
工业设备状态显示面板、资产追踪标签、运输过程中的温湿度记录仪等。
支持无线通信 + E-Ink 的组合方案,实现远程监控。
三、注意事项
- 刷新策略优化
避免不必要的刷新操作,尽量采用局部刷新(Partial Refresh)减少闪烁与延迟。
全局刷新(Full Update)虽然显示效果更好,但耗时较长且易造成视觉不适。 - 内存占用问题
E-Ink 屏幕分辨率较高时,帧缓冲区(Frame Buffer)会占用大量 RAM。
对于 Arduino UNO/Nano 等低端设备,建议选择小尺寸或使用外部 SRAM 缓冲。 - 驱动库的选择与配置
推荐使用主流开源库如:
GxEPD2:功能强大,支持多种 E-Ink 模块。
Adafruit_EPD:适用于 Adafruit 自家模块。
注意 SPI 速率、引脚映射、复位逻辑是否匹配硬件。 - 避免残影与图像老化
长时间显示相同内容可能导致“图像残留”,称为“残影效应”。
建议定期执行“清除刷新”(Clear Update)或随机扰动内容布局来缓解。 - 电源管理策略
可结合 Arduino 的休眠模式,在非工作时段关闭屏幕供电或进入低功耗模式。
使用 MOSFET 控制屏幕电源,进一步降低待机电流。 - 开发调试难度较大
由于刷新速度慢,调试过程中需耐心等待每次更新结果。
建议先在 TFT/OLED 上验证逻辑,再迁移到 E-Ink 平台。
在 Arduino 开发中,E-Ink 之基础文本显示(Basic Text Display on E-Ink) 是一项非常实用且具有广泛适用性的功能。它利用了电子墨水屏(E-Ink / Electronic Paper Display, EPD)的低功耗、高可视性等特性,实现静态文本信息的高效展示。
一、主要特点
- 极低功耗
E-Ink 屏幕仅在刷新时消耗能量,内容保持不变时几乎不耗电。
十分适合电池供电或远程部署的低功耗设备。 - 阳光下可视性强
利用环境光反射成像,无背光干扰,在强光下依旧清晰可见。
比 OLED 和 LCD 更适合户外或光照强烈的应用场景。 - 支持多种字体与大小
可通过图形库(如 GxEPD2、Adafruit GFX)加载不同字体,包括自定义字体,提升可读性和美观度。
支持多行文本布局,便于构建结构化信息界面。 - 刷新机制复杂
需要根据屏幕型号配置合适的刷新模式(Full Update / Partial Refresh)。
刷新频率较低(通常为几百毫秒至数秒),不适合频繁更新内容。 - 帧缓冲区占用内存大
对于分辨率较高的 E-Ink 屏幕,需要较大的 RAM 来存储帧缓冲区(Frame Buffer)。
在资源受限的 Arduino UNO/Nano 上使用时需谨慎选择屏幕尺寸和刷新策略。 - 抗老化设计要求高
长时间显示相同内容可能导致“图像残留”(残影)。
建议定期执行全屏刷新或内容扰动操作,防止屏幕老化。
二、应用场景
- 智能价签系统
显示商品价格、促销信息等,适用于超市、便利店等零售场景。
示例:基于 ESP32 + E-Ink 的无线电子价签。 - 家庭信息中心
显示天气预报、日程安排、待办事项、温湿度等生活信息。
示例:壁挂式家庭信息看板,每日定时刷新。 - 工业仪表盘
显示传感器数据(如温度、压力、液位等)、设备状态、运行参数等。
示例:工厂控制箱中的低功耗数据显示模块。 - 农业与环境监测
部署在温室、气象站、水质检测点等户外环境中,用于展示实时数据。
示例:太阳能供电的空气质量监测终端。 - 物流与资产管理
显示资产编号、位置信息、运输状态等,适用于仓库管理、物流追踪。
示例:带 RFID 的 E-Ink 资产标签。
三、注意事项
- 合理设置刷新模式
尽量使用局部刷新(Partial Refresh)来减少闪烁和延迟。
全局刷新(Full Update)虽然能清除残影,但刷新时间较长,建议只在必要时使用。 - 优化内存使用
使用小尺寸 E-Ink 屏幕(如 1.54"、2.13"、2.9")以降低帧缓存需求。
若使用低端 Arduino 控制器(如 UNO、Nano),应避免高分辨率屏幕或启用外部 SRAM 缓冲。 - 字体与排版设计
选用易读性高的字体,避免过于细小的文字。
合理规划文本布局,避免文字重叠或显示不全。 - 驱动库的选择与适配
推荐使用主流开源库:
GxEPD2:支持广泛的 E-Ink 模块,功能丰富。
Adafruit_EPD:适用于 Adafruit 自家 E-Ink 屏幕。
注意 SPI 通信速率、引脚映射、复位逻辑是否匹配硬件。 - 电源管理优化
在非刷新时段关闭屏幕供电,可使用 MOSFET 或继电器控制 VCC。
结合 Arduino 的休眠模式进一步降低整体功耗。 - 调试与测试技巧
由于刷新速度慢,调试过程中应耐心等待每次更新结果。
建议先在 TFT/OLED 上验证逻辑与界面布局,再迁移到 E-Ink 平台。
1、单色E-Ink显示屏显示文本
#include <GxEPD2_BW.h> // 引入单色E-Ink显示屏库
#define EPD_CS 5
#define EPD_DC 0
#define EPD_RST 2
#define EPD_BUSY 15
GxEPD2_BW<GxEPD2_213_B72, GxEPD2_213_B72::HEIGHT> epd(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY);
void setup() {
epd.init(115200); // 初始化E-Ink显示屏,设置波特率
epd.setRotation(1); // 设置屏幕旋转方向
epd.fillScreen(GxEPD_WHITE); // 填充屏幕为白色
epd.setTextColor(GxEPD_BLACK); // 设置文本颜色为黑色
epd.setTextSize(2); // 设置文本大小
epd.setCursor(10, 30); // 设置文本起始位置
epd.print("Hello, E-Ink!"); // 显示文本
epd.display(); // 显示内容
epd.hibernate(); // 将显示屏置于休眠模式以节省电量
}
void loop() {
// 空循环,保持显示
}
要点解读:
库选择:使用GxEPD2_BW库,适用于单色E-Ink显示屏。
引脚定义:根据实际连接定义显示屏的控制引脚。
屏幕初始化:通过epd.init初始化显示屏,并设置波特率。
文本显示:使用epd.print函数在指定位置显示文本。
休眠模式:通过epd.hibernate将显示屏置于休眠模式,减少功耗。
2、三色E-Ink显示屏显示文本
#include <GxEPD2_3C.h> // 引入三色E-Ink显示屏库
#include <Fonts/FreeMonoBold9pt7b.h> // 引入字体库
#define EPD_CS 5
#define EPD_DC 0
#define EPD_RST 2
#define EPD_BUSY 15
GxEPD2_3C<GxEPD2_290_C90c, GxEPD2_290_C90c::HEIGHT> epd(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY);
void setup() {
epd.init(115200); // 初始化E-Ink显示屏,设置波特率
epd.setRotation(1); // 设置屏幕旋转方向
epd.fillScreen(GxEPD_WHITE); // 填充屏幕为白色
epd.setTextColor(GxEPD_BLACK); // 设置文本颜色为黑色
epd.setTextSize(2); // 设置文本大小
epd.setCursor(10, 30); // 设置文本起始位置
epd.print("Hello, E-Ink!"); // 显示文本
epd.display(); // 显示内容
epd.hibernate(); // 将显示屏置于休眠模式以节省电量
}
void loop() {
// 空循环,保持显示
}
要点解读:
库选择:使用GxEPD2_3C库,适用于三色E-Ink显示屏。
字体选择:通过#include <Fonts/FreeMonoBold9pt7b.h>引入字体库,使用epd.setFont(&FreeMonoBold9pt7b)设置字体。
文本颜色:可以设置文本颜色为黑色、红色等,例如epd.setTextColor(GxEPD_RED)。
屏幕刷新:使用epd.display函数刷新屏幕,显示文本。
3、使用WaveShare库显示文本
#include <SPI.h>
#include "epd2in9.h"
#include "epdpaint.h"
#define COLORED 0
#define UNCOLORED 1
unsigned char image[1024];
Paint paint(image, 0, 0);
Epd epd;
void setup() {
Serial.begin(9600);
if (epd.Init(lut_full_update) != 0) {
Serial.print("e-Paper init failed");
return;
}
// Memory Frame Must Be Cleared Twice
epd.ClearFrameMemory(0xFF); // bit set = white, bit reset = black
epd.DisplayFrame();
epd.ClearFrameMemory(0xFF); // bit set = white, bit reset = black
epd.DisplayFrame();
// Set Display Settings
paint.SetRotate(ROTATE_270);
paint.SetWidth(24);
paint.SetHeight(296);
// Write The Text Messages To The Display
paint.Clear(UNCOLORED);
paint.DrawStringAt(0, 0, "E-Paper / E-Ink Display", &Font16, COLORED);
epd.SetFrameMemory(paint.GetImage(), 30, 0, paint.GetWidth(), paint.GetHeight());
paint.Clear(UNCOLORED);
paint.DrawStringAt(0, 0, "Arduino Tutorial From", &Font16, COLORED);
epd.SetFrameMemory(paint.GetImage(), 60, 0, paint.GetWidth(), paint.GetHeight());
paint.Clear(UNCOLORED);
paint.DrawStringAt(0, 0, "DeepBlueMbedded.com", &Font20, COLORED);
epd.SetFrameMemory(paint.GetImage(), 90, 0, paint.GetWidth(), paint.GetHeight());
epd.DisplayFrame();
}
void loop() {
// Nothing To Do Here!
}
要点解读:
库选择:使用WaveShare提供的E-Paper库。
初始化:通过epd.Init初始化显示屏,并进行两次清屏操作。
文本绘制:使用Paint类的DrawStringAt方法绘制文本,SetFrameMemory将绘制的内容发送到显示屏。
显示刷新:通过epd.DisplayFrame刷新屏幕,显示文本。
4、静态文本显示(Hello World)
#include <Adafruit_ThinkInk.h>
#define EPD_CS 9
#define EPD_DC 10
#define SRAM_CS 6
#define EPD_RESET 8
#define EPD_BUSY 7
ThinkInk_290_mono_M06 display(EPD_DC, EPD_RESET, EPD_CS, SRAM_CS, EPD_BUSY);
void setup() {
display.begin(thinkink_mono);
display.clearBuffer();
display.setTextSize(2);
display.setCursor(10, 20); // 调整文本位置
display.setTextColor(EPD_BLACK);
display.print("Hello E-Ink!");
display.display(); // 刷新屏幕
}
void loop() {} // 静态显示无需循环
要点解读:
引脚定义:通过#define指定SPI通信引脚(CS、DC、RESET、BUSY)。
初始化:display.begin()初始化屏幕,display.clearBuffer()清空缓冲区。
文本显示:setTextSize()设置字体大小,setCursor()定位光标,print()输出文本。
刷新机制:display()触发屏幕刷新,更新过程需数秒且功耗较高。
5、动态文本更新(温度传感器数据)
#include <Adafruit_ThinkInk.h>
#define TEMP_PIN A0 // 模拟输入引脚(示例)
#define EPD_CS 9
// ... 其他引脚定义同案例1
ThinkInk_290_mono_M06 display(EPD_DC, EPD_RESET, EPD_CS, SRAM_CS, EPD_BUSY);
void setup() {
Serial.begin(9600);
display.begin(thinkink_mono);
}
void loop() {
int tempValue = analogRead(TEMP_PIN); // 模拟读取(实际需替换为传感器库)
float temperature = map(tempValue, 0, 1023, 0, 50); // 示例转换
display.clearBuffer();
display.setTextSize(1);
display.setCursor(0, 0);
display.print("Temp: ");
display.print(temperature);
display.print(" C");
display.display();
delay(5000); // 每5秒刷新一次(避免频繁更新)
}
要点解读:
数据读取:通过analogRead()获取模拟信号(需根据实际传感器调整)。
刷新限制:E-Ink屏幕更新频率低(建议≤3分钟/次),避免损坏。
延迟控制:delay()确保每次更新间隔足够长,延长屏幕寿命。
6、多页文本切换(分页显示)
#include <Adafruit_ThinkInk.h>
#define BUTTON_PIN 2
#define EPD_CS 9
// ... 其他引脚定义同案例1
ThinkInk_290_mono_M06 display(EPD_DC, EPD_RESET, EPD_CS, SRAM_CS, EPD_BUSY);
int currentPage = 0;
String pages[] = {"Page 1: Hello", "Page 2: Arduino", "Page 3: E-Ink"};
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
display.begin(thinkink_mono);
updateDisplay();
}
void loop() {
if (digitalRead(BUTTON_PIN) == LOW) { // 按钮按下检测
currentPage = (currentPage + 1) % 3; // 循环切换页面
updateDisplay();
delay(500); // 防抖延迟
}
}
void updateDisplay() {
display.clearBuffer();
display.setTextSize(1);
display.setCursor(0, 0);
display.print(pages[currentPage]);
display.display();
}
要点解读:
按钮检测:通过digitalRead()检测按钮状态,INPUT_PULLUP启用内部上拉电阻。
页面管理:使用数组存储多页内容,通过索引currentPage切换。
防抖处理:delay()避免按钮抖动导致多次触发。
注意,以上案例只是为了拓展思路,仅供参考。它们可能有错误、不适用或者无法编译。您的硬件平台、使用场景和Arduino版本可能影响使用方法的选择。实际编程时,您要根据自己的硬件配置、使用场景和具体需求进行调整,并多次实际测试。您还要正确连接硬件,了解所用传感器和设备的规范和特性。涉及硬件操作的代码,您要在使用前确认引脚和电平等参数的正确性和安全性。