Neste tutorial, vais aprender a usar o Waveshare 3-inch 4-color E-paper display com um ESP32.
O módulo de ecrã E-paper de 3 polegadas e 4 cores da Waveshare é um excelente hardware, mas o Demo software só tem exemplos para Arduino, STM32 e Raspberry. Portanto, se quiseres usar o ecrã com um ESP32, estás sem sorte.
Além disso, o exemplo do Arduino apenas mostra como exibir uma imagem estática pré-feita, não como criar e mostrar conteúdo dinamicamente, por exemplo, um relógio a funcionar ou uma estação meteorológica.
Seria ótimo se pudéssemos usar a biblioteca GxEPD2, mas em dezembro de 2024 ainda não tem driver para o E-paper de 3 polegadas e 4 cores. Por isso, implementei uma biblioteca simples (epd4c), que faz essencialmente o mesmo.
Neste tutorial, mostro-te como fazer o código de exemplo do Arduino funcionar com um ESP32, como criar conteúdo dinamicamente usando uma canvas e como usar a biblioteca epd4c.
Peças Necessárias
Estou a usar o ESP32 lite como microprocessador, porque é barato e tem interface para bateria. Como os ecrãs E-paper consomem muito pouca energia, são uma ótima escolha para projetos alimentados a bateria, e o ESP32 lite encaixa bem aqui. No entanto, qualquer outro ESP32 também funciona.
Obviamente, também vais precisar do módulo de ecrã E-paper de 3 polegadas e 4 cores listado abaixo. Testei o código com esse, mas deve funcionar também com o 2.13-inch 4-color E-Paper ou o 2.66-inch 4-color E-Paper. Contudo, não suporta ecrãs a 3 cores ou preto e branco.

Ecrã E-paper de 3 polegadas e 4 cores

ESP32 lite

Cabo USB de Dados

Conjunto de Fios Dupont

Breadboard
Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.
Ecrã E-paper de 3″ e 4 cores
O ecrã E-paper usado neste projeto é um módulo de 3 polegadas, com resolução de 400×168 pixels, 4 cores (branco, preto, vermelho, amarelo), tempo de atualização de 12 segundos (apenas atualização total suportada) e um controlador embutido com interface SPI.

Note que o módulo tem um pequeno jumper/chave na parte de trás para alternar entre SPI de 4 fios e SPI de 3 fios. Vamos usar o SPI de 4 fios por defeito aqui, por isso não precisas de alterar nada.

O módulo funciona a 3.3V ou 5V, tem uma corrente de sono muito baixa de 0.01µA e consome cerca de 60mW durante a atualização. Para mais informações sobre ecrãs E-paper em geral, vê o tutorial Interfacing Arduino To An E-ink Display.
Abaixo está o datasheet do ecrã e também vê o Waveshare manual:
Ligação do ecrã E-paper de 4 cores ao ESP32
Nesta secção vamos ligar o ecrã E-paper a um ESP32 lite. A imagem seguinte mostra toda a ligação entre o ESP32 e o ecrã para alimentação e interface SPI.

Podes alimentar o ecrã com 3.3V ou 5V, mas o ESP32-lite só tem saída de 3.3V. Nota que tens de usar os pinos SPI hardware do microcontrolador. No caso do ESP32-lite, são os pinos 18 e 23. Abaixo está uma tabela com todas as ligações para conveniência.
| Ecrã E-paper | ESP32 lite |
|---|---|
| CS/SS | 5 |
| SCL/SCK | 18 |
| SDA/DIN/MOSI | 23 |
| BUSY | 4 |
| RES/RST | 16 |
| DC | 17 |
| VCC | 3.3V |
| GND | G |
Fazer o código de demonstração funcionar com ESP32
Se descarregares o Demo software para o ecrã E-paper da Waveshare, vais encontrar uma pasta dentro desse ficheiro zip chamada Arduino/epd3in0g. Lá dentro está um sketch chamado epd3in0g.ino que essencialmente produz a seguinte imagem no ecrã:

