【花雕学编程】Arduino E-Ink 之循环更新进度条

在这里插入图片描述

《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 等屏幕有着本质区别,特别适用于需要长时间静态显示、低刷新频率、节能的场景。

一、主要特点

  1. 超低功耗
    E-Ink 屏幕仅在刷新画面时消耗电力,显示内容保持不变时几乎不耗电。
    非常适合电池供电设备或太阳能供电系统,可显著延长续航时间。
  2. 阳光下可视性强
    借助环境光反射原理,E-Ink 屏幕在强光下依旧清晰可见,优于 OLED 和 LCD。
    无背光设计使其更适合户外或高亮度环境下的使用。
  3. 黑白/灰阶显示为主
    大多数 E-Ink 屏幕为单色(黑白)或有限灰阶(如 3bit),色彩表现能力弱于 TFT 或 OLED。
    这使得其更适用于文字、图标、仪表等简洁信息的展示。
  4. 刷新率低,不适合动态内容
    刷新一次通常需要几百毫秒至数秒,且频繁刷新会导致残影问题。
    不适合播放视频、动画或实时图形更新类应用。
  5. 驱动复杂度较高
    相比普通字符型 LCD,E-Ink 屏幕需要精确控制波形驱动(Driver Waveform),否则容易出现残影或老化现象。
    通常依赖专用库(如 GxEPD2、Adafruit_EPD)进行图像缓冲和刷新控制。
  6. 寿命长,耐久性好
    E-Ink 屏幕具有很高的耐久性,理论上可支持数十万次刷新,不易老化。
    对比 OLED 的“烧屏”风险,E-Ink 更加稳定可靠。

二、应用场景

  1. 智能标签(Smart Label)
    应用于零售行业,作为货架价格标签、库存管理标签等,可远程更新商品信息。
    示例:超市电子价签系统。
  2. 智能家居显示终端
    显示温湿度、空气质量、日程提醒、门锁状态等信息。
    可作为壁挂式低功耗家庭信息中心。
  3. 便携式电子设备
    如电子书阅读器(Kindle)、智能手表辅助显示界面、户外导航设备等。
    特别适合需要长时间待机、无需频繁刷新的设备。
  4. 农业与环境监测
    在温室大棚、气象站、水质检测点部署低功耗显示屏,展示传感器数据。
    示例:太阳能供电的空气污染监测站显示模块。
  5. 工业与物流追踪
    工业设备状态显示面板、资产追踪标签、运输过程中的温湿度记录仪等。
    支持无线通信 + E-Ink 的组合方案,实现远程监控。

三、注意事项

  1. 刷新策略优化
    避免不必要的刷新操作,尽量采用局部刷新(Partial Refresh)减少闪烁与延迟。
    全局刷新(Full Update)虽然显示效果更好,但耗时较长且易造成视觉不适。
  2. 内存占用问题
    E-Ink 屏幕分辨率较高时,帧缓冲区(Frame Buffer)会占用大量 RAM。
    对于 Arduino UNO/Nano 等低端设备,建议选择小尺寸或使用外部 SRAM 缓冲。
  3. 驱动库的选择与配置
    推荐使用主流开源库如:
    GxEPD2:功能强大,支持多种 E-Ink 模块。
    Adafruit_EPD:适用于 Adafruit 自家模块。
    注意 SPI 速率、引脚映射、复位逻辑是否匹配硬件。
  4. 避免残影与图像老化
    长时间显示相同内容可能导致“图像残留”,称为“残影效应”。
    建议定期执行“清除刷新”(Clear Update)或随机扰动内容布局来缓解。
  5. 电源管理策略
    可结合 Arduino 的休眠模式,在非工作时段关闭屏幕供电或进入低功耗模式。
    使用 MOSFET 控制屏幕电源,进一步降低待机电流。
  6. 开发调试难度较大
    由于刷新速度慢,调试过程中需耐心等待每次更新结果。
    建议先在 TFT/OLED 上验证逻辑,再迁移到 E-Ink 平台。

在这里插入图片描述

