当前位置:首页 > 工业控制 > 电路设计项目集锦
[导读]彩色电子纸面板以复杂、运行缓慢且文档不全而著称。Seeed Studio reTerminal E1002在开发板上给人留下深刻印象:一块7.3英寸的6色Spectra 6(ACeP)显示屏,分辨率为800×480,内置简洁的白色壁挂式外壳,并由集成的Seeed XIAO ESP32-S3芯片供电。该设备配备microSD卡插槽、带ADC电压检测功能的电池充电器、三个用户按钮、一个被动蜂鸣器以及一个用户LED指示灯。

彩色电子纸面板以复杂、运行缓慢且文档不全而著称。Seeed Studio reTerminal E1002在开发板上给人留下深刻印象:一块7.3英寸的6色Spectra 6(ACeP)显示屏,分辨率为800×480,内置简洁的白色壁挂式外壳,并由集成的Seeed XIAO ESP32-S3芯片供电。该设备配备microSD卡插槽、带ADC电压检测功能的电池充电器、三个用户按钮、一个被动蜂鸣器以及一个用户LED指示灯。

然而,要在其上运行软件却是一大挑战。

Seeed官方文档推荐使用一个过时的GxEPD2分支版本,该版本与上游发布版本存在冲突,并破坏了Adafruit_GFX标准图形库函数。Good Display和Waveshare厂商的代码假设不同的主机板,未正确管理控制引脚,或在控制器关机状态下出现异常。此外,使用标准库循环绘制SD卡位图需要数分钟时间,因为涉及成千上万次冗余的SD寻道调用。

为了解决这个问题,我创建了一个统一的仓库,其中包含了针对三种主要驱动堆栈(上游 GxEPD2、Good Display 厂商代码以及 Waveshare 的 GUI_Paint 图形引擎)经过测试的 Arduino 示例代码。本文将详细介绍引脚布局、硬件陷阱、如何在 PSRAM 中缓冲帧,以及如何从六色面板中获得清晰的色彩渲染效果。

硬件:面板与载板连接

E1002 内部的显示模块是 Good Display 的 GDEP073E01,Waveshare 也以 7.3 英寸电子纸(E)型号销售。该模块使用集成的 Solomon Systech / Good Display ED2208 时序控制器。

载板通过内部 FPC 胶带将面板连接至 XIAO ESP32-S3:

•SCK:GPIO 7(硬件 SPI)

•MOSI:GPIO 9(硬件 SPI)

•CS:GPIO 10(片选,低电平有效)

•DC:GPIO 11(数据/命令选择)

•RST:GPIO 12(硬件复位,低电平有效)

•BUSY:GPIO 13(硬件状态)

一个关键细节是:在 ED2208 上,BUSY 是低电平有效(0 表示正在刷新,1 表示就绪/空闲)。许多单色电子纸控制器在更新时会将 BUSY 拉高。如果您的驱动代码接反了这种极性,就会导致程序要么无限阻塞,要么立即退出等待循环,从而破坏后续写入操作。

SPI 时钟以 2 MHz 的频率稳定运行。若通过内部柔性电缆传输更高频率,可能会导致时钟失真,从而引发像素间歇性丢失或命令字节损坏。

双串行日志

E1002 载板内置一个 USB 到 UART 桥接器,连接至 GPIO 43(TX)和 GPIO 44(RX)。同时,XIAO ESP32-S3 提供了原生的 USB CDC 串行接口。

为了无论插入哪个 USB 端口或显示器,调试过程都变得轻松便捷,仓库中的所有示例都会同时将日志输出到这两个接口:

Arduino IDE 必需设置

每个程序在 Arduino IDE 中必须配置以下三项设置:

- 板子:XIAO_ESP32S3

- 上传速度:115200(更高的速度会导致此板上的串行引导加载器超时)

- PSRAM:OPI PSRAM(用于图像缓冲的必需组件;若未启用,PSRAM 内存分配调用将失败)

上游 GxEPD2 与 Seeed 分支对比

Seeed 的 Wiki 建议用户安装 GitHub 上托管的自定义分支 Seeed_GxEPD2。请勿安装该分支。该分支基于较旧的代码库,与官方库存在冲突,若两者同时存在于 Arduino 库文件夹中,将导致编译器冲突。

相反,直接从Arduino库管理器安装标准的上游库:

搜索Jean-Marc Zingg的GxEPD2。

上游版本的GxEPD2通过GxEPD2_730c_GDEP073E01驱动类,已原生支持该面板。设置显示对象仅需以下内容:

一个800×480分辨率、每像素4位(每字节2个像素)的面板,其完整帧缓冲区需要192,000字节。对于缺乏外部存储的标准微控制器,GxEPD2会将屏幕划分为4或8个水平分页区域,并通过内部SRAM依次重新绘制每个页面。

由于E1002上的XIAO ESP32-S3拥有8MB高速OPI PSRAM,加载图像时性能可以大幅提升。

快速SD卡位图:避免分页循环陷阱

从SD卡绘制位图时常见的陷阱是,在GxEPD2的firstPage() / nextPage()循环中调用display.drawPixel():

如果显示屏被划分为12个分页区域,那么位图的每一行都会被索引并读取12次。对于480行的图像,这意味着在共享的SPI总线上进行5,760次独立的文件寻址操作,导致渲染过程持续数分钟,耗时严重。

解决方案是先将帧缓冲在PSRAM中,然后通过一次写入操作将其传递给控制器。

在仓库中,两个草图展示了这一模式:

1. 原始打包二进制文件(Demo_SDcard)

•图像通过辅助Python脚本(convert_image.py)预先量化,生成一个包含4位字节的扁平192 KB二进制文件。

