《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显示屏显示点、线、面图形(Displaying Points, Lines, and Shapes on E-Ink) 是一种利用电子墨水屏(Electronic Paper Display, EPD)展示基本图形元素的技术。与传统的TFT或OLED屏幕相比,E-Ink屏幕以其独特的低功耗、高对比度和阳光下可读性而著称。
1、主要特点
超低功耗
E-Ink屏幕仅在刷新时消耗电能,在静态显示状态下几乎不耗电。
特别适合电池供电设备或需要长时间待机的应用场景。
高对比度与阳光下可视性强
由于其工作原理基于环境光反射,因此在强光环境下依然清晰可见,优于大多数背光源显示屏。
支持多种图形绘制
可以通过库函数绘制点、线、矩形、圆形、椭圆等基本图形元素,构建复杂界面。
有限的颜色表现
大多数E-Ink屏幕提供黑白显示,部分高级型号支持灰阶显示(如3bit灰度),但色彩表现能力有限。
较长的响应时间
刷新一次屏幕通常需要几百毫秒至数秒,不适合频繁更新或动态内容展示。
抗老化设计要求
长时间显示相同内容可能导致“残影”现象,需定期执行全屏刷新来避免屏幕老化。
2、应用场景
智能标签
在零售行业中作为电子价签使用,不仅显示价格信息,还可以展示商品图片或其他促销信息。
智能家居显示器
作为家庭信息中心的一部分,可以展示天气预报图标、安防摄像头截图等。
户外广告牌
利用其低功耗和高可视性的特点,适合用于太阳能供电的户外广告或公告板。
健康监测设备
显示心电图、血糖曲线等医疗数据图表,帮助用户更好地理解和跟踪健康状况。
教育与阅读设备
如电子书阅读器上展示插图、漫画等,增强阅读体验。
物流与资产管理
显示资产的照片或标识,便于识别和管理。
3、需要注意的事项
图像资源管理
确保所有图形都被转换为适合Arduino使用的格式(通常是位图数组),并且妥善管理这些资源以避免超出MCU的内存限制。
对于较大尺寸的图形,考虑使用压缩算法或外部存储器来处理。
性能优化
高分辨率图形可能会导致刷新时间过长,影响用户体验。可以通过降低图形分辨率或使用局部刷新技术来加快速度。
注意减少不必要的重绘操作,采用缓存策略提高效率。
驱动库的选择与配置
使用成熟的开源库(如GxEPD2、Adafruit_EPD)简化开发过程。
根据具体型号调整库参数(如SPI速率、引脚映射、复位逻辑),确保兼容性。
电源管理
在非刷新时段关闭屏幕供电,使用MOSFET控制VCC以进一步降低功耗。
结合Arduino的休眠模式进一步延长设备的工作时间。
界面设计与用户体验
设计时需考虑用户的接受度和识别度,确保每个图形都能准确传达其意图。
合理安排图形尺寸、间距以及颜色对比度,确保在不同光照条件下都能清晰可见。
1、显示点、线、面图形
#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.drawPixel(50, 50, GxEPD_BLACK); // 在(50, 50)位置绘制一个黑色点
// 绘制线
epd.drawLine(10, 10, 100, 100, GxEPD_BLACK); // 从(10, 10)到(100, 100)绘制一条黑色线
// 绘制矩形
epd.drawRect(120, 10, 50, 50, GxEPD_BLACK); // 在(120, 10)位置绘制一个宽50高50的黑色矩形边框
// 绘制填充矩形
epd.fillRect(120, 70, 50, 50, GxEPD_BLACK); // 在(120, 70)位置绘制一个宽50高50的黑色填充矩形
// 绘制圆形
epd.drawCircle(50, 150, 30, GxEPD_BLACK); // 在(50, 150)位置绘制一个半径为30的黑色圆形边框
// 绘制填充圆形
epd.fillCircle(150, 150, 30, GxEPD_BLACK); // 在(150, 150)位置绘制一个半径为30的黑色填充圆形
epd.display(); // 显示内容
epd.hibernate(); // 将显示屏置于休眠模式以节省电量
}
void loop() {
// 空循环,保持显示
}
要点解读:
图形绘制:使用epd.drawPixel绘制点,epd.drawLine绘制线,epd.drawRect和epd.fillRect绘制矩形和填充矩形,epd.drawCircle和epd.fillCircle绘制圆形和填充圆形。
屏幕刷新:通过epd.display函数刷新屏幕,显示图形。
休眠模式:通过epd.hibernate将显示屏置于休眠模式,减少功耗。
2、动态绘制点、线、面图形
#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); // 设置屏幕旋转方向
}
void loop() {
epd.fillScreen(GxEPD_WHITE); // 清屏
// 动态绘制点
for (int i = 0; i < 10; i++) {
int x = random(0, epd.width());
int y = random(0, epd.height());
epd.drawPixel(x, y, GxEPD_BLACK);
}
// 动态绘制线
for (int i = 0; i < 5; i++) {
int x1 = random(0, epd.width());
int y1 = random(0, epd.height());
int x2 = random(0, epd.width());
int y2 = random(0, epd.height());
epd.drawLine(x1, y1, x2, y2, GxEPD_BLACK);
}
// 动态绘制矩形
for (int i = 0; i < 3; i++) {
int x = random(0, epd.width() - 50);
int y = random(0, epd.height() - 50);
epd.drawRect(x, y, 50, 50, GxEPD_BLACK);
}
epd.display(); // 显示内容
delay(5000); // 每5秒刷新一次
}
要点解读:
动态绘制:通过random函数生成随机位置和大小,动态绘制点、线、矩形。
屏幕刷新:每次绘制前清屏,然后刷新屏幕显示新的图形。
刷新间隔:通过delay函数控制屏幕刷新的间隔时间。
3、综合绘图测试
#include <TFT_eSPI.h> // 引入TFT_eSPI库
#define SCREEN_WIDTH 240
#define SCREEN_HEIGHT 240
TFT_eSPI tft = TFT_eSPI();
void setup() {
tft.init();
tft.setRotation(2);
tft.fillScreen(TFT_BLACK);
}
void drawRandomDots() {
for (int i = 0; i < 100; i++) {
int x = random(0, SCREEN_WIDTH);
int y = random(0, SCREEN_HEIGHT);
uint16_t color = tft.color565(random(50, 255), random(50, 255), random(50, 255));
tft.drawPixel(x, y, color);
}
}
void drawMovingLines() {
for (int i = 0; i < SCREEN_WIDTH; i += 10) {
uint16_t color = tft.color565(random(100, 255), random(100, 255), random(100, 255));
tft.drawLine(i, 0, SCREEN_WIDTH - i, SCREEN_HEIGHT, color);
delay(20);
}
}
void drawFilledShapes() {
for (int i = 0; i < 5; i++) {
int x = random(30, SCREEN_WIDTH - 30);
int y = random(30, SCREEN_HEIGHT - 30);
int size = random(20, 50);
uint16_t color = tft.color565(random(50, 255), random(50, 255), random(50, 255));
if (random(0, 2) == 0) {
tft.fillRect(x, y, size, size, color);
} else {
tft.fillCircle(x, y, size / 2, color);
}
}
}
void loop() {
tft.fillScreen(TFT_BLACK);
drawRandomDots();
delay(500);
drawMovingLines();
delay(500);
drawFilledShapes();
delay(500);
}
要点解读:
综合绘图:在一个程序中综合绘制点、线、面图形,测试屏幕的渲染效果。
动态效果:通过随机生成点、线、面的位置和颜色,实现动态绘图效果。
屏幕刷新:每次绘制前清屏,然后刷新屏幕显示新的图形。
刷新间隔:通过delay函数控制屏幕刷新的间隔时间,确保动态效果的流畅性。
4、绘制基本图形(点、线、矩形)
#include "Adafruit_ThinkInk.h"
#define EPD_CS 9
#define EPD_DC 10
#define EPD_RESET 8
#define EPD_BUSY 7
ThinkInk_290_mono_M06 display(EPD_DC, EPD_RESET, EPD_CS, -1, EPD_BUSY); // 2.9英寸单色屏
void setup() {
display.begin(thinkink_mono);
display.clearBuffer();
// 绘制点
display.drawPixel(50, 20, EPD_BLACK);
// 绘制线(从(10,10)到(100,10))
display.drawLine(10, 10, 100, 10, EPD_BLACK);
// 绘制矩形(左上角(20,30),宽80,高40)
display.drawRect(20, 30, 80, 40, EPD_BLACK);
// 填充矩形(左上角(20,80),宽80,高40)
display.fillRect(20, 80, 80, 40, EPD_BLACK);
display.display(); // 刷新屏幕
}
void loop() {
// 空循环
}
要点解读:
图形函数:
drawPixel(x, y, color):绘制单个像素点。
drawLine(x1, y1, x2, y2, color):绘制直线。
drawRect(x, y, width, height, color):绘制空心矩形。
fillRect(x, y, width, height, color):绘制填充矩形。
刷新机制:所有图形操作需在display.display()前完成,刷新后内容保留。
应用场景:适合绘制简单界面(如按钮边框、网格线)。
5、动态进度条(水平填充)
#include "Adafruit_ThinkInk.h"
#define EPD_CS 9
#define EPD_DC 10
#define EPD_RESET 8
#define EPD_BUSY 7
ThinkInk_290_mono_M06 display(EPD_DC, EPD_RESET, EPD_CS, -1, EPD_BUSY);
int progress = 0;
void setup() {
display.begin(thinkink_mono);
display.clearBuffer();
display.drawRect(10, 50, 100, 10, EPD_BLACK); // 进度条边框
display.display();
}
void loop() {
if (progress <= 100) {
updateProgress(progress);
progress += 10;
delay(2000); // 每2秒更新一次
}
}
void updateProgress(int value) {
display.clearBuffer();
display.drawRect(10, 50, 100, 10, EPD_BLACK);
int width = map(value, 0, 100, 0, 100);
display.fillRect(10, 50, width, 10, EPD_BLACK); // 填充部分进度
display.display();
}
要点解读:
动态更新:通过fillRect实现进度条填充效果,每次更新前调用clearBuffer()清除旧内容。
刷新策略:每2秒更新一次,避免频繁刷新损坏屏幕。
应用场景:适合低频状态指示(如充电进度、任务进度)。
6、绘制圆形和三角形(几何图形)
#include "Adafruit_ThinkInk.h"
#define EPD_CS 9
#define EPD_DC 10
#define EPD_RESET 8
#define EPD_BUSY 7
ThinkInk_290_mono_M06 display(EPD_DC, EPD_RESET, EPD_CS, -1, EPD_BUSY);
void setup() {
display.begin(thinkink_mono);
display.clearBuffer();
// 绘制空心圆(中心(60,40),半径30)
display.drawCircle(60, 40, 30, EPD_BLACK);
// 绘制填充圆(中心(60,100),半径20)
display.fillCircle(60, 100, 20, EPD_BLACK);
// 绘制三角形(三点坐标)
Point p1 = Point(10, 70);
Point p2 = Point(50, 110);
Point p3 = Point(110, 70);
display.drawTriangle(p1, p2, p3, EPD_BLACK);
display.display();
}
void loop() {
// 空循环
}
要点解读:
扩展图形函数:
drawCircle(x, y, radius, color):绘制空心圆。
fillCircle(x, y, radius, color):绘制填充圆。
drawTriangle(p1, p2, p3, color):绘制三角形(需定义Point结构体)。
坐标计算:需手动计算图形坐标,电子墨水屏分辨率较低(如296x128),适合简单图形。
应用场景:适合绘制仪表盘、图标等静态界面。
注意,以上案例只是为了拓展思路,仅供参考。它们可能有错误、不适用或者无法编译。您的硬件平台、使用场景和Arduino版本可能影响使用方法的选择。实际编程时,您要根据自己的硬件配置、使用场景和具体需求进行调整,并多次实际测试。您还要正确连接硬件,了解所用传感器和设备的规范和特性。涉及硬件操作的代码,您要在使用前确认引脚和电平等参数的正确性和安全性。