在 Arduino 项目中,E-Ink 之循环更新进度条(Cyclic Progress Bar on E-Ink Display) 是一种将任务执行状态以图形化方式呈现在电子墨水屏上的技术。由于 E-Ink 屏幕的刷新机制和功耗特性,这种“动态”进度条的设计需要兼顾显示效果、用户体验与系统资源之间的平衡。

一、主要特点

  1. 低功耗下的“伪动态”更新
    E-Ink 屏幕仅在刷新时消耗电能,因此即使实现“循环更新”的进度条,其整体功耗仍远低于 TFT 或 OLED。
    进度条的变化是“伪动态”的,即通过定时刷新局部区域或整个屏幕来模拟动画效果。
  2. 刷新率限制明显
    刷新一次通常需要几百毫秒到数秒,不适合高频更新。
    因此,进度条的更新频率应控制在合理范围(如每秒一次或更慢),以避免闪烁或残影。
  3. 支持局部刷新(Partial Update)
    部分 E-Ink 模块支持局部刷新功能,可以只更新进度条部分区域,减少全屏刷新带来的延迟和视觉干扰。
    可显著提升用户体验并延长屏幕寿命。
  4. 图形绘制能力有限但足够
    借助图形库(如 GxEPD2、Adafruit GFX)可轻松绘制矩形、填充矩形等基本形状,用于构建进度条。
    虽然不能实现复杂的渐变或色彩过渡,但对于黑白进度条已足够清晰直观。
  5. 适合周期性任务展示
    可用于表示定时任务、传感器采集周期、数据上传过程等,帮助用户理解设备运行状态。

二、应用场景

  1. 智能农业监测系统
    显示土壤湿度采集或灌溉任务的完成进度,提示用户当前阶段。
  2. 远程气象站
    在数据采集过程中,用进度条表示传感器轮询进度或数据打包上传状态。
  3. 电池电量指示器
    结合电压检测模块,用进度条形式显示电池剩余电量,替代传统数字显示。
  4. 物联网设备状态反馈
    在设备启动、配置同步、固件更新等操作中,提供可视化进度反馈。
  5. 教育类嵌入式项目
    教学演示中用于说明任务调度、定时器中断等功能,增强学生对系统行为的理解。

三、注意事项

  1. 刷新策略优化
    避免频繁刷新:建议设定一个合理的刷新间隔(如 500ms~1s),以平衡响应速度与视觉体验。
    优先使用局部刷新:若硬件支持,尽量只刷新进度条所在的区域,而非整屏刷新。
  2. 内存管理
    绘制图形会占用帧缓冲区(Frame Buffer),高分辨率屏幕可能超出低端 Arduino 的 RAM 容量。
    推荐使用小尺寸屏幕(如 2.13"、2.9")或选择支持外部缓存的控制器(如 ESP32)。
  3. 驱动库适配与调试
    使用主流开源库:
    GxEPD2:功能强大,支持多种 E-Ink 模块。
    Adafruit_EPD:适用于 Adafruit 自家模块。
    注意 SPI 速率、引脚映射、复位逻辑是否匹配硬件。
  4. 防止图像残留(残影)
    长时间在同一位置刷新相同内容可能导致残影。
    建议定期执行全屏刷新或轻微扰动进度条位置,防止老化。
  5. 界面设计优化
    合理设置进度条长度与位置,确保在不同分辨率下都能清晰显示。
    可配合文字说明(如百分比)提升信息传达效率。
  6. 电源管理优化
    在非刷新时段关闭屏幕供电,可使用 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); // 设置屏幕旋转方向
}

void loop() {
  for (int i = 0; i <= 100; i++) {
    epd.fillScreen(GxEPD_WHITE); // 清屏
    epd.setTextColor(GxEPD_BLACK); // 设置文本颜色为黑色
    epd.setTextSize(2); // 设置文本大小
    epd.setCursor(10, 30); // 设置文本起始位置
    epd.print("Progress: ");
    epd.print(i);
    epd.print("%");

    epd.fillRect(10, 50, i * 2, 10, GxEPD_BLACK); // 绘制进度条
    epd.display(); // 显示内容
    delay(100); // 控制进度条更新速度
  }
}

