En este artículo te explico paso a paso como mostrar imágenes en una pantalla ePaper de 4 colores usando una placa XIAO RA4M1 y el adaptador de expansión para tinta electrónica de Seeed Studio.
Introducción
Las pantallas utilizadas en proyectos con microcontroladores han avanzado considerablemente desde los tiempos en que solo disponíamos de simples displays LED de 7 segmentos.
Hoy en día, contamos con una amplia variedad de opciones, como pantallas LCD, OLED y tecnologías más innovadoras como ePaper, que ofrecen mejoras significativas en resolución y eficiencia energética. Estas nuevas tecnologías permiten desarrollar interfaces más dinámicas y personalizables, adecuadas para una gran variedad de aplicaciones, desde dispositivos portátiles hasta proyectos IoT y sistemas industriales.
En este artículo, exploraremos una aplicación práctica con una pantalla ePaper de 4 colores y te mostraré cómo controlarla utilizando una placa de expansión especial de Seeed Studio, diseñada específicamente para este tipo de displays. Además, usaremos la placa XIAO RA4M1 como controlador, que programaremos usando el Arduino IDE2. Esto nos brindará una excelente oportunidad para seguir descubriendo las capacidades de este pequeño gigante.
Elementos utilizados
Hardware
Software
Pantallas de tinta electrónica
La tecnología de tinta electrónica, también conocida como eInk o ePaper fue desarrollada hace mas de 30 años con la finalidad de crear pantallas que tengan un aspecto similar al papel impreso.
Funciona empleando un sistema de microcápsulas que contienen pigmentos blancos y negros (en un principio eran solo monocromáticos pero luego incorporaron escalas de grises y mas colores). Estas microcápsulas están suspendidas en un líquido y pueden moverse hacia la superficie al aplicar una corriente eléctrica, creando imágenes de alto contraste sin necesidad de iluminación posterior.
Este mecanismo de movimiento se denomina efecto electroforético, por lo que estos display a veces son llamados de la misma forma. Otra denominación que reciben es displays o pantallas EPD, de Electronic Paper Display.
Ventajas
La principal ventaja de la tecnología electroforética es su bajo consumo de energía, ya que solo requiere de electricidad cuando cambia la imagen en pantalla, mientas que no consume nada si la imagen se mantiene constante. Además, la imagen tiene gran contraste, lo que la hace fácilmente legible aún en ambientes de mucha luminosidad.
Desventajas
El talón de Aquiles de estas pantallas es su baja tasa de refresco: modificar la imagen en pantalla puede tomar varios segundos. Esto limita severamente su uso para mostrar contenido que cambia rápidamente, como un video. Otra limitación es su capacidad de mostrar muchos colores. Si bien es una tecnología en constante desarrollo y se ofrecen en la actualidad pantallas capaces de mostrar una amplia gama de colores, todavía están por detrás de otras tecnologías como OLED.
Aplicaciones
Las aplicaciones mas populares de estas pantallas son los lectores de libros electrónicos, etiquetas de precios electrónicas, señalización en ambientes con luz solar, paneles informativos para aplicaciones de domótica, entre otras. También se las puede encontrar en algunos dispositivos portátiles como pantalla auxiliar de bajo consumo.
El adaptador para tinta electrónica XIAO
Los EPD o displays de tinta electrónica tienen habitualmente muchos pines de conexión para su control y es común que estos pines estén disponibles en una cinta de circuito impreso flexible (FPC, Flexible Printed Circuit) que debe conectarse empleando un conector especial con un paso muy pequeño. Estos conectores pueden ser difíciles de soldar si no se tienen herramientas especiales, por lo cual distintos fabricantes producen placas adaptadoras que facilitan trabajar con estas pantallas.
En este tutorial voy a emplear una placa de Seeed Studio denominada eInk Expansion Board, especialmente diseñada para conectar distintos modelos de placas XIAO a una variedad de EPDs.
Características
Las características sobresalientes de esta placa adaptadora son las siguientes:
- Conector de 24 pines para la cinta flexible del display.
- Zócalo de conexión para la placa XIAO.
- Conector de paso 0,1″ y 8 pines para conectar a otro microcontrolador.
- Resistencias para adaptar niveles de señal entre el EPD y la XIAO.
- Soporte para numerosos displays y distintas placas XIAO.
Puedes consultar todas las características de la eInk Expansion Board en su Wiki.
El display
El display o pantalla que usaré para este tutorial es el GDEY0213F51 de la marca Good Display que también comercializa Seeed Studio.
Características
- Tamaño: 2,13 pulgadas
- Resolución: 122 x 250 pixeles
- Controlador: JD79661
- Área activa: 48.55 mm x 23.7046 mm
- Colores: Blanco, Negro, Amarillo y Rojo
- Tiempo de refresco completo: 25 segundos
- Interface: SPI
- Conector: Cinta flexible de 24 pines, paso de 0.5mm
- Alto contraste
- Alta reflectancia
- Ultra bajo consumo (9,9 mW en la trancisión)
Luego de haber revisado los distintos componentes a emplear, veamos ahora el procedimiento para mostrar imagenes en el display.
Preparando la imagen
Antes de poder mostrar una imagen en el ePaper, es necesario seguir algunos pasos previos. Primero, debemos diseñar la imagen respetando las especificaciones de tamaño y la paleta de colores permitida. Luego, es preciso convertir esa imagen a un formato compatible que podamos integrar en nuestro código.
Diseño de la imagen
La imagen a mostrar debe tener un tamaño de 250 pixeles de ancho por 128 pixeles de alto (aunque el display tenga solo 122 pixeles). Para crearla o diseñarla puedes usar cualquier programa de diseño, hasta el Paint que está incluido en Windows.
Si usas Paint, el tamaño lo puedes configurar haciendo click en Archivo – Propiedades de imagen (o pulsando Ctrl E).
Luego de pulsar Aceptar y establecer el tamaño de la imagen puedes dar rienda suelta a tu imaginación dibujando lo que quieras pero recordando que tienes sólo cuatro colores disponibles: Blanco, Negro, Rojo y Amarillo, que puedes ubicar en la paleta de colores de Paint:
A continuación puedes ver un ejemplo (como notarás mi imaginación no volo muy alto que digamos):
Otra alternativa es tomar una imagen o parte de una imagen que ya tengas diseñada y reducir la cantidad de colores en la paleta empleando un programa de diseño algo mas sofisticado como GIMP.
En el ejemplo de mas abajo, creé una imagen de 250×128 pixeles con el generador de imágenes de IA de Canva. Le pedí que tuviera 4 colores pero en realidad la paleta de la imagen creada tiene muchos mas. Usando GIMP reduje la cantidad de colores empleando una paleta personalizada que definí y que contiene sólo los colores presentes en el display, que son:
- Blanco: #000000
- Negro: #FFFFFF
- Rojo: #FF0000
- Amarillo: #FFFF00
Y si no quieres complicarte, te dejo esta herramienta online que te hace la conversión de colores con distintos métodos (dale click a la imagen para abrir la herramienta en otra pestaña)
Formato
Cualquiera sea el procedimiento que uses para preparar la imagen, debes guardarla en formato BMP o JPG para el proceso de conversión.
Conversión de la imagen
Una vez que tienes la imagen lista, con el tamaño y la cantidad de colores adecuada, debes convertirla a otro formato para poder incorporarla al código escrito en el Arduino IDE.
Esto se puede hacer empleando el programa image2lcd, que toma la imagen y la convierte a un archivo de cabecera (un archivo “.h”) con la información de la imagen en la forma de un array de 8000 bytes (unsigned char).
Instalación de image2lcd
El programa image2lcd puede ser descargado desde este enlace.
Al hacer click en el enlace, se descargará un archivo comprimido en formato “7z”. Debes descomprimirlo, correr el archivo ejecutable y seguir los pasos de la instalación. Este programa es exclusivo para Windows y no cuenta con versiones para otros sistemas operativos.
Una vez instalado, ejecutalo y verás una pantalla como la siguiente:
Abajo a la derecha hay una solapa que dice “Register”. Es importante que registres el programa sino te agregará un texto a las imagenes que quieras convertir. Toca la solapa “Register” e introduce el siguiente código: 0000-0000-0000-0000-6A3B
Conversión de la imagen
Una vez instalado y registrado el programa puedes proceder a convertir el formato de la imagen.
Haz click en el ícono Open y carga la imagen a transformar. Ajusta las configuraciones de la izquierda para que queden de la siguiente forma:
Una vez ajustada la configuración, no te olvides de pulsar el botón con forma de flecha al lado del 128. Con esto la imagen quedará convertida.
Ahora pulsa el ícono correspondiente a Save (a la derecha de Open) y guarda los datos con cualquier nombre (por ejemplo “demo.h”). Te quedará algo así:
Transfiriendo la imagen
Para transferir y mostrar la imagen en el display usaremos un programa de demostración que pone a nuestra disposición Seeed Studio en su Wiki y que puedes descargar desde este repositorio (la descripción hace referencia a un display de 212 x 104, pero el código es para 250 x 128.
También lo copio a continuación:
#include <SPI.h> #include"demo.h" //IO settings int BUSY_Pin = D5; int RES_Pin = D0; int DC_Pin = D3; int CS_Pin = D1; #define EPD_W21_CS_0 digitalWrite(CS_Pin,LOW) #define EPD_W21_CS_1 digitalWrite(CS_Pin,HIGH) #define EPD_W21_DC_0 digitalWrite(DC_Pin,LOW) #define EPD_W21_DC_1 digitalWrite(DC_Pin,HIGH) #define EPD_W21_RST_0 digitalWrite(RES_Pin,LOW) #define EPD_W21_RST_1 digitalWrite(RES_Pin,HIGH) #define isEPD_W21_BUSY digitalRead(BUSY_Pin) //2bit #define black 0x00 /// 00 #define white 0x01 /// 01 #define yellow 0x02 /// 10 #define red 0x03 /// 11 #define Source_BITS 128 #define Gate_BITS 250 #define ALLSCREEN_BYTES Source_BITS*Gate_BITS/4 ////////FUNCTION////// void SPI_Write(unsigned char value); void EPD_W21_WriteCMD(unsigned char command); void EPD_W21_WriteDATA(unsigned char datas); //EPD void EPD_init(void); void Acep_color(unsigned char color); void PIC_display (const unsigned char* picData); void Display_All_White(void); void EPD_sleep(void); void EPD_refresh(void); void lcd_chkstatus(void); void setup() { pinMode(BUSY_Pin, INPUT); pinMode(RES_Pin, OUTPUT); pinMode(DC_Pin, OUTPUT); pinMode(CS_Pin, OUTPUT); //SPI SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0)); SPI.begin (); } //Tips// /*When the electronic paper is refreshed in full screen, the picture flicker is a normal phenomenon, and the main function is to clear the display afterimage in the previous picture. When the local refresh is performed, the screen does not flash.*/ /*When you need to transplant the driver, you only need to change the corresponding IO. The BUSY pin is the input mode and the others are the output mode. */ void loop() { ///////////////////////////Normal picture display///////////////////////////////////////////////////////////////// /************Normal picture display*******************/ EPD_init(); //EPD init PIC_display(gImage_demo);//EPD_picture1 EPD_sleep();//EPD_sleep,Sleep instruction is necessary, please do not delete!!! delay(5000); //5s // EPD_init(); //EPD init // Display_All_White(); // EPD_sleep();//EPD_sleep,Sleep instruction is necessary, please do not delete!!! delay(300000); // The program stops here } ///////////////////EXTERNAL FUNCTION//////////////////////////////////////////////////////////////////////// /////////////////////delay////////////////////////////////////// //////////////////////SPI/////////////////////////////////// void SPI_Write(unsigned char value) { SPI.transfer(value); } void EPD_W21_WriteCMD(unsigned char command) { EPD_W21_CS_0; EPD_W21_DC_0; // command write SPI_Write(command); EPD_W21_CS_1; } void EPD_W21_WriteDATA(unsigned char datas) { EPD_W21_CS_0; EPD_W21_DC_1; // command write SPI_Write(datas); EPD_W21_CS_1; } /////////////////EPD settings Functions///////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////// //JD void EPD_init(void) { delay(20);//At least 20ms delay EPD_W21_RST_0; // Module reset delay(40);//At least 40ms delay EPD_W21_RST_1; delay(50);//At least 50ms delay lcd_chkstatus(); EPD_W21_WriteCMD(0x4D); EPD_W21_WriteDATA(0x78); EPD_W21_WriteCMD(0x00); //PSR EPD_W21_WriteDATA(0x0F); EPD_W21_WriteDATA(0x29); EPD_W21_WriteCMD(0x01); //PWRR EPD_W21_WriteDATA(0x07); EPD_W21_WriteDATA(0x00); EPD_W21_WriteCMD(0x03); //POFS EPD_W21_WriteDATA(0x10); EPD_W21_WriteDATA(0x54); EPD_W21_WriteDATA(0x44); EPD_W21_WriteCMD(0x06); //BTST_P EPD_W21_WriteDATA(0x05); EPD_W21_WriteDATA(0x00); EPD_W21_WriteDATA(0x3F); EPD_W21_WriteDATA(0x0A); EPD_W21_WriteDATA(0x25); EPD_W21_WriteDATA(0x12); EPD_W21_WriteDATA(0x1A); EPD_W21_WriteCMD(0x50); //CDI EPD_W21_WriteDATA(0x37); EPD_W21_WriteCMD(0x60); //TCON EPD_W21_WriteDATA(0x02); EPD_W21_WriteDATA(0x02); EPD_W21_WriteCMD(0x61); //TRES EPD_W21_WriteDATA(Source_BITS/256); // Source_BITS_H EPD_W21_WriteDATA(Source_BITS%256); // Source_BITS_L EPD_W21_WriteDATA(Gate_BITS/256); // Gate_BITS_H EPD_W21_WriteDATA(Gate_BITS%256); // Gate_BITS_L EPD_W21_WriteCMD(0xE7); EPD_W21_WriteDATA(0x1C); EPD_W21_WriteCMD(0xE3); EPD_W21_WriteDATA(0x22); EPD_W21_WriteCMD(0xB4); EPD_W21_WriteDATA(0xD0); EPD_W21_WriteCMD(0xB5); EPD_W21_WriteDATA(0x03); EPD_W21_WriteCMD(0xE9); EPD_W21_WriteDATA(0x01); EPD_W21_WriteCMD(0x30); EPD_W21_WriteDATA(0x08); EPD_W21_WriteCMD(0x04); lcd_chkstatus(); } //////////////////////////////All screen update//////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// void EPD_refresh(void) { EPD_W21_WriteCMD(0x12); //Display Update Control EPD_W21_WriteDATA(0x00); lcd_chkstatus(); } void EPD_sleep(void) { EPD_W21_WriteCMD(0X02); //power off lcd_chkstatus(); //waiting for the electronic paper IC to release the idle signal delay(100); //!!!The delay here is necessary,100mS at least!!! EPD_W21_WriteCMD(0X07); //deep sleep EPD_W21_WriteDATA(0xA5); } void lcd_chkstatus(void) { while(1) { //=0 BUSY if(isEPD_W21_BUSY==1) break; } } unsigned char Color_get(unsigned char color) { unsigned datas; switch(color) { case 0x00: datas=white; break; case 0x01: datas=yellow; break; case 0x02: datas=red; break; case 0x03: datas=black; break; default: break; } return datas; } void PIC_display(const unsigned char* picData) { unsigned int i,j; unsigned char temp1; unsigned char data_H1,data_H2,data_L1,data_L2,datas; EPD_W21_WriteCMD(0x10); for(i=0;i<Gate_BITS;i++) //Source_BITS*Gate_BITS/4 { for(j=0;j<Source_BITS/4;j++) { temp1=pgm_read_byte(&picData[i*Source_BITS/4+j]); data_H1=Color_get(temp1>>6&0x03)<<6; data_H2=Color_get(temp1>>4&0x03)<<4; data_L1=Color_get(temp1>>2&0x03)<<2; data_L2=Color_get(temp1&0x03); datas=data_H1|data_H2|data_L1|data_L2; EPD_W21_WriteDATA(datas); } } //Refresh EPD_refresh(); } void Display_All_White(void) { unsigned long i; EPD_W21_WriteCMD(0x10); { for(i=0;i<ALLSCREEN_BYTES;i++) { EPD_W21_WriteDATA(0x55); } } EPD_refresh(); } //////////////////////////////////END//////////////////////////////////////////////////
Copia el código en Arduino IDE y en la misma carpeta del archivo “.ino” copia el archivo “demo.h” que contiene la información de imagen. (Si le cambiaste el nombre deberás modificar el include al principio del código).
En el siguiente video puedes ver el programa en funcionamiento:
Como puedes apreciar, este display es mucho mas lento que un OLED y demora algunos segundos en cargar la imagen, pero esto se ve compensado con el bajo consumo. De hecho, si desconectas la alimentación del display, la imagen se mantiene.
Conclusiones
En este artículo te expliqué paso a paso cómo mostrar imágenes en un display ePaper de cuatro colores con una placa XIAO RA4M1.
Vimos de que se trata la tecnología de tinta electrónica o electroforética, cuales son sus principales ventajas, desventajas y aplicaciones. También te describí las características de la placa adaptadora para tinta electrónica de Seeed Studio, que facilita muchísimo la conexión de un display de este tipo con distintos modelos de placas XIAO. De la misma forma, vimos las características principales del display GDEY0213F51, que es el que uso para este tutorial y como se conecta a la placa adaptadora.
Finalmente te mostré el procedimiento que debes seguir para diseñar y preparar una imagen, teniendo en cuenta el tamaño y la cantidad de colores. Te mostré distintas opciones para adecuar la paleta de colores, incluída una herramienta online que te simplifica mucho el trabajo. También vimos como transformar esa imagen en un archivo de cabecera “.h” usando el programa image2lcd y como incluir el mismo en un programa de ejemplo que puedes probar usando el Arduino IDE para transferir la imagen al display.
Este seguramente no será el último tutorial dedicado a este display, que tiene un gran potencial. En otra oportunidad te mostraré otras formas de emplearlo para sacarle provecho y también te compartiré algunos proyectos y aplicaciones prácticas.
Aprovecho para agradecer a la gente de Seeed Studio que, en el marco del programa Early Adopter me envió los materiales necesarios para realizar este tutorial y me brindaron el soporte necesario cuando tuve dudas o necesité realizar consultas.
Espero que el tutorial te sea de utilidad como punto de partida para que realices tus propios proyectos con este display y con la línea de placas XIAO. Como siempre, cualquier duda o consulta puedes dejarla mas abajo en la sección de comentarios.
Más info
Hoja de datos del display en PDF
Enlace de descarga de image2lcd
Sitio web de Good-Display, el fabricante del EPD
Página de la placa de expansión de tinta electrónica en la Wiki de Seeed Studio