Aqui está o trecho reduzido desse código de exemplo que produz a imagem. Podes ver que cria o objeto do ecrã epd, inicializa-o, mostra os dados da imagem e depois coloca o ecrã em modo de sono:
#include "epd3in0g.h"
#include "imagedata.h"
Epd epd;
void setup() {
epd.Init();
epd.Display(IMAGE_DATA);
epd.Sleep();
}
void loop() { }
Este código não funciona num ESP32. No entanto, podes fazê-lo funcionar seguindo os passos abaixo (vê este blog post para mais contexto):
- Muda
const unsigned charparaunsigned charemimagedata.cppeimagedata.h - Muda
#include <avr/pgmspace>para#include <pgmspace>emimagedata.h - Muda as definições dos pinos em
epdif.hpara usar os pinos SPI hardware do ESP32 - Adiciona
SPI.endTransaction();à funçãoIfInit()emepdif.cpp
Aqui estão as definições dos pinos que precisas de usar em epdif.h:
#define RST_PIN 16 #define DC_PIN 17 #define CS_PIN 5 #define BUSY_PIN 4
e aqui está o código em epdif.cpp que tens de mudar de
int EpdIf::IfInit(void) {
...
SPI.begin();
SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
return 0;
}
para este código adicionando uma linha (endTransaction):
int EpdIf::IfInit(void) {
...
SPI.begin();
SPI.endTransaction(); // <== ADD THIS LINE
SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
return 0;
}
Com essas alterações, o código de exemplo deve funcionar. No entanto, ainda está limitado à exibição de imagens estáticas. Na próxima secção, mostro-te uma pequena adição que permite usar a biblioteca gráfica Adafruit_GFX para mostrar conteúdo dinamicamente, como texto e gráficos.
Desenhar no ecrã E-paper de 4 cores usando a canvas Adafruit_GFX
A biblioteca Adafruit_GFX é uma biblioteca gráfica que fornece um conjunto comum de graphics primitives (texto, pontos, linhas, círculos, etc.). Basta instalá-la via Library Manager como de costume. Após a instalação, deve aparecer no Library Manager assim:

A biblioteca Adafruit_GFX tem o conceito de “canvas” que te permite desenhar num buffer do ecrã (=canvas) em segundo plano (sem mostrar). Abaixo está um trecho de código que cria uma canvas de 8 bits de profundidade com as dimensões do ecrã E-paper.
#include "Adafruit_GFX.h"
GFXcanvas8 canvas(EPD_WIDTH, EPD_HEIGHT);
void setup() {
canvas.setRotation(1);
canvas.fillScreen(WHITE);
canvas.fillCircle(200, 84, 60, RED);
}
Depois define a orientação do buffer/ecrã, preenche o buffer com branco e desenha um círculo vermelho. Como o buffer é essencialmente uma imagem, seria ótimo se pudéssemos usar o seguinte código para mostrar o desenho no buffer no E-paper:
epd.Display(canvas.getBuffer());
No entanto, o E-paper de 4 cores usa uma imagem comprimida, onde quatro pixels são comprimidos num byte para poupar memória. Como só há quatro cores, cada cor pode ser representada por 2 bits:
| Cor | Bits |
|---|---|
| preto | 00 |
| branco | 01 |
| amarelo | 10 |
| vermelho | 11 |
O que significa que, se tivermos uma sequência de quatro pixels com as cores preto, branco, amarelo e vermelho na imagem original, podemos comprimi-la num byte (00011011 = 0x1B) assim:

Tens de fazer isto para todos os blocos de 4 pixels na imagem original para criar uma imagem comprimida que pode ser mostrada no E-paper via epd.Display(image). A seguinte função compress() pega no buffer do canvas e comprime-o como descrito:
uint8_t* compress(GFXcanvas8& canvas) {
uint8_t* buf = canvas.getBuffer();
int n = canvas.width() * canvas.height();
int ci = 0;
for (int i = 0; i < n; i += 4) {
uint8_t com = buf[i];
com = (com << 2) | buf[i + 1];
com = (com << 2) | buf[i + 2];
com = (com << 2) | buf[i + 3];
buf[ci++] = com;
}
return buf;
}
Note que reutiliza o buffer do ecrã. Portanto, não é necessária memória adicional para a imagem comprimida, mas não podes desenhar na canvas depois de comprimida. Terás de a limpar primeiro.
Com a função compress() podes criar conteúdo dinamicamente e mostrar no E-paper. A estrutura do código é esta:
Epd epd;
GFXcanvas8 canvas(EPD_WIDTH, EPD_HEIGHT);
void setup() {
canvas.setRotation(1);
canvas.fillScreen(WHITE);
... // more graphics code
epd.Init();
epd.Display(compress(canvas)); // display compressed image
epd.Sleep();
}
Aqui está um exemplo completo com tudo incluído:
#include "Adafruit_GFX.h"
#include "epd3in0g.h"
Epd epd;
GFXcanvas8 canvas(EPD_WIDTH, EPD_HEIGHT);
uint8_t* compress(GFXcanvas8& canvas) {
uint8_t* buf = canvas.getBuffer();
int n = canvas.width() * canvas.height();
int ci = 0;
for (int i = 0; i < n; i += 4) {
uint8_t com = buf[i];
com = (com << 2) | buf[i + 1];
com = (com << 2) | buf[i + 2];
com = (com << 2) | buf[i + 3];
buf[ci++] = com;
}
return buf;
}
void setup() {
canvas.setRotation(1);
canvas.fillScreen(red);
canvas.fillCircle(200, 84, 50, yellow);
canvas.setCursor(190, 80);
canvas.setTextColor((black));
canvas.print("Test");
epd.Init();
epd.Display(compress(canvas));
epd.Sleep();
}
void loop() {
}
Se carregares e executares este código, deverás ver um círculo amarelo num fundo vermelho com o texto “Test” no meio:

compress()Embora o código acima funcione, é um pouco complicado de usar. Primeiro, tens de integrar os ficheiros do código de demonstração da Waveshare (epd3in0g.h, epd3in0g.cpp, epdif.h, epdif.cpp) em cada novo projeto que use o ecrã E-paper. Segundo, tens de reimplementar a função compress() cada vez.
Por isso, criei uma pequena biblioteca chamada epd4c, que evita tudo isso. Só tens de a instalar e depois podes usá-la independentemente do código de demonstração. Na próxima secção, mostro como funciona.
Desenhar no ecrã E-paper de 4 cores usando a biblioteca epd4c
Para instalar a epd4c Library, vai ao epd4c_arduino_lib github repo e clica no botão verde “Code“. Depois clica em “Download Zip” como mostrado abaixo:

Depois vai a “Sketch" -> "Include Library" -> "Add .Zip Library..” e seleciona o ficheiro “epd4c_arduino_lib-main.zip” que acabaste de descarregar:

Com a biblioteca epd4c (e a biblioteca Adafruit_GFX), escrever texto e desenhar no ecrã E-paper de 4 cores fica muito mais fácil.
Código de exemplo
Aqui está um código de exemplo. Desenha uma série de círculos coloridos junto com um texto centrado no ecrã. Como podes ver, já não é necessário um canvas separado nem usar o código de demonstração da Waveshare.
#include "epd4c.h"
#define RST_PIN 16
#define DC_PIN 17
#define CS_PIN 5
#define BUSY_PIN 4
#define EPD_WIDTH 168
#define EPD_HEIGHT 400
Epd4c epd(EPD_WIDTH, EPD_HEIGHT, RST_PIN, DC_PIN, CS_PIN, BUSY_PIN);
void setup() {
epd.init();
epd.setRotation(1);
epd.fillScreen(WHITE);
epd.fillCircle(200, 84, 60, RED);
epd.fillCircle(200, 84, 50, YELLOW);
epd.fillCircle(200, 84, 40, BLACK);
epd.fillCircle(200, 84, 30, WHITE);
epd.setCursor(190, 80);
epd.setTextColor((BLACK));
epd.print("Test");
epd.display();
epd.sleep();
}
void loop() {}
Vamos decompor o código em componentes para melhor compreensão.
Inclusão da Biblioteca
Começamos por incluir a biblioteca epd4c para controlar o ecrã E-paper, que é uma extensão da biblioteca Adafruit_GFX canvas, e por isso suporta todas as graphics primitives da biblioteca Adafruit_GFX.
#include "epd4c.h"
Definições dos Pinos
De seguida, definimos os pinos usados para ligar o ecrã E-paper ao ESP32. Nota que os pinos SPI não podem ser definidos. Tens de usar e ligar aos pinos SPI hardware por defeito do teu microcontrolador.
#define RST_PIN 16 #define DC_PIN 17 #define CS_PIN 5 #define BUSY_PIN 4
Dimensões do Ecrã
Também definimos a largura e altura do ecrã E-paper. Como mencionado, o código deve funcionar para outros ecrãs E-paper de 4 cores, com dimensões diferentes, mas não testei isso.
#define EPD_WIDTH 168 #define EPD_HEIGHT 400
Criação do Objeto do Ecrã
Aqui, criamos uma instância da classe Epd4c, passando as dimensões do ecrã e as definições dos pinos como parâmetros. Este objeto será usado para controlar o ecrã durante o programa.
Epd4c epd(EPD_WIDTH, EPD_HEIGHT, RST_PIN, DC_PIN, CS_PIN, BUSY_PIN);
Função Setup
Na função setup(), inicializamos o ecrã E-paper e configuramos as suas definições. Aqui definimos a rotação do ecrã, preenchemos o ecrã com branco e desenhamos vários círculos sobrepostos de cores e tamanhos diferentes.
void setup() {
epd.init();
epd.setRotation(1);
epd.fillScreen(WHITE);
epd.fillCircle(200, 84, 60, RED);
epd.fillCircle(200, 84, 50, YELLOW);
epd.fillCircle(200, 84, 40, BLACK);
epd.fillCircle(200, 84, 30, WHITE);
epd.setCursor(190, 80);
epd.setTextColor((BLACK));
epd.print("Test");
epd.display();
epd.sleep();
}
A saída no ecrã E-paper será a seguinte

onde
epd.init();inicializa o ecrã.epd.setRotation(1);define a orientação do ecrã.epd.fillScreen(WHITE);preenche todo o ecrã com cor branca.- As funções
fillCircle()desenham círculos de vários raios e cores nas coordenadas especificadas (200, 84). epd.setCursor(190, 80);define a posição para o texto a imprimir.epd.setTextColor((BLACK));define a cor do texto para preto.epd.print("Test");imprime o texto “Test” no ecrã.epd.display();atualiza o ecrã com os gráficos desenhadosepd.sleep();coloca o ecrã em modo de sono para poupar energia.
Função Loop
A função loop() está vazia neste exemplo, o que significa que, uma vez concluído o setup, o programa não executa mais ações. O ecrã permanecerá em modo de sono e continuará a mostrar a imagem, mesmo quando o ESP32 estiver desligado.
void loop() {}
Se quiseres atualizar o conteúdo continuamente, por exemplo, para mostrar um relógio a funcionar, colocarias o código gráfico na função loop. Vê os tutoriais Digital Clock on e-Paper Display ou Weather Station on e-Paper Display para exemplos.
E é tudo!
Conclusões
Neste tutorial aprendeste a controlar o ecrã E-paper de 3 polegadas e 4 cores da Waveshare com um ESP32.
Mostrei-te como alterar o código de demonstração do Arduino para funcionar com um ESP32. Também usamos a Adafruit_GFX canvas para criar conteúdo dinamicamente para o ecrã E-paper. E finalmente, apresentei-te a biblioteca epd4c.
A biblioteca epd4c faz essencialmente o mesmo que a biblioteca GxEPD2, mas infelizmente esta última atualmente não suporta o ecrã E-paper de 3 polegadas e 4 cores da Waveshare. Eu preferia que suportasse. Poderia ter estendido a biblioteca GxEPD2, mas fui preguiçoso e simplesmente limpei e estendi o código de demonstração da Waveshare para criar a biblioteca epd4c.
Se tiveres alguma dúvida, não hesites em deixar nos comentários.
Boas experiências a criar ; )