要点解读:
进度条绘制:通过epd.fillRect函数绘制进度条,进度条的长度根据当前进度动态调整。
动态更新:使用for循环逐步增加进度条的长度,模拟进度的增加。
屏幕刷新:每次更新进度条后调用epd.display函数刷新屏幕,显示新的进度条。

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() {
  for (int i = 0; i <= 100; i++) {
    epd.fillScreen(GxEPD_WHITE); // 清屏
    epd.setTextColor(GxEPD_BLACK); // 设置文本颜色为黑色
    epd.setTextSize(2); // 设置文本大小
    epd.setCursor(10, 30); // 设置文本起始位置
    epd.print("Progress: ");
    epd.print(i);
    epd.print("%");

    epd.fillRect(10, 50, i * 2, 10, GxEPD_BLACK); // 绘制进度条
    epd.display(); // 显示内容
    delay(100); // 控制进度条更新速度
  }
}

要点解读:
文本提示:在进度条上方显示当前进度的百分比,增强用户对进度的直观感受。
动态更新:进度条的长度和文本提示同步更新,确保信息的一致性。
屏幕刷新:每次更新后刷新屏幕,显示新的进度条和文本提示。

3、模拟任务执行的循环更新进度条

#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() {
  for (int i = 0; i <= 100; i++) {
    epd.fillScreen(GxEPD_WHITE); // 清屏
    epd.setTextColor(GxEPD_BLACK); // 设置文本颜色为黑色
    epd.setTextSize(2); // 设置文本大小
    epd.setCursor(10, 30); // 设置文本起始位置
    epd.print("Task Progress: ");
    epd.print(i);
    epd.print("%");

    epd.fillRect(10, 50, i * 2, 10, GxEPD_BLACK); // 绘制进度条
    epd.display(); // 显示内容
    delay(100); // 控制进度条更新速度
  }
}

要点解读:
任务模拟:通过循环逐步增加进度条的长度,模拟任务的执行过程。
进度条绘制:进度条的长度根据当前进度动态调整,直观显示任务的完成情况。
屏幕刷新:每次更新进度条后调用epd.display函数刷新屏幕,显示新的进度条。

在这里插入图片描述

4、基于ESP32的SPI接口E-Ink进度条(实时数据监控)

#include <GxEPD2_BW.h>
#include <GxEPD2_3C.h>
#include <Fonts/FreeMonoBold9pt7b.h>
 
#define EPD_CS 5
#define EPD_DC 17
#define EPD_RESET 16
#define EPD_BUSY 4
 
GxEPD2_BW<GxEPD2_154_T8, GxEPD2_154_T8::HEIGHT> display(GxEPD2_154_T8(/*CS=*/ EPD_CS, /*DC=*/ EPD_DC, /*RST=*/ EPD_RESET, /*BUSY=*/ EPD_BUSY));
 
void setup() {
  display.init();
  display.setRotation(1);
  display.fillScreen(GxEPD_WHITE);
  display.setTextColor(GxEPD_BLACK);
  display.setFont(&FreeMonoBold9pt7b);
}
 
void loop() {
  static int progress = 0;
  static unsigned long startTime = millis();
  
  // 更新进度条(0-100%)
  display.fillRect(10, 10, 200, 20, GxEPD_WHITE); // 清除旧进度条
  display.fillRect(10, 10, 200 * progress / 100, 20, GxEPD_BLACK); // 绘制新进度条
  
  // 显示剩余时间(假设总耗时10秒)
  int elapsed = (millis() - startTime) / 1000;
  int remaining = max(0, 10 - elapsed);
  display.setCursor(10, 40);
  display.print("剩余时间: ");
  display.print(remaining);
  display.print("秒");
  
  display.display(); // 刷新屏幕
  progress = (progress + 1) % 101; // 循环进度
  delay(1000); // 1秒更新一次
}

