En este tutorial aprenderás cómo usar el Waveshare 3-inch 4-color E-paper display con un ESP32.
El módulo de pantalla E-paper de 3 pulgadas y 4 colores de Waveshare es un buen hardware, pero el Demo software solo tiene ejemplos para Arduino, STM32 y Raspberry. Así que, si quieres usar la pantalla con un ESP32, estás sin suerte.
Además, el ejemplo de Arduino solo muestra cómo mostrar una imagen estática predefinida, pero no cómo crear y mostrar contenido dinámico, por ejemplo, un reloj en marcha o una estación meteorológica.
Sería genial si pudiéramos usar la biblioteca GxEPD2, pero a diciembre de 2024 no tiene un controlador para la pantalla E-paper de 3 pulgadas y 4 colores. Por eso, implementé una biblioteca simple (epd4c), que hace esencialmente lo mismo.
En este tutorial, te mostraré cómo hacer funcionar el código de ejemplo de Arduino con un ESP32, cómo crear contenido dinámico usando un canvas y cómo usar la biblioteca epd4c.
Partes necesarias
Estoy usando el ESP32 lite como microprocesador, porque es barato y tiene interfaz para batería. Dado que las pantallas E-paper consumen muy poca energía, son una excelente opción para proyectos con batería, y el ESP32 lite encaja bien aquí. Sin embargo, cualquier otro ESP32 también funcionará.
Obviamente también necesitarás el módulo de pantalla E-paper de 3 pulgadas y 4 colores listado abajo. Probé el código con ese, pero debería funcionar también con el 2.13-inch 4-color E-Paper o el 2.66-inch 4-color E-Paper. Sin embargo, no soporta pantallas de 3 colores o blanco y negro.

Pantalla E-paper de 3 pulgadas y 4 colores

ESP32 lite

Cable USB de datos

Juego de cables Dupont

Protoboard
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.
Pantalla E-paper de 3″ y 4 colores
La pantalla E-paper usada en este proyecto es un módulo de 3 pulgadas, con resolución de 400×168 píxeles, 4 colores (blanco, negro, rojo, amarillo), tiempo de refresco de 12 segundos (solo soporta refresco completo) y un controlador integrado con interfaz SPI.

Ten en cuenta que el módulo tiene un pequeño jumper o interruptor en la parte trasera para cambiar de SPI de 4 cables a SPI de 3 cables. Usaremos el SPI de 4 cables por defecto aquí, así que no tienes que cambiar nada.

El módulo funciona a 3.3V o 5V, tiene una corriente de sueño muy baja de 0.01µA y consume solo unos 60mW durante el refresco. Para más información sobre pantallas E-paper en general, echa un vistazo al tutorial Interfacing Arduino To An E-ink Display.
Abajo enlazo la hoja de datos de la pantalla y también consulta el Waveshare manual:
Conexión de la pantalla E-paper de 4 colores con ESP32
En esta sección vamos a conectar la pantalla E-paper a un ESP32 lite. La siguiente imagen muestra el cableado completo entre el ESP32 y la pantalla para alimentación e interfaz SPI.

Puedes alimentar la pantalla con 3.3V o 5V, pero el ESP32-lite solo tiene salida de 3.3V. Ten en cuenta que debes usar los pines SPI hardware de tu microcontrolador. En el caso del ESP32-lite, son los pines 18 y 23. Abajo una tabla con todas las conexiones para mayor comodidad.
| Pantalla 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 |
Hacer funcionar el código demo con ESP32
Si descargas el Demo software para la pantalla E-paper de Waveshare, encontrarás una carpeta dentro de ese archivo zip llamada Arduino/epd3in0g. Allí hay un sketch llamado epd3in0g.ino que produce esencialmente la siguiente imagen en la pantalla:

Aquí está el fragmento reducido de ese código de ejemplo que produce la imagen. Puedes ver que crea el objeto display epd, lo inicializa, muestra los datos de la imagen y luego pone la pantalla en modo sueño:
#include "epd3in0g.h"
#include "imagedata.h"
Epd epd;
void setup() {
epd.Init();
epd.Display(IMAGE_DATA);
epd.Sleep();
}
void loop() { }
Este código no funciona en un ESP32. Sin embargo, puedes hacerlo funcionar siguiendo los pasos listados abajo (consulta este blog post para más contexto):
- Cambia
const unsigned charporunsigned charenimagedata.cppyimagedata.h - Cambia
#include <avr/pgmspace>por#include <pgmspace>enimagedata.h - Cambia las definiciones de pines en
epdif.hpara usar los pines SPI hardware del ESP32 - Agrega
SPI.endTransaction();a la funciónIfInit()enepdif.cpp
Aquí están las definiciones de pines que necesitas usar en epdif.h:
#define RST_PIN 16 #define DC_PIN 17 #define CS_PIN 5 #define BUSY_PIN 4
y aquí está el código en epdif.cpp que tienes que cambiar de
int EpdIf::IfInit(void) {
...
SPI.begin();
SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
return 0;
}
a este código agregando una línea (endTransaction):
int EpdIf::IfInit(void) {
...
SPI.begin();
SPI.endTransaction(); // <== ADD THIS LINE
SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
return 0;
}
Con esos cambios el código de ejemplo debería funcionar. Sin embargo, sigue limitado a mostrar imágenes estáticas. En la siguiente sección, te muestro una pequeña adición que te permite usar la biblioteca gráfica Adafruit_GFX para mostrar contenido dinámico como texto y gráficos.
Dibujar en pantalla E-paper de 4 colores usando canvas de Adafruit_GFX
La biblioteca Adafruit_GFX es una biblioteca gráfica que proporciona un conjunto común de graphics primitives (texto, puntos, líneas, círculos, etc.). Solo instálala vía Library Manager como de costumbre. Tras la instalación debería aparecer en el Library Manager así:

La biblioteca Adafruit_GFX tiene el concepto de un «canvas» que te permite dibujar en un buffer de pantalla (=canvas) en segundo plano (sin mostrarlo). Abajo un fragmento de código que crea un canvas de 8 bits de profundidad con las dimensiones de la pantalla 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);
}
Luego establece la orientación del buffer/pantalla, llena el buffer con blanco y dibuja un círculo rojo. Como el buffer es esencialmente una imagen, sería ideal si pudiéramos usar el siguiente código para mostrar el dibujo en el buffer en la pantalla E-paper:
epd.Display(canvas.getBuffer());
Sin embargo, la pantalla E-paper de 4 colores usa una imagen comprimida, donde cuatro píxeles se comprimen en un byte para ahorrar memoria. Como solo hay cuatro colores, cada color se representa con 2 bits:
| Color | Bits |
|---|---|
| negro | 00 |
| blanco | 01 |
| amarillo | 10 |
| rojo | 11 |
Lo que significa que, si tenemos una secuencia de cuatro píxeles con los colores negro, blanco, amarillo y rojo en la imagen original, podemos comprimirla en un byte (00011011 = 0x1B) así:

Tienes que hacer esto para todos los bloques de 4 píxeles en la imagen original para crear una imagen comprimida que pueda mostrarse en la E-paper vía epd.Display(image). La siguiente función compress() toma el buffer de pantalla del canvas y lo comprime como se describió:
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;
}
Ten en cuenta que reutiliza el buffer de pantalla. Así que no se necesita memoria adicional para la imagen comprimida, pero no puedes dibujar en el canvas después de comprimirlo. Tendrías que limpiarlo primero.
Con la función compress() puedes crear contenido dinámico y mostrarlo en la E-paper. El esquema del código es así:
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();
}
Aquí tienes un ejemplo completo con todo incluido:
#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() {
}
Si subes y ejecutas este código, deberías ver un círculo amarillo sobre fondo rojo con el texto «Test» en él:

compress()Aunque el código anterior funciona, es un poco engorroso de usar. Primero, tienes que integrar los archivos del código demo de Waveshare (epd3in0g.h, epd3in0g.cpp, epdif.h, epdif.cpp) en cada nuevo proyecto que use la pantalla E-paper. Segundo, también tienes que reimplementar la función compress() cada vez.
Por eso creé una pequeña biblioteca llamada epd4c, que evita todo eso. Solo tienes que instalarla y luego usarla independientemente del código demo. En la siguiente sección te muestro cómo funciona.
Dibujar en pantalla E-paper de 4 colores usando la biblioteca epd4c
Para instalar la epd4c Library ve al epd4c_arduino_lib github repo y haz clic en el botón verde «Code«. Luego haz clic en «Download Zip» como se muestra abajo:

Luego ve a «Sketch" -> "Include Library" -> "Add .Zip Library..» y selecciona el archivo «epd4c_arduino_lib-main.zip» que acabas de descargar:

Con la biblioteca epd4c (y la biblioteca Adafruit_GFX), escribir texto y dibujar en la pantalla E-paper de 4 colores es mucho más fácil.
Código de ejemplo
Aquí tienes un código de ejemplo. Dibuja una serie de círculos de colores junto con un texto centrado en la pantalla. Como ves, ya no hace falta un canvas separado ni usar el código demo de 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 a desglosar el código en sus componentes para entenderlo mejor.
Inclusión de biblioteca
Empezamos incluyendo la biblioteca epd4c para controlar la pantalla E-paper, que es una extensión de una biblioteca Adafruit_GFX canvas, y por tanto soporta todas las graphics primitives de la biblioteca Adafruit_GFX.
#include "epd4c.h"
Definición de pines
Luego definimos los pines usados para conectar la pantalla E-paper al ESP32. Ten en cuenta que los pines SPI no pueden definirse, debes usar y conectar los pines SPI hardware por defecto de tu microcontrolador.
#define RST_PIN 16 #define DC_PIN 17 #define CS_PIN 5 #define BUSY_PIN 4
Dimensiones de la pantalla
También definimos el ancho y alto de la pantalla E-paper. Como se mencionó, el código debería funcionar para otras pantallas E-paper de 4 colores con diferentes dimensiones, pero no lo he probado.
#define EPD_WIDTH 168 #define EPD_HEIGHT 400
Creación del objeto pantalla
Aquí creamos una instancia de la clase Epd4c, pasando las dimensiones de la pantalla y las definiciones de pines como parámetros. Este objeto se usará para controlar la pantalla durante todo el programa.
Epd4c epd(EPD_WIDTH, EPD_HEIGHT, RST_PIN, DC_PIN, CS_PIN, BUSY_PIN);
Función setup
En la función setup(), inicializamos la pantalla E-paper y configuramos sus ajustes. Aquí establecemos la rotación de la pantalla, llenamos la pantalla con color blanco y dibujamos varios círculos superpuestos de diferentes colores y tamaños.
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();
}
La salida en la pantalla E-paper será la siguiente

donde
epd.init();inicializa la pantalla.epd.setRotation(1);establece la orientación de la pantalla.epd.fillScreen(WHITE);llena toda la pantalla con color blanco.- Las funciones
fillCircle()dibujan círculos de radios y colores variados en las coordenadas especificadas (200, 84). epd.setCursor(190, 80);establece la posición para el texto a imprimir.epd.setTextColor((BLACK));establece el color del texto a negro.epd.print("Test");imprime el texto «Test» en la pantalla.epd.display();actualiza la pantalla con los gráficos dibujadosepd.sleep();pone la pantalla en modo sueño para ahorrar energía.
Función loop
La función loop() está vacía en este ejemplo, lo que significa que una vez completado el setup, el programa no realizará más acciones. La pantalla permanecerá en modo sueño y seguirá mostrando la imagen, incluso cuando el ESP32 esté apagado.
void loop() {}
Si quieres actualizar el contenido continuamente, por ejemplo para mostrar un reloj en marcha, deberías colocar el código gráfico en la función loop. Consulta los tutoriales Digital Clock on e-Paper Display o Weather Station on e-Paper Display para ejemplos.
¡Y eso es todo!
Conclusiones
En este tutorial aprendiste a controlar la pantalla E-paper de 3 pulgadas y 4 colores de Waveshare con un ESP32.
Te mostré cómo cambiar el código demo de Arduino para que funcione con un ESP32. También usamos la biblioteca Adafruit_GFX canvas para crear contenido dinámico para la pantalla E-paper. Y finalmente, te presenté la biblioteca epd4c.
La biblioteca epd4c hace esencialmente lo mismo que la biblioteca GxEPD2 pero desafortunadamente esta última actualmente no soporta la pantalla E-paper de 3 pulgadas y 4 colores de Waveshare. Hubiera preferido usarla. Podría haber extendido la biblioteca GxEPD2 pero fui perezoso y simplemente limpié y extendí el código demo de Waveshare para crear la biblioteca epd4c.
Si tienes alguna pregunta, no dudes en dejarla en la sección de comentarios.
¡Feliz bricolaje ; )

