《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 之显示 BMP 图像(Displaying BMP Images on E-Ink Display) 是一种将静态图像信息通过电子墨水屏(Electronic Paper Display, EPD)呈现的技术。BMP 格式因其结构简单、无需压缩算法支持,特别适合嵌入式系统使用。
一、主要特点
- 低功耗下的图像展示
E-Ink 屏幕仅在刷新时消耗电能,一旦图像稳定后几乎不耗电。
非常适合电池供电或远程部署的图像展示场景。 - 黑白/灰阶为主,色彩受限
大多数 E-Ink 屏幕为单色(黑白)或灰阶(如 3bit 灰度),不支持彩色显示。
BMP 图像需预处理为二值化或灰度图像,适配屏幕特性。 - 支持本地存储与 SPI 加载
可通过 SD 卡读取 BMP 文件,并通过 SPI 接口加载到帧缓冲区后显示。
对于资源有限的 MCU(如 ATmega328P),建议使用小尺寸图像(如 128x64、296x128)。 - 刷新率较低但适合静态图像
刷新一次通常需要几百毫秒至数秒,不适合动画或频繁更新。
适用于静态图像展示,如图标、状态图、二维码等。 - 抗老化设计要求
长时间显示相同图像可能导致“残影”现象,影响显示质量。
建议定期执行全屏刷新清除残留图像。 - 内存占用较大
高分辨率图像需要较大的 RAM 存储帧缓冲区(Frame Buffer),对低端 Arduino 控制器构成挑战。
推荐使用 ESP32、Teensy 或 RP2040 等高性能平台支持更高分辨率图像。
二、应用场景
- 智能价签(Electronic Shelf Label, ESL)
显示商品图片、条形码、促销海报等内容,提升零售体验。
示例:基于 ESP32 的无线电子价签终端。 - 智能家居控制面板
显示设备图标、状态指示图、天气预报图像等辅助信息。
示例:家庭能源管理系统的可视化界面。 - 户外广告与公告牌
展示静态宣传图、通知、活动海报等信息。
示例:公园导览图、公交站牌、博物馆展品介绍。 - 教育与阅读设备
显示插图、图表、漫画等内容,增强电子书阅读器的视觉体验。
示例:Arduino + E-Ink 构建简易电子书阅读器。 - 物流与资产管理
显示资产编号、照片、二维码等信息,便于识别和追踪。
示例:带 RFID 的资产追踪标签。 - 医疗与健康监测
显示心电图、血糖曲线、体温趋势图等医学图像。
示例:便携式健康记录仪的数据展示模块。
三、注意事项
- 图像预处理优化
使用图像处理软件(如 Photoshop、GIMP)或专用工具(如 ImageConverter Plus、BmpToCArray)将图像转换为适合 E-Ink 显示的黑白或灰度图像。
对图像进行裁剪、缩放、去噪等操作,提高显示效果并降低内存占用。 - 合理选择图像尺寸
小型 E-Ink 屏幕(如 1.54"、2.9")建议使用不超过 200×100 像素的图像。
避免加载超出屏幕分辨率的图像,防止显示异常或溢出。 - 驱动库的选择与适配
推荐使用主流开源库:
GxEPD2:功能强大,支持多种 E-Ink 模块。
Adafruit_EPD:适用于 Adafruit 自家模块。
注意 SPI 速率、引脚映射、复位逻辑是否匹配硬件。 - 电源管理优化
在非刷新时段关闭屏幕供电,可使用 MOSFET 或继电器控制 VCC。
结合 Arduino 的休眠模式进一步降低整体功耗。 - 防止图像残留(残影)
定期执行“全屏刷新”,避免长时间显示相同图像导致老化。
若图像内容长期不变,建议每隔几天手动刷新一次。 - 内存与性能限制
对于低端控制器(如 Arduino UNO/Nano),建议使用小尺寸图像或外部 SRAM 缓冲。
考虑使用 ESP32、Teensy 等高性能平台来支持更高分辨率图像。
1、基础BMP图像显示
#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);
// 包含BMP图像数据
#include "bmp_image.h"
void setup() {
epd.init(115200); // 初始化E-Ink显示屏,设置波特率
epd.setRotation(1); // 设置屏幕旋转方向
epd.fillScreen(GxEPD_WHITE); // 填充屏幕为白色
epd.drawBitmap(0, 0, bmp_image, 212, 104, GxEPD_BLACK); // 显示BMP图像
epd.display(); // 显示内容
epd.hibernate(); // 将显示屏置于休眠模式以节省电量
}
void loop() {
// 空循环,保持显示
}
要点解读:
图像加载:通过epd.drawBitmap函数加载并显示BMP图像,需要将图像转换为C数组。
屏幕刷新:使用epd.display函数刷新屏幕,显示图像。
休眠模式:通过epd.hibernate将显示屏置于休眠模式,减少功耗。
2、动态更新BMP图像
#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);
// 包含BMP图像数据
#include "bmp_image1.h"
#include "bmp_image2.h"
void setup() {
epd.init(115200); // 初始化E-Ink显示屏,设置波特率
epd.setRotation(1); // 设置屏幕旋转方向
}
void loop() {
epd.fillScreen(GxEPD_WHITE); // 清屏
epd.drawBitmap(0, 0, bmp_image1, 212, 104, GxEPD_BLACK); // 显示第一张图像
epd.display(); // 显示内容
delay(5000); // 延迟5秒
epd.fillScreen(GxEPD_WHITE); // 清屏
epd.drawBitmap(0, 0, bmp_image2, 212, 104, GxEPD_BLACK); // 显示第二张图像
epd.display(); // 显示内容
delay(5000); // 延迟5秒
}
要点解读:
动态更新:通过定时切换不同的BMP图像,实现动态效果。
屏幕刷新:每次更新图像时调用epd.display函数刷新屏幕。
延迟控制:使用delay函数控制图像切换的时间间隔。
3、结合文本的BMP图像显示
#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);
// 包含BMP图像数据
#include "bmp_image.h"
void setup() {
epd.init(115200); // 初始化E-Ink显示屏,设置波特率
epd.setRotation(1); // 设置屏幕旋转方向
epd.fillScreen(GxEPD_WHITE); // 填充屏幕为白色
epd.drawBitmap(0, 0, bmp_image, 212, 104, GxEPD_BLACK); // 显示BMP图像
epd.setTextColor(GxEPD_BLACK); // 设置文本颜色为黑色
epd.setTextSize(2); // 设置文本大小
epd.setCursor(10, 120); // 设置文本起始位置
epd.print("Hello, E-Ink!"); // 显示文本
epd.display(); // 显示内容
epd.hibernate(); // 将显示屏置于休眠模式以节省电量
}
void loop() {
// 空循环,保持显示
}
要点解读:
图像与文本结合:在显示BMP图像的同时,添加文本说明。
文本显示:使用epd.print函数在指定位置显示文本。
屏幕刷新:使用epd.display函数刷新屏幕,显示图像和文本。
4、电子相册(展示艺术画作)
功能:周期性显示不同艺术画作的BMP图像,支持低功耗运行。
代码示例(基于Adafruit GFX库):
#include <Adafruit_GFX.h>
#include <GxEPD2_BW.h>
#include <SPI.h>
#define EPD_CS 10
#define EPD_DC 9
#define EPD_RESET 8
GxEPD2_BW<GxEPD2_290, GxEPD2_290::HEIGHT> display(EPD_DC, EPD_RESET, EPD_CS);
#include "artwork1.h" // 预转换的BMP图像数组
#include "artwork2.h"
void setup() {
display.init();
display.setRotation(1);
display.fillScreen(GxEPD_WHITE);
// 显示第一幅画作
display.drawBitmap(0, 0, artwork1, GxEPD2_290::WIDTH, GxEPD2_290::HEIGHT, GxEPD_BLACK);
display.display();
delay(5000); // 显示5秒
// 局部刷新显示第二幅画作(减少闪烁)
display.drawBitmap(0, 0, artwork2, GxEPD2_290::WIDTH, GxEPD2_290::HEIGHT, GxEPD_BLACK);
display.display(true); // true表示局部刷新
}
void loop() {
// 低功耗模式(如使用RTC唤醒)
ESP.deepSleep(300e6); // 300秒后唤醒(仅ESP32/ESP8266)
}
要点:
图像预处理:需使用工具(如LCD Image Converter)将BMP转换为C数组格式。
局部刷新:display.display(true)减少全屏刷新次数,延长屏幕寿命。
低功耗:结合deepSleep实现长期运行,适合太阳能供电场景。
5、环境监测站(结合传感器图标)
功能:显示温度/湿度传感器数据,并用BMP图标表示状态(如太阳/雨滴)。
代码示例(基于ESP32 + 三色E-Ink):
#include <GxEPD2_3C.h>
#include <Fonts/FreeSans9pt7b.h>
#define EPD_CS 5
#define EPD_DC 17
#define EPD_RESET 16
GxEPD2_3C<GxEPD2_290_T5, GxEPD2_290_T5::HEIGHT> display(EPD_DC, EPD_RESET, EPD_CS);
#include "sun_icon.h" // 预转换的BMP图标
#include "rain_icon.h"
void setup() {
display.init();
display.setRotation(1);
display.fillScreen(GxEPD_WHITE);
// 显示温度数据(需连接传感器)
display.setFont(&FreeSans9pt7b);
display.setTextColor(GxEPD_BLACK);
display.setCursor(10, 20);
display.print("温度: 25C");
// 根据条件显示图标(示例固定显示太阳)
display.drawBitmap(100, 10, sun_icon, 50, 50, GxEPD_BLACK);
display.display();
}
void loop() {}
要点:
条件显示:通过传感器数据动态切换图标(如温度>30℃显示红色警告图标)。
三色屏幕:利用红色高亮关键数据(如setTextColor(GxEPD_RED))。
图标对齐:使用drawBitmap(x, y, …)精确定位,避免图像重叠。
6、零售货架标签(动态促销图标)
功能:在价格标签旁显示促销图标(如“特价”或“新品”)。
代码示例(基于Arduino Uno + 小尺寸E-Ink):
#include <GxEPD2_BW.h>
#include <Fonts/FreeMonoBold9pt7b.h>
#define EPD_CS 4
#define EPD_DC 7
#define EPD_RESET 6
GxEPD2_BW<GxEPD2_154_D67, GxEPD2_154_D67::HEIGHT> display(EPD_DC, EPD_RESET, EPD_CS);
#include "sale_icon.h" // 促销图标
void setup() {
display.init();
display.setRotation(0);
display.fillScreen(GxEPD_WHITE);
// 显示价格文本
display.setFont(&FreeMonoBold9pt7b);
display.setCursor(10, 10);
display.print("价格: $19.99");
// 显示促销图标
display.drawBitmap(80, 5, sale_icon, 40, 40, GxEPD_BLACK);
display.display();
}
void loop() {}
要点:
图标尺寸:需适配屏幕分辨率(如1.54英寸屏建议40x40像素图标)。
存储优化:BMP数组较大时,使用PROGMEM存储(如const uint8_t sale_icon[] PROGMEM = {…})。
动态更新:通过串口接收新图标数据(需扩展代码实现动态加载)。
注意,以上案例只是为了拓展思路,仅供参考。它们可能有错误、不适用或者无法编译。您的硬件平台、使用场景和Arduino版本可能影响使用方法的选择。实际编程时,您要根据自己的硬件配置、使用场景和具体需求进行调整,并多次实际测试。您还要正确连接硬件,了解所用传感器和设备的规范和特性。涉及硬件操作的代码,您要在使用前确认引脚和电平等参数的正确性和安全性。