要点解读
硬件接口:使用ESP32的SPI接口驱动E-Ink,需配置CS、DC、RST、BUSY引脚。
双缓冲机制:通过fillRect清除旧进度条区域,避免画面闪烁。
时间计算:基于millis()函数计算剩余时间,模拟真实下载场景。

5、基于STM32的I²C接口E-Ink进度条(低功耗设备)

#include <Wire.h>
#include <GxEPD2_BW.h>
 
#define EPD_I2C_ADDR 0x3C
GxEPD2_BW<GxEPD2_154_T8, GxEPD2_154_T8::HEIGHT> display(EPD_I2C_ADDR);
 
void setup() {
  Wire.begin();
  display.init();
  display.setRotation(1);
  display.fillScreen(GxEPD_WHITE);
}
 
void loop() {
  static int batteryLevel = 0;
  
  // 模拟电池充电(每5秒增加10%)
  display.fillRect(10, 10, 200, 20, GxEPD_WHITE);
  display.fillRect(10, 10, 200 * batteryLevel / 100, 20, GxEPD_BLACK);
  
  // 显示电量百分比
  display.setCursor(10, 40);
  display.print("电量: ");
  display.print(batteryLevel);
  display.print("%");
  
  display.display();
  batteryLevel = (batteryLevel + 10) % 101;
  
  // 进入低功耗模式(示例:延迟5秒)
  delay(5000);
  // 可添加STM32的睡眠指令(如HAL_PWR_EnterSTOPMode)
}

要点解读
I²C通信:通过Wire库初始化I²C接口,简化硬件连接。
低功耗设计:使用delay模拟低功耗延迟,实际应用中可结合STM32的STOP模式。
进度条样式:通过调整矩形宽度实现百分比映射,避免复杂计算。

6、基于Arduino Uno的并行接口E-Ink进度条(低成本方案)

#include <GxEPD2_BW.h>
 
// 模拟并行接口引脚定义(需根据实际硬件调整)
#define EPD_D0 2
#define EPD_D1 3
#define EPD_D2 4
#define EPD_D3 5
#define EPD_D4 6
#define EPD_D5 7
#define EPD_D6 8
#define EPD_D7 9
#define EPD_CS 10
#define EPD_DC 11
#define EPD_RST 12
#define EPD_BUSY 13
 
GxEPD2_BW<GxEPD2_154_T8, GxEPD2_154_T8::HEIGHT> display(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY);
 
void setup() {
  display.init();
  display.setRotation(1);
  display.fillScreen(GxEPD_WHITE);
}
 
void loop() {
  static int downloadProgress = 0;
  static int initProgress = 0;
  
  // 更新下载进度条
  display.fillRect(10, 10, 200, 10, GxEPD_WHITE);
  display.fillRect(10, 10, 200 * downloadProgress / 100, 10, GxEPD_BLACK);
  
  // 更新初始化进度条
  display.fillRect(10, 30, 200, 10, GxEPD_WHITE);
  display.fillRect(10, 30, 200 * initProgress / 100, 10, GxEPD_BLACK);
  
  display.display();
  downloadProgress = (downloadProgress + 1) % 101;
  initProgress = (initProgress + 2) % 101; // 不同速度模拟
  
  delay(200); // 快速更新以演示并行效果
}

要点解读
并行接口:直接操作GPIO引脚模拟并行通信,需根据E-Ink模块数据手册调整时序。
多进度条:通过调整Y坐标和高度实现并行显示,适用于复杂任务监控。
性能优化:减少display.display()调用频率,避免频繁刷新导致屏幕残留。

注意,以上案例只是为了拓展思路,仅供参考。它们可能有错误、不适用或者无法编译。您的硬件平台、使用场景和Arduino版本可能影响使用方法的选择。实际编程时,您要根据自己的硬件配置、使用场景和具体需求进行调整,并多次实际测试。您还要正确连接硬件,了解所用传感器和设备的规范和特性。涉及硬件操作的代码,您要在使用前确认引脚和电平等参数的正确性和安全性。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

驴友花雕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值