•ESP32仅需48毫秒即可将全部192,000字节读入PSRAM缓冲区。

•该缓冲区直接通过SPI传输至控制器内存。

•运行时无任何解码开销。

2. 标准24位Windows BMP(Demo_BMP)

•您可以直接将标准的24位未压缩BMP文件拖放到SD卡上,无需先在电脑上进行转换。

•该程序通过读取BMP头信息来提取宽度、高度和像素偏移量。

•每行24位BGR像素都会从SD卡中读取一次。

•邻域欧几里得颜色距离函数将每个24位RGB值量化为6种物理面板颜色之一:

•打包的字节组存储在PSRAM缓冲区中,并以单个数据块形式写入显示屏。从SD卡读取并解码的总时间约为420毫秒。

Good Display厂商驱动:全屏刷新 vs 部分刷新

Good Display提供了GDEP073E01型号的官方C语言源代码。将其移植到reTerminal E1002后,发现两个值得注意的特性。

横向与纵向显示方向

Good Display官方演示图像(gImage_1)是为竖直方向的便携式ID徽章(480x800)设计的。而reTerminal E1002显示器实际安装时为横向(800x480)。

若直接写入纵向数据,会导致图像呈横向显示,并在底部边缘被截断。在我们移植的驱动程序中,image.h 会将图像矩阵顺时针旋转90度,并将其居中显示在800x480的画布上:

Spectra 6上的部分刷新物理机制

第二个示例 GDEP073E01_Partial 使用ED2208命令0x83(指定区域部分刷新),通过绘制一个8x8的棋盘,并以颜色更新每个100x60像素的方格来实现:

Spectra 6 是一款ACeP(高级彩色电子纸)面板。每个微小电极杯包含六种不同的物理颜料(黑色、白色、红色、黄色、蓝色和绿色),这些颜料具有不同的静电荷和物理质量。

在全屏刷新期间,定时控制器会在共享的前表面ITO电极上施加交替的高压波形,持续15至25秒。这种强烈的振荡会将所有颜料完全释放并推动其进入完全饱和的层。

而在局部窗口更新过程中,控制器无法对目标区域外的静态图像进行完整振荡,因为这会导致外部图像受到干扰。局部电场较弱且持续时间较短,因此颜料未能完全分离。结果是,通过部分刷新更新的颜色相比全屏刷新显得明显更浅、更柔和或褪色。

对于较小的数值增量或状态徽章,可使用部分更新,但应定期进行完整刷新,以消除图像模糊并恢复丰富的色彩对比度。

Waveshare 7.3英寸(E)型号与关机故障

Waveshare 提供了一种替代驱动程序,并结合其 GUI_Paint 图形框架。该驱动支持绘制线条、空心和实心矩形、圆形、可缩放的 ASCII 字体(从8磅到24磅)以及中文 GB2312 字符。

在对 Waveshare 驱动程序进行初步测试时,显示屏出现了严重的水平噪声条纹,随后串行控制台出现40秒超时错误:

通过逻辑分析仪和电流表排查问题时,发现了两个明显的缺陷:

1. 冷启动刷新时间超出了40秒的看门狗限制

在室温(约21摄氏度)下,完成所有六个色素状态的完整电泳迁移需要30到44秒。驱动程序内部的忙等待循环设定了固定的40秒超时。在启动时清除屏幕时,计时器在硬件完成前刚刚到期。

2. ED2208 DC/DC升压器睡眠陷阱

当完成一次完整刷新(0x12 DRF)后,ED2208内部的电源时序器会自动关闭高压DC/DC升压电路,以防止电泳膜长期承受直流偏置应力。

Waveshare的原始演示代码仅在setup()中调用了一次EPD_7IN3E_Init()。后续阶段(位图显示、彩色条纹、GUI基本图形)发送数据字节和刷新命令时,并未重新初始化升压器。

由于升压电路已关闭,控制器静默地忽略了0x12命令。BUSY引脚从未变为低电平,ReadBusyH()返回时间为0毫秒,随后的SPI数据写入操作被发送到无电的面板,导致显示屏冻结成杂乱的水平条带。

解决方案

通过以下三个修改永久解决了该问题:

- 在每次刷新阶段前重新初始化:

- 将超时时间扩展至60秒,并为每个阶段设置毫秒级遥测信息。

- 防止FreeRTOS任务饥饿:

每2MHz频率下发送192,000字节数据需要近一秒的连续SPI传输。每30行调用yield()可为ESP32-S3的FreeRTOS看门狗提供反馈,保持后台任务响应性。

一旦这些修复措施到位,Waveshare矢量图形演示在800x480全屏面板上都能清晰渲染。

零电流电池测量

将电池直接连接到电阻分压电路会持续消耗少量静态电流,即使设备处于空闲状态,也会缓慢耗尽电池电量。

E1002载板在电池电压分压与地之间插入一个P沟道MOSFET开关,由GPIO 21控制。保持GPIO 21为低电平可完全关闭分压电路。要进行测量时,先将GPIO 21设置为高电平,稍作延迟让电压稳定,读取GPIO 1上的ADC值,然后立即再次将GPIO 21置为低电平:

指南

•打开Arduino IDE 2.x,并通过Espressif安装esp32板载支持包。

•通过库管理器安装Jean-Marc Zingg开发的GxEPD2。

•在“工具”->“板子”中选择XIAO_ESP32S3。

•将上传速度设置为115200,PSRAM设置为OPI PSRAM。

•从GxEPD2/、good_display/、Waveshare_7in3e/或Peripherals/目录中的任意程序打开,编译并刷入。

本文编译自hackster.io

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