E-Paper Display am ESP32 und ESP8266 - [Teil 2] - AZ-Delivery

Introducción 

En la primera parte de esta serie de blogs mostré cómo usar una pantalla de papel electrónico en un microcontrolador ESP32. En el proceso, algunos usuarios ya han notado inconsistencias. En esta parte de la serie, me ocuparé primero de eso. Luego mostraré cómo mostrar las imágenes propias, los datos de los sensores o los datos de la red del módulo WLAN. También usaré el ESP8266 D1 Mini en lugar del ESP32. Vámonos. 

Hardware requerido

Numero Componente Nota
1 ESP32 NodeMCU o Kit de desarrollo ESP-32 C V4
1 ESP8266 D1 Mini
1 1,54" exhibición del E-papel
1 Sensor de temperatura DHT11
PC con Arduino IDE y conexión a internet

Un consejo de antemano

Si no quieres pulsar el botón BOOT del ESP32 cada vez para subir un programa, sigue estas instrucciones. Necesitas un condensador de 10 µF entre las patillas EN (+) y GND (-).

E-Paper display V1 vs V2

Recibimos algunas reacciones a la primera parte de esta serie. Por lo tanto, mi investigación en ese momento fue lamentablemente insuficiente. Ahora en este punto la pista para ti:

Los códigos fuente y las imágenes de la parte 1 se refieren a la pantalla del Waveshare ePaper con un tamaño de 1,45" y una resolución de 200x200 píxeles en blanco y negro en la (antigua) versión 1.

En este punto, un gran agradecimiento a Eberhard Werminghoff por su apoyo. Espero que ahora todo funcione como debería.

El fabricante Waveshare señala en su página web que las placas de control de la pantalla V1 y V2 son diferentes y por lo tanto el código fuente del controlador debe ser intercambiado. Además, la versión 1 debe ser alimentada con un voltaje de 3,3 V, la versión 2 tolera hasta 5 V. Para más detalles, vea las dos hojas de datos de la antigua versión 1 y la nueva versión 2.
Aquí mostraré brevemente las diferencias de ambas pantallas:


Aquí puedes ver las diferencias externas de la nueva versión:

  • El enchufe es más pequeño y está más alejado
  • El número de componentes se amplía y se ordenan de forma diferente
  • La clavija para el voltaje de suministro se llama ahora VCC, en lugar de 3.3V.
  • Se llama Rev2.1
  • Es una pegatina V2, en lugar de una pegatina PASS.
  • La opción de interfaz BS se invierte
  • Hay una fecha impresa en el cable de la cinta. La nueva pantalla es de 2017:

En cuanto a los números de los alfileres, los había escogido para poder clavarlos uno al lado del otro en el tablero. Eso excluye a SCK y MOSI, que no pueden ser cambiados. Por supuesto, puedes usar los pines predeterminados de los ejemplos. Asegúrate entonces de cambiar los números de mi código fuente.

Los tableros ESP32 o ESP8266 están disponibles en diferentes variantes. Por ejemplo, con 30 en lugar de 38, o el D1 Mini ESP2866 con aún menos alfileres. Por favor, compruebe las especificaciones en las hojas de datos.

Volvamos a las bibliotecas. Por un lado uso la biblioteca EPD de Asuki Kono, que también se especifica en la Referencia de Arduino. La información sobre cómo usarlo y el código fuente se puede encontrar en Github. Puede utilizarse para las antiguas pantallas V1 con un tamaño de pantalla de 1,54" y trae ejemplos de las tres variantes de módulos, para cada una de las cuales debe incluirse un archivo de cabecera diferente:

Para mi pantalla, había usado el ejemplo de ShowRunningTime como fuente.

Nota: Preste atención si tiene una pantalla en blanco y negro, la pantalla en blanco y negro/rojo (B), o la pantalla en blanco y negro/amarillo (C). Entonces presta atención a si utilizas el panel RAW (es decir, la pantalla pura) o el tablero con interfaz SPI.

Desafortunadamente, esta biblioteca no ha sido actualizada y adaptada a las nuevas versiones de las pantallas. El fabricante Waveshare ofrece el código fuente de la nueva versión de Github. Desafortunadamente, no se puede migrar el código de Waveshare a la biblioteca de la EPD tan fácilmente.

He adaptado la fuente de ondas compartidas para la pantalla en blanco y negro de 1,54" para que podamos usarla, como la biblioteca de la EPD. Puedes descargar el código fuente de la misma:

Descargar Biblioteca epd1in54 V2

Esto no funciona con las pantallas multicolores. Para eso tendrías que reescribir también los otros archivos fuente.

Breve descripción de la instalación:

  • abre la carpeta "Libros de bosquejo" de la biblioteca.
  • si no sabes la ubicación, abre el IDE de Arduino, allí el menú Archivo -> Preferencias
  • en la parte superior de la ventana encontrarás el camino bajo la ubicación de Sketchbook
  • copiar la carpeta epd1in54_V2 en las bibliotecas de carpetas
  • reiniciar el IDE de Arduino
  • Encontrará un boceto de ejemplo en el menú Archivo -> Ejemplos -> Ejemplos de bibliotecas propias -> epd1in54V2 -> epd1in54V2
  • en la parte superior encontrarás información sobre los pinouts de los diferentes tableros
  • comentar en la línea que se ajusta a tu tabla
  • después de subir al microcontrolador la demo de Waveshare debería funcionar

Si utilizas una pantalla de diferente tamaño o con más colores, puedes descargar las bibliotecas actuales de Waveshare de Github. Preste atención al pinout que se da en la biblioteca respectiva. En caso de que quieras usar otros pines, abre el archivo de código fuente epdif.h y cambia las siguientes líneas:

// Pin definition
#define RST_PIN 8
#define DC_PIN 9
#define CS_PIN 10
#define BUSY_PIN 7

Esto es entonces codificado, pero aún así se ajusta a sus necesidades. Si tus habilidades de programación van más allá, puedes cambiar el constructor de la clase epd para que puedas pasar los números de los alfileres.

También tienes que cambiar la ubicación del archivo pgmspace.h en algunos archivos. La diferencia aquí es el uso de la placa (placa 100% compatible con Arduino o ESP32 o ESP8266).

Aquí hay un extracto del archivo font8.c anterior:

#include < avr / pgmspace.h >

y después:

#if defined(__AVR__) || defined(ARDUINO_ARCH_SAMD)
#include <avr/pgmspace.h>
#elif defined(ESP8266) || defined(ESP32)
#include <pgmspace.h>
#endif

Usaré mi biblioteca extendida epd1in54_V2 para la pantalla V2 de 1.54" en este post.

Como biblioteca alternativa, te he mostrado el GxEPD2 de Jean-Marc Zingg. En el GxEPD2_Ejemplo tienes que comentar la línea apropiada que se ajusta a tu pantalla. Además, también tienes que elegir el procesador adecuado (ESP8266, ESP32, STM32 o tarjeta compatible con el AVR de Arduino). Para ello, busque las siguientes líneas:

#if defined (ESP8266)

o

#if defined(ESP32)

o

#if defined(ARDUINO_ARCH_STM32)

o

#if defined(__AVR)
#if defined (ARDUINO_AVR_MEGA2560)

Los números de las líneas cambian de vez en cuando, porque el proyecto sigue en marcha. Por lo tanto, no los doy aquí.
Bajo las definiciones especificadas encontrará las declaraciones apropiadas para su exhibición. Para mi pantalla era esta línea:

GxEPD2_BW<GxEPD2_154, GxEPD2_154::HEIGHT> display(GxEPD2_154(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEP015OC1 no longer available

Yo había cambiado esto a:

GxEPD2_BW<GxEPD2_154, GxEPD2_154::HEIGHT> display(GxEPD2_154(/*CS=*/26, /*DC=*/ 25, /*RST=*/ 33, /*BUSY=*/ 27)); // GDEP015OC1 no longer available

que coinciden con mi pinout, que también se encuentra a continuación.

Nota: En el Nodo ESP32 MCU no debe utilizar los pines GPIO0, GPIO2 y GPIO12, de lo contrario la carga no funcionará. Puede encontrar más información aquí.

En este punto ya se puede ver en el comentario del desarrollador la nota "GDEP015OC1 ya no está disponible". Esta es la versión antigua de la pantalla de 1,54" con la resolución de 200x200 píxeles. Para la versión actual en el ESP32 seleccione esta línea:

GxEPD2_BW<GxEPD2_154_D67, GxEPD2_154_D67::HEIGHT> display(GxEPD2_154_D67(/*CS=D5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEH0154D67

 en el ESP8266 es este:

GxEPD2_BW<GxEPD2_154_D67, GxEPD2_154_D67::HEIGHT> display(GxEPD2_154_D67(/*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2, /*BUSY=D2*/ 4)); // GDEH0154D67

También puedes usar los pines de los ejemplos, pero entonces tienes que cambiar las conexiones en el hardware. En una inspección más cercana también verá que la diferencia entre ESP32 y ESP8266 es sólo el pinout.
Si usas una de las pantallas de tres colores, tienes que buscar más abajo para encontrar esa línea:

GxEPD2_3C<GxEPD2_154c, GxEPD2_154c::HEIGHT> display(GxEPD2_154c(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4));

Entonces debes incluir esta biblioteca para esto, como también se hace en el GxEPD2_Ejemplo.

#include < gxepd2 - u3c.h >

No necesitaba esto en mi código fuente. El desarrollador da una pista más importante para el uso del ESP8266, que podría ser importante para usted en el futuro:

NOTA para ESP8266 : El uso de SS (GPIO15) para CS puede causar problemas en el modo de arranque, usa un pin diferente en caso de que.

Traducido esto significa que la clavija CS número 15 puede llevar a problemas de arranque y deberías cambiar a otra clavija.

Mostrar ESP32 y sus propias imágenes

La conexión al microcontrolador ESP32 NodeMCU se ve así:
Pin EPD Esp32 gpio
Autobús 27
Rst 33
D.C. 25
élite antiterrorista 26
Reloj Sck = 18
Normas industriales alemanas MOSS = 23
Ingreso nacional bruto Ingreso nacional bruto
3,3 voltios 3,3 voltios

SCK y MOSI están predefinidos por el microcontrolador. En el ESP32 son la clavija 18 para SCK y la clavija 23 para MOSI. Mira en el pinout de tu microcontrolador. Preste atención a la diferencia entre el número de GPIO y el número impreso en el tablero. Busy, RST, DC y CS pueden seleccionarse libremente (presta atención a las notas de la sección anterior).


Nota : Evita usar la clavija GND junto a la clavija 5V (abajo a la izquierda en la foto). Para más información, por favor, consulte el resumen del pinout y la hoja de datos.

Asumo que las bibliotecas EPD y GxEPD2 de la primera parte de esta serie de blogs están instaladas. También necesitarás mi biblioteca alternativa EPD V2 para la nueva pantalla.

Crear imágenes

Ahora queremos mostrar nuestra propia imagen en la pantalla. En la primera parte describí cómo cargar los datos de la imagen en el búfer de la imagen en forma de un conjunto de caracteres. Así que tenemos que extraer los datos de la imagen deseada y copiarla en la matriz. Primero, encontremos una imagen. Usaré el logo de AZDelivery:

Como la pantalla tiene un formato cuadrado, la imagen también debe ser cuadrada. Para extraer los datos de la imagen, Waveshare recomienda la herramienta image2lcd. Encontré una herramienta online a través de Github que también funciona muy bien. El fabricante de pantallas Waveshare muestra en su página web cómo puedes convertir tus propias imágenes con un programa de gráficos.

Yo uso la herramienta online aquí. En el paso 1 se selecciona el archivo de imagen, en el paso 2 se pueden dejar los ajustes tal como están. En la vista previa del paso 3, la imagen debería aparecer ahora en blanco y negro. En el paso 4 fijamos el formato de salida del código en "Código Arduino". El identificador puede ser elegido libremente por usted. Este es el nombre de la matriz de datos de imágenes más tarde. En nuestro caso es irrelevante, porque sólo necesitamos el contenido. La matriz ya existe y queremos seguir usándola. Ponemos el modo de dibujo en Horizontal - 1 bit por píxel y generamos el código haciendo clic en el botón correspondiente.

1.54" Display V1

Abrimos el IDE de Arduino y en él, desde la biblioteca EPD, abrimos el ejemplo EPD1in54ShowRunningTime. Esta será nuestra plantilla. Cambiamos las líneas 43 y 44 de nuevo:

// EPD1in54 epd; // default reset: 8, dc: 9, cs: 10, busy: 7
EPD1in54 epd(33, 25, 26, 27); // reset, dc, cs, busy

En el ejemplo, se muestran primero el texto y los símbolos geométricos, seguidos de un gráfico a tamaño real y luego la visualización de la hora. O bien comentamos las líneas que no son necesarias, o simplemente las borramos. La línea 70 a la 116 es la parte que genera el texto y los símbolos y por lo tanto no es necesaria.


La medición del tiempo en la línea 122 tampoco es necesaria. Eliminamos el contenido de la función loop() así como la función updateTime() completa. Guardamos el proyecto con un nuevo nombre. Los imagedata.h y .cpp deben ser guardados automáticamente. El código fuente parece ahora acortado de la siguiente manera:

#include <SPI.h>
#include <EPD1in54.h>
#include <EPDPaint.h>
#include "imagedata.h"

#define COLORED 0
#define UNCOLORED 1

unsigned char image[1024];
EPDPaint paint(image, 0, 0); // width should be the multiple of 8

// Die Zeile fuer das gewuenschte Board einkommentieren
// ****************************************************
//
// ESP32:
EPD1in54 epd(33, 25, 26, 27); // reset, dc, cs, busy

// ESP8266:
// EPD1in54 epd(5, 0, SS, 4); // reset, dc, cs, busy


void setup() {
Serial.begin(115200);
if (epd.init(lutFullUpdate) != 0) {
Serial.print("e-Paper init failed");
return;
}

epd.clearFrameMemory(0xFF); // bit set = white, bit reset = black
epd.displayFrame();
epd.clearFrameMemory(0xFF); // bit set = white, bit reset = black
epd.displayFrame();

paint.setRotate(ROTATE_0);

// Demo-Bild
epd.setFrameMemory(IMAGE_DATA);
epd.displayFrame();
}

void loop() {}

Ahora copiamos de la herramienta en línea el código fuente generado que está dentro de los corchetes.

En el IDE de Arduino, la pestaña para la imagen de datos.h / .cpp debe estar disponible en la parte superior de la ventana del programa:


Nota : Los archivos de imagen se han trasladado a archivos externos, porque contienen una cantidad relativamente grande de código fuente. Estos archivos deben estar ubicados en la misma carpeta. El archivo .h está incluido entre comillas. Esto hace que se conozca el correspondiente .cpp. Su contenido puede ser usado en nuestro programa. En este caso, en forma de conjuntos de datos de imágenes. Cuando abra el proyecto en el IDE de Arduino, las pestañas deberían aparecer como se muestra en la imagen de arriba. De la misma manera puedes intercambiar funciones o métodos o procedimientos y reutilizarlos en otros programas.

Seleccionamos el archivo imagedata.cpp e insertamos nuestros nuevos datos de imagen de la herramienta en línea en la matriz IMAGE_DATA entre los corchetes.


Alternativamente, también se puede crear una nueva matriz. Para ello, copie el código fuente completo generado previamente en la página web (CTRL + A y luego CTRL + C) y péguelo en el imagedata.cpp al final. Así es como se ve como un ejemplo abreviado:

// 'AZ-Logo', 200x200px
const unsigned char AZLogo[] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
...
...
...
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};

Después, la matriz debe ser declarada en el imagedata.h. Para hacerlo, simplemente copie la línea que ya está ahí y sólo cambie el nombre:

extern const unsigned char AZLogo[];

Si decidiste usar la imagen adicional, añadimos las siguientes líneas al final de la función setup():

delay(2000);

epd.clearFrameMemory(0xFF); // bit set = white, bit reset = black
epd.displayFrame();
epd.clearFrameMemory(0xFF); // bit set = white, bit reset = black
epd.displayFrame();

// Eigenes Bild
epd.setFrameMemory(AZLogo);
epd.displayFrame();

Cuando compilas el programa y lo cargas en el ESP32, la pantalla debería mostrar la imagen que usaste.


El logo que usé consta de sólo dos colores y pocos detalles. Esto está bien para mostrarlo en una pantalla de dos colores. Sin embargo, si quiere usar las fotos con más detalle, puede que tenga que hacer algunos ajustes. La mayoría de las veces, es suficiente para cambiar el contraste y el brillo. Para ello, puede cambiar el valor de "Brillo / umbral alfa" en el sitio web mencionado en el punto 2. Si esto no es suficiente, tienes que recurrir a un programa de gráficos.

ESP8266 D1 Mini

El pinout del ESP8266 es ligeramente diferente al del ESP32. Usamos los números de GPIO, que se muestran en turquesa en la siguiente imagen:

Conectamos los cables del D1 Mini al EPD de acuerdo con el siguiente esquema (la etiqueta con la D al lado es la etiqueta impresa en el microcontrolador, los números GPIO son los que uso en el IDE de Arduino): 

Pernos de EPD ESP2866 nodo MCU D1 Mini GPIO
Ocupado D2 (GPIO 4)
PRIMERA D1 (GPIO 5)
DC D3 (GPIO 0)
CS D8 (GPIO15, SS)
CLK D5 (SCK)
Estruendo D7 (MOSI)
GND GND
3.3 V 3.3 V

En el IDE de Arduino, en el menú "Herramientas", cambiamos la placa a NodeMCU 1.0 (módulos ESP-12E) o a Wemos D1 R1.


Ahora comentamos la línea apropiada en el código fuente:

// ESP32:
// EPD1in54 epd(33, 25, 26, 27); // reset, dc, cs, busy

// ESP8266:
EPD1in54 epd(5, 0, SS, 4); // reset, dc, cs, busy

También puedes cambiar los números de los alfileres. Lo he simplificado un poco aquí. No necesitas nada más que diferentes números de pin aquí.
Si subimos el programa, la imagen que seleccionamos debería aparecer de nuevo.

Descargar el programa completo: Epdeigenbildesp32esp8266_v1

El cambio de ESP32 a ESP8266 es relativamente sencillo. Si ha encontrado los pines correctos, los ha conectado y los ha cambiado en el código fuente, la pantalla funciona como siempre. Los otros ejemplos de la parte 1 también pueden ser ejecutados con el D1 Mini.

1.54" Display V2 en ESP32

Ahora conectaremos la nueva versión de la pantalla y mostraremos las mismas imágenes en ella. El pinout sigue siendo el mismo. Primero uso la biblioteca EPD modificada de Waveshare.


En la primera sección de este post, te mostré cómo subir el programa de muestra. Usamos este ejemplo como fuente. También borramos aquí las variables de tiempo y casi todas las líneas del setup(). El código fuente que queda ahora es muy claro:

#include <SPI.h>
#include "epd1in54_V2.h"
#include "epdpaint.h"
#include "imagedata.h"

#define COLORED 0
#define UNCOLORED 1

unsigned char image[1024];
Paint paint(image, 0, 0); // width should be the multiple of 8

// Die Zeile fuer das gewuenschte Board einkommentieren
// ****************************************************
//
// ESP32:
Epd epd(33, 25, 26, 27); // my Pins ESP32 (Reset, DC, CS, Busy)
//
// ESP8266:
// Epd epd(5, 0, SS, 4); // my Pins ESP8266 (Reset, DC, CS, Busy)

void setup() {
Serial.begin(115200);
Serial.print(epd.HDirInit());
epd.HDirInit();

// Demo-Bild
epd.Display(IMAGE_DATA);

delay(2000);

// Eigenes Bild
epd.Display(AZLogo);
}

void loop() {}

Es el mismo procedimiento que en el programa de la antigua pantalla.

1.54" Display V2 en ESP8266

Para el D1 Mini sólo comentamos en otra línea en consecuencia, donde inicializamos la pantalla:

Epd epd(5, 0, SS, 4); // my Pins ESP8266 (D1, D3, D8, D2)

Luego, por supuesto, seguimos cambiando la placa en el IDE de Arduino en Herramientas y subimos el programa. De nuevo, la imagen demo se muestra primero y después de una pausa de dos segundos el logo de AZ.

Descargar el programa completo: Epdeigenbildesp32esp8266_v2

Comparación con la biblioteca GxEPD2

#include
#include "imagedata.casa"

// Introduzca la línea para el tablero deseado
// ****************************************************
//
// 1,54" 200x200 V1 (viejo):
// -----------------------
// ESP32:
// GxEPD2_BW<GxEPD2_154, GxEPD2_154::HEIGHT> display(GxEPD2_154(26, 25, 33, 27)); // CS, DC, RST, Ocupado //GDEP015OC1 ya no disponible
/Descripción del producto:
// GxEPD2_BW<GxEPD2_154, GxEPD2_154::HEIGHT> display(GxEPD2_154(SS, 0, 5, 4)); //CS, DC, RST, BUSY //GDEP015OC1 ya no disponible
//
// 1.54 " 200x200 V2 (Artículo nuevo):
// -----------------------
// ESP32:
// GxEPD2_BW<GxEPD2_154_D67, GxEPD2_154_D67::HEIGHT> display(GxEPD2_154_D67(26, 25, 33, 27)); // CS, DC, RST, Ocupado // GDEH0154D67
/Descripción del producto:
// GxEPD2_BW<GxEPD2_154_D67, GxEPD2_154_D67::HEIGHT> display(GxEPD2_154_D67(SS, 0, 5, 4)); // CS, DC, RST, Ocupado // GDEH0154D67

anular configuración() {
Mostrar.inicio();
Mostrar.setRotation(0);
Mostrar.setFullWindow();

  // Imagen de demostración
Mostrar.Pantalla de relleno (GxEPD_BLACK);
Mostrar.DrawBitmap(0, 0, IMAGE_DATA, 200, 200, GxEPD_WHITE);
  mientras (Mostrar.SiguientePágina());
 
retraso(2000);

  // Propia imagen
Mostrar.Pantalla de relleno (GxEPD_BLACK);
Mostrar.DrawBitmap(0, 0, AZLogo, 200, 200, GxEPD_WHITE);
  mientras (Mostrar.SiguientePágina());
}

anular bucle() {}

He intercambiado los datos de la imagen en archivos separados, equivalentes al ejemplo anterior con la biblioteca de la EPD. Tiene que comentar aquí la línea que corresponde a su configuración. Pantalla V1 en ESP32 o ESP8266 o Pantalla V2 en ESP32 o ESP8266.

Descargar el programa completo: Gxepd2eigenbildesp32esp8266v1and_v2

Mostrar los datos del sensor

A continuación, queremos mostrar datos reales en la pantalla. Elijo el sensor de temperatura del DHT11 para esto. Sigo usando el D1 Mini y por ahora la biblioteca EPD para la pantalla V1. Conectamos el sensor de la siguiente manera:
Pernos DHT11 ESP2866 D1 Mini GPIO
S (DATOS) D0 (GPIO 16)
GND GND
VCC 5V

En la gestión de la biblioteca hay que instalar una biblioteca adecuada. Uso la "Biblioteca de sensores DHT para ESPx de beegee_tokyo". 
Para la temperatura y la humedad declaramos cuatro variables:

flotante temperatura = 0.0;
flotante temperatur_old = 0.0;
flotante humedad = 0.0;
flotante humidity_old = 0.0;

Hay dos de cada uno, ya que queremos comparar entre los datos antiguos y los nuevos más tarde. Esto nos da la posibilidad de actualizar la pantalla sólo cuando los valores han cambiado. Otra opción sería especificar un período de tiempo después del cual se lee el sensor y se actualiza la pantalla.

La siguiente línea crea una instancia de objeto DHT:

dht.setup(16, DHTesp::DHT11);

En el setup() ahora el sensor de temperatura debe ser inicializado. Uso un sensor DHT11 en la clavija D0. En el gráfico de arriba se puede ver que el número correspondiente de GPIO es 16. Esto se introduce aquí.

Nivel de Cifrado WEPconfiguración(16, DHTesp::DHT11);

Mi secuencia de programa es ahora para limpiar la pantalla, y luego mostrar el logo de AZ. Entonces la pantalla debe ser borrada de nuevo. Entonces se muestra una imagen de fondo que he creado. Después de eso, se muestran los valores de humedad y temperatura. Se actualizan tan pronto como cambian. No se debe actualizar toda la pantalla, sino sólo los nuevos datos.

Convertí la imagen en datos de imagen usando la herramienta online, la añadí a imagedata.cpp/.h y la llamé "Background":

imagedata.cpp (extracto):

// 'Fondo', 200x200px
Construir sin signo char Antecedentes [] PROGMEM = {
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ...

imagedata.casa:

/**
 *  @filename: imagedata.casa
 *  @brief: archivo de cabeza para imagedata.cpp
*/

externo Construir sin signo char Fondo[];
externo Construir sin signo char AZLogo[];

/* FILE
FINAL */

Que bucle()La función ahora se complementa con la lectura del sensor:

anular bucle() {
temperatura = dht.getTemperature();
humedad = dht.getHumidity();
 
  si (temperatura != temperatura_viejo) {
temperatur_old = temperatura;
updateTemp (temperatura);
  }

  si (humedad != humedad_viejo) {
humidity_old = humedad;
updateHum(humedad);
  }
}

Dependiendo de si uno de los valores cambia, se llama una función asociada. Decidí usar la función updateTime() del ejemplo EPD1in54ShowRunningTime como plantilla y crear dos nuevas funciones para la temperatura y la humedad a partir de ella.


Ambos valores se examinarán por separado y se actualizarán también por separado en la pantalla. Dependiendo del valor que haya cambiado. Entonces sólo se cambia una pequeña ventana (área parcial) en la pantalla, o dos para los valores respectivos. La imagen de fondo permanece y no se reescribe. Esto ahorra energía y es un poco más rápido. Aquí está el código fuente de la antigua Display V1:

anular actualizaciónTemp(flotante temperatura) {
  char ¿Cómo puedo hacerlo? {'0', '0', '\0'};
dtostrf(temperatura, 2, 0, temp_string);
 
pintura.setWidth(30);
pintura.SetHeight(21);
 
pintura.claro (SIN COLOR);
pintura.Método de codificación de datos:(2, 2, temp_string, & Font24, COLORADO);
epd.memoria setframe (pintura.getImage(), 30, 159, pintura.getwidth (), pintar.Nuestros servicios());
epd.displayFrame();
epd.memoria setframe (pintura.getImage(), 30, 159, pintura.getwidth (), pintar.Nuestros servicios());
epd.displayFrame();
}

anular updateHum(flotante humedad) {
  char ¿Cómo puedo hacerlo? {'0', '0', '\0'};
dtostrf(humedad, 2, 0, temp_string);
 
pintura.setWidth(30);
pintura.SetHeight(21);
 
pintura.claro (SIN COLOR);
pintura.Método de codificación de datos:(2, 2, temp_string, & Font24, COLORADO);
epd.memoria setframe (pintura.getImage(), 30, 93, pintura.getwidth (), pintar.Nuestros servicios());
epd.displayFrame();
epd.memoria setframe (pintura.getImage(), 30, 93, pintura.getwidth (), pintar.Nuestros servicios());
epd.displayFrame();
}

Cada una de las funciones se pasa los datos del sensor. Se crea una matriz de caracteres, que se llena con 0. Entonces los datos del sensor pasado se escriben en la matriz. En el proceso, los dígitos se convierten en caracteres.


La función dtostrf() para convertir también puede escribir decimales en la matriz. Elegí omitir los decimales porque el DHT11, a diferencia de otros sensores, no emite decimales (aunque el tipo de datos de la boya lo permitiría). Si utiliza otro sensor, tendría la posibilidad de mostrar los decimales en este punto. Para ello, cambie el segundo parámetro y especifique toda la longitud del valor, incluyendo el punto decimal.


Como tercer parámetro, introduzca el número de decimales. En mi caso, los números tienen dos dígitos y ningún decimal. El 2 y el 0 significan esto.

Los tamaños de las ventanas que se van a actualizar se introducen en el objeto de la pintura. Tienes que intentarlo un poco hasta que todo esté en el lugar correcto. Esto se hace un poco más fácil si se establece el color a negro. Entonces puedes ver dónde se encuentra la ventana respectiva y puedes posicionarla mejor. Estas áreas son entonces sobrescritas con un solo color. Luego la respectiva cadena se genera como texto, se escribe en la memoria intermedia de la pantalla y se imprime al final.

Por supuesto, las dos funciones pueden combinarse en una sola para evitar el código redundante y hacer el código fuente un poco más ligero. Pero no voy a entrar en eso aquí y dejarlo como está.

Si cargamos el programa en la D1-Mini, primero aparece el logo y luego los valores del sensor. Dependiendo de cuál de los dos valores cambie, se actualizará en la pantalla.

Dos cosas pueden verse inmediatamente en la imagen. En primer lugar, el D1-Mini no tiene fuente de alimentación y la pantalla sigue mostrando los últimos valores. En segundo lugar, actualmente hace bastante calor.

Para usar el programa con el ESP32, sólo tienes que cambiar los números de los alfileres de nuevo, o simplemente comentar la línea correspondiente:

// Introduzca la línea para el tablero deseado
// ****************************************************
//
// ESP32:
EPD1in54 epd(33, 25, 26, 27);   // restablecer, dc, cs, ocupado
//
/Descripción del producto:
// EPD1in54 epd(5, 0, SS, 4); // restablecer, dc, cs, ocupado

Es posible que tenga que cambiar el pin de entrada del sensor de temperatura en la configuración() si su placa ESP32 no tiene un pin con el número 16.

dht.setup(16, DHTesp::DHT11);  // Pin D0 / GPIO16

Descargar el programa completo: EPDESP32ESP8266V1DHT11

Ahora queremos implementar lo mismo con la nueva Display V2. Volvemos al ejemplo de epd1in54_V2. El código fuente se ve relativamente similar a la antigua pantalla. Los nombres de las funciones sólo difieren ligeramente. Los procesos son los mismos.

Como actualizamos los datos de temperatura en la pantalla tan pronto como cambian, hay que hacer un refresco parcial. Esto refresca la pantalla con los nuevos valores en el punto donde están los números. Este también fue el caso en la versión antigua. En la nueva versión de la biblioteca tienes que cargar la imagen de fondo estática con DisplayPartBaseImage(). Los datos de temperatura se muestran con DisplayPartFrame() en lugar de DisplayFrame().

Pruebe el programa usted mismo:

Descargar el programa completo: EPDESP32ESP8266V2DHT11

Resumen provisional

Después de varias pruebas tuve que determinar que la biblioteca para la nueva pantalla desafortunadamente no funciona como la versión antigua. Esto llevó a que en mis pruebas la imagen fuera sólo muy pálida de ver. Sólo después de que la temperatura se actualizara varias veces, la imagen de fondo se mostraba cada vez más saturada.


El borde exterior de la pantalla pulsa ligeramente, incluso si no se actualiza nada. Así que no estoy realmente satisfecho con ello. Tampoco he encontrado más información en los wikis del fabricante sobre este comportamiento. Sin embargo, esto sólo afecta a la actualización parcial de la pantalla. La salida normal del contenido de la pantalla completa parecía normal. Tal vez no estoy usando las ejecuciones de las funciones correctamente. Desafortunadamente toda la biblioteca no está bien documentada. Excepto por algunos consejos en la página web de Waveshare, no se puede encontrar ningún enfoque, por desgracia.

Una vez más con GxEPD2

Se cristaliza tan lentamente que tiene sentido usar esta biblioteca. Es muy extenso, actualmente se está desarrollando y adaptando a las pantallas. Ahora me gustaría implementar el ejemplo anterior con esta biblioteca alternativa.


Para ello, fusionamos los códigos fuente de los programas que ya hemos escrito. Obtenemos el flujo del programa para la medición de la temperatura a partir de los bocetos anteriores en los que utilizamos las otras bibliotecas. Para la salida en la pantalla, usamos el programa que usamos antes para mostrar nuestras propias imágenes. Incluimos las siguientes bibliotecas:

#include
#include <Fuentes/FreeSans12pt7b.h>
#include "imagedata.casa"
#include "DHTesp.casa"

En la siguiente parte del programa puede elegir de nuevo entre la pantalla V1 o V2, y los procesadores ESP32 o ESP8266. Comente la línea correcta para esto. Entonces presta atención de nuevo al cableado de los alfileres. A continuación, volvemos a declarar las variables de temperatura y humedad y una instancia de objeto DHTesp.

flotante temperatura = 0.0;
flotante temperatur_old = 0.0;
flotante humedad = 0.0;
flotante humidity_old = 0.0;

DHTesp dht;

En setup() inicializamos el sensor de temperatura y luego la pantalla. Primero se muestra el logo de AZ y después de una breve pausa la imagen de fondo que te mostré antes:

anular configuración() {
// Serie.Comienzo(115200);
Nivel de Cifrado WEPconfiguración(16, DHTesp::DHT11); // Pin D0/gpio16
Mostrar.inicio();
Mostrar.setRotation(0);
Mostrar.setFullWindow();

  // AZLogo
Mostrar.Pantalla de relleno (GxEPD_BLACK);
Mostrar.DrawBitmap(0, 0, AZLogo, 200, 200, GxEPD_WHITE);
  mientras (Mostrar.SiguientePágina());
 
retraso(2000);

  // Fondo
Mostrar.Pantalla de relleno (GxEPD_BLACK);
Mostrar.DrawBitmap(0, 0, Fondo, 200, 200, GxEPD_WHITE);
  mientras (Mostrar.SiguientePágina());

}

Podemos tomar la función loop() completamente como está. Sólo dupliqué las llamadas para la salida. Sucedió que los valores no se mostraron correctamente. Esta es mi solución:

anular bucle() {
temperatura = dht.getTemperature();
humedad = dht.getHumidity();

  si (temperatura != temperatura_viejo) {
temperatur_old = temperatura;
updateTemp (temperatura);
updateTemp (temperatura);
  }

  si (humedad != humedad_viejo) {
humidity_old = humedad;
updateHum(humedad);
updateHum(humedad);
  }
}

En las dos funciones updateTemp() y updateHum() la salida en la pantalla debe ser reemplazada:

anular actualizaciónTemp(flotante temperatura) {
  char ¿Cómo puedo hacerlo? {'0', '0', '\0'};
  int16_t Tbx, Tby;
  Sistema abierto. Tbw, tbh;
 
dtostrf(temperatura, 2, 0, temp_string);

  Sistema abierto. x = 30;
  Sistema abierto. Yahoo = 178;
Mostrar.¿Cómo puedo hacerlo?);
Mostrar.Esta es la página de configuración del teléfono.);
Mostrar.setText color (GxEPD_BLACK);
Mostrar.Ventana setpartial (tbx, tby, tbw, tbh);
Mostrar.primeraPágina();
  hacer {
Mostrar.Pantalla de relleno (GxEPD_WHITE);
Mostrar.setCursor (x, y);
Mostrar.de impresión(temp_string);
  } mientras (Mostrar.SiguientePágina());
}

anular updateHum(flotante humedad) {
  char ¿Cómo puedo hacerlo? {'0', '0', '\0'};
  int16_t Tbx, Tby;
  Sistema abierto. Tbw, tbh;
 
dtostrf(humedad, 2, 0, temp_string);

  Sistema abierto. x = 30;
  Sistema abierto. Yahoo = 112;
Mostrar.¿Cómo puedo hacerlo?);
Mostrar.Esta es la página de configuración del teléfono.);
Mostrar.setText color (GxEPD_BLACK);
Mostrar.Ventana setpartial (tbx, tby, tbw, tbh);
Mostrar.primeraPágina();
  hacer {
Mostrar.Pantalla de relleno (GxEPD_WHITE);
Mostrar.setCursor (x, y);
Mostrar.de impresión(temp_string);
  } mientras (Mostrar.SiguientePágina());
}

Las variables tbx, tby, tbw y tbh se llenan con los valores que ocupará la ventana parcial. La abreviatura "tb" significa "límite de texto". Ya te había introducido la función dtostr().

(También hay otra forma mostrada en el GxEPD2_Ejemplo. Para este propósito la función helloValue().)

Las variables x e y son el punto de esquina de nuestra ventana de salida. Note aquí que no es la esquina superior izquierda, sino la línea de base del texto. Se puede encontrar información al respecto en el manual de la biblioteca Adafruit_GFX en la sección "Uso de las fuentes GFX en los bocetos de Arduino".


La llamada a la función getTextBounds() también es de esta biblioteca. Se le pasa la cadena que se va a emitir y las coordenadas donde se debe mostrar la cadena. Los otros cuatro parámetros son las variables de frontera de texto mencionadas anteriormente. No sirven como parámetros de paso, sino que sirven para dar a conocer la memoria en la que se almacenan los resultados de la función. Son casi cuatro valores de retorno de una función.
Usar los valores puede ser un poco confuso. Esto se debe a que la línea de base, no la esquina superior izquierda, es el punto de anclaje del texto a emitir. La siguiente imagen debe ilustrar cómo se entiende:

Especificamos con x e y dónde debe ubicarse el texto. La función getTextBounds() calcula ahora a partir del texto el tamaño de la ventana que se debe cambiar, en la que se muestra el texto. Los valores tbx y tby representan entonces la esquina superior izquierda de la ventana calculada. Para la anchura y la altura se utilizan tbw y tbh.

Las siguientes líneas probablemente se expliquen por sí solas. Se establece la fuente y luego el color para el texto (por supuesto, sólo tenemos la opción de elegir entre blanco y negro). Con setPartialWindow(tbx, tby, tbw, tbh) establecemos el área que cambiará después. Aquí las coordenadas tbx y tby son para la esquina superior izquierda, no la línea de base.

Lo último que hay que hacer es llenar la ventana con un color y luego poner el cursor, es decir, el comienzo del texto, en las coordenadas x y y. Aquí está de nuevo la línea de base. Luego se escribe el texto.

La fuente debe ser incluida como un archivo de encabezamiento (ver arriba). Puedes encontrar un resumen de las fuentes incluidas aquí. Si necesitas otros tamaños o tipos de fuentes, puedes hacerlo con este convertidor de fuentes en línea, que produce archivos de encabezado ya preparados. Tienes que copiarlos en la carpeta de fuentes de la biblioteca. Ya te dije cómo encontrar la biblioteca. Busca en la carpeta "bibliotecas" la carpeta GxEPD2 y allí las fuentes de la carpeta.

Una visión general de todas las funciones del AdafruitGFX se puede encontrar [aquí](http://adafruit.github.io/Adafruit-GFX-Library/html/classadafruit__gf_x.html). La biblioteca GxEPD2 en combinación con la biblioteca GFX es una herramienta muy poderosa para mostrar en las pantallas.

Al cargarlo en el microcontrolador, debería aparecer la misma pantalla que antes con el otro boceto.

Descargar el programa completo: GxEPD2ESP32ESP8266V1undV2DHT11

He combinado las dos funciones de temperatura y humedad y así he acortado un poco el código fuente:

Descargar el programa completo: GxEPD2ESP32ESP8266V1undV2DHT11_B

Los datos de la WLAN

Ahora llegamos al último punto que anuncié. Con el ESP32 y también el ESP8266 es posible conectarse a una red WLAN. Primero intentemos mostrar los datos de la red en el monitor de serie. Después de eso nos encargamos de que estos datos aparezcan en la pantalla de E-Paper.

Quiero entrar en mi WLAN y luego mostrar mi IP, el nombre de la red (SSID), el canal utilizado y la intensidad de la señal (en dBm).

Empecemos de nuevo con la pantalla V1. Incluimos la biblioteca ESP8266WiFi.h o WiFi.h, dependiendo del tablero que utilice. En setup() inicializamos la conexión a través de WLAN:

# si está definido (ESP8266)
#include
#elif definido (ESP32)
#include Descripcióncasa>
#endif

anular configuración() {
Serie.comenzar(115200);
Sistema abierto.comenzar("SU SSID", "SU CLAVE WIFI"); // SSID, CLAVE
Serie.imprimir("Conectar");
    mientras Sistema abierto.estado() != WL_CONNECTED) {
retraso(500);
Serie.imprimir(".");
      }
Serie.Información();
Serie.imprimir("Conectado, dirección IP: ");
Serie.println (WiFi.LocalIP());
Serie.imprimir("Difusión SSID: ");
Serie.println (WiFi.Difusión SSID());
Serie.imprimir("Canal: ");
Serie.println (WiFi.canal());
Serie.imprimir("Fuerza de la señal: ");
Serie.impresión (WiFi.RSSI());
Serie.Información(" Operador dBm");}

anular bucle() {

}

Para el SSID y la CLAVE, por favor, introduzca sus propios datos antes de cargar el programa en su microcontrolador. Si todo funciona, deberías ver la dirección IP, el SSID, el canal y la intensidad de la señal en el monitor de serie.

Ahora queremos insertar este código en el programa que usamos para la pantalla de e-paper. Eliminamos la segunda imagen de fondo y reemplazamos los datos climáticos con los datos de la WLAN. Podemos eliminar las dos funciones de temperatura y humedad. 


El loop() también puede dejarse vacío ya que sólo necesitamos recuperar los datos una vez. Sigo usando la biblioteca de la EPD. Del ejemplo EPD1in54ShowRunningTime, podemos tomar el código fuente para mostrar el texto del setup(). Para la salida del texto, necesitamos una matriz de caracteres como búfer para algunos datos. Declaramos esto globalmente:

char ¿Cómo funciona? {'0', '0', '0', '\0'};

En el setup() debería haber insertado ahora la inicialización de la red WLAN como mostré en el ejemplo anterior. Luego se inicializa la pantalla y se imprime el logo de AZ. Después mostramos los mismos datos que en el monitor en serie de la EPD:

pintura.setRotate (ROTATE_0);
pintura.setWidth(200);
pintura.SetHeight(18);
 
pintura.claro (COLOR);
pintura.Método de codificación de datos:(0, 2, "WIFI conectado:", & Font16, SIN COLOR);
epd.memoria setframe (pintura.getImage(), 0, 0, pintura.getwidth (), pintar.Nuestros servicios());
  
pintura.claro (SIN COLOR);
pintura.Método de codificación de datos:(0, 2, "Dirección IP:", y Font16, COLORADO);
epd.memoria setframe (pintura.getImage(), 0, 20, pintura.getwidth (), pintar.Nuestros servicios());
 
pintura.claro (SIN COLOR);
pintura.Método de codificación de datos:(0, 2Acerca delocalIP ().toString ().C_str (), y Font16, COLORADO);
epd.memoria setframe (pintura.getImage(), 0, 40, pintura.getwidth (), pintar.Nuestros servicios());
 
pintura.claro (SIN COLOR);
pintura.Método de codificación de datos:(0, 2, "Difusión SSID:", y Font16, COLORADO);
epd.memoria setframe (pintura.getImage(), 0, 60, pintura.getwidth (), pintar.Nuestros servicios());
 
pintura.claro (SIN COLOR);
pintura.Método de codificación de datos:(0, 2Acerca deDifusión SSID().C_str (), y Font16, COLORADO);
epd.memoria setframe (pintura.getImage(), 0, 80, pintura.getwidth (), pintar.Nuestros servicios());
 
pintura.claro (SIN COLOR);
pintura.Método de codificación de datos:(0, 2, "Canal:", y Font16, COLORADO);
epd.memoria setframe (pintura.getImage(), 0, 100, pintura.getwidth (), pintar.Nuestros servicios());
 
dtostrf (WiFi.canal(), 2, 0, tempString);
pintura.claro (SIN COLOR);
pintura.Método de codificación de datos:(0, 2, tempString, & Font16, COLOREADO);
epd.memoria setframe (pintura.getImage(), 0, 120, pintura.getwidth (), pintar.Nuestros servicios());
 
pintura.claro (SIN COLOR);
pintura.Método de codificación de datos:(0, 2, "Fuerza de la señal:", y Font16, COLORADO);
epd.memoria setframe (pintura.getImage(), 0, 140, pintura.getwidth (), pintar.Nuestros servicios());
 
Señal de cadena, cadena = cadena (WiFi.RSSI ()) + " Operador dBm";
pintura.claro (SIN COLOR);
pintura.Método de codificación de datos:(0, 2cadena de señal.C_str (), y Font16, COLORADO);
epd.memoria setframe (pintura.getImage(), 0, 160, pintura.getwidth (), pintar.Nuestros servicios());
 
epd.displayFrame();

La dirección IP puede ser devuelta como una cadena con .toString(). Sin embargo, la función drawStringAt() espera una matriz de caracteres. Así que añadimos .c_str() al final. Entonces funciona. El SSID ya ha sido devuelto como una cuerda. También convertimos eso en una matriz de caracteres. Para el canal utilizamos de nuevo la función dtostrf(), que ya fue utilizada para los datos de temperatura. Para ello, también se necesita la matriz de caracteres previamente declarada, que creamos como un amortiguador.

He reescrito el código fuente para que puedas ver en la pantalla si la conexión WLAN se estableció o no. Para la fuerza de la señal implementé otra posibilidad para emitir números y texto. Como queremos añadir la unidad de medida dBm al valor, he utilizado la clase String y la función de conversión String(). Entonces podemos concatenar fácilmente dos cadenas y pasar el resultado con .c_str() para dibujarStringAt().

Al cargar el programa en el D1 Mini, la pantalla debería mostrar primero el logo de AZ y luego los datos de su red WLAN. La misma información también se muestra en el monitor de serie.

Descargar el programa completo: EPDESP8266WifiData_V1

Ahora también podrías escribir la salida en la función loop(), si la fuerza de la señal cambia y quieres tener esta información siempre actualizada. El código fuente para la salida de las líneas de texto podría acortarse para evitar código redundante.

Para completar, reescribimos el programa para la Display V2. Hacemos los mismos cambios que hicimos para el proyecto DHT11. Cambiamos las inclusiones de las bibliotecas. Fíjense en las comillas, en lugar de los corchetes:

#include "epd1in54_V2.casa"
#include "epdpaint.casa"

Entonces la clase debe ser renombrada:

/Descripción del producto:
Epd epd(5, 0, OESTRADIOL, 4); // restablecer, dc, cs, ocupado

También cambiamos la inicialización de la pantalla, así como la limpieza de la pantalla y la salida del logotipo de AZ:

epd.HDirInit();
epd.Claro();
epd.Exhibición (AZLogo);
retraso(2000);
epd.Claro();

A excepción de los cambios ya mencionados de los nombres de las funciones, también necesitamos cambiar el posicionamiento:

pintura.Sistema abierto.(0, 2, "WIFI conectado:", & Font16, SIN COLOR);
epd.Setframe memoria(pintura.GetImage(), 0, 0, pintura.Getwidth (), pintura.GetHeight());

convertir:

pintura.Sistema abierto.(0, 2, "WIFI conectado:", & Font16, SIN COLOR);
epd.Setframe memoria(pintura.GetImage(), 0, 180, pintura.Getwidth (), pintura.GetHeight());

Todas las posiciones y ahora tienen valores en 20 pasos hacia abajo, en lugar de hacia arriba.

Nota : He notado que no se puede mostrar nada por encima de un valor y de 180. Es por eso que la pantalla completa se ha movido hacia abajo en una línea. Si quieres usar la pantalla completa, la última línea se corta.

Descargue el programa completo: EPDESP8266WifiData_V2

Por último, pero no menos importante, ahora reescribiremos esto para la biblioteca GxEPD2. Reemplazamos a los incluidos:

#include
#include
#include "imagedata.casa"

Y eliminar todas las líneas que pertenecen a la clase epd.


Hemos establecido las inicializaciones para las clases de visualización:

// Introduzca la línea para el tablero deseado
// ****************************************************
//
// 1,54" 200x200 V1 (viejo):
// -----------------------
// ESP32:
// GxEPD2_BW<GxEPD2_154, GxEPD2_154::HEIGHT> display(GxEPD2_154(26, 25, 33, 27)); // CS, DC, RST, Ocupado //GDEP015OC1 ya no disponible
/Descripción del producto:
// GxEPD2_BW<GxEPD2_154, GxEPD2_154::HEIGHT> display(GxEPD2_154(SS, 0, 5, 4)); //CS, DC, RST, BUSY //GDEP015OC1 ya no disponible
//
// 1.54 " 200x200 V2 (Artículo nuevo):
// -----------------------
// ESP32:
Pantalla GxEPD2_BW<GxEPD2_154_D67, GxEPD2_154_D67::HEIGHT> (GxEPD2_154_D67(26, 25, 33, 27)); // CS, DC, RST, ocupado / / GDEH0154D67
/Descripción del producto:
// GxEPD2_BW<GxEPD2_154_D67, GxEPD2_154_D67::HEIGHT> display(GxEPD2_154_D67(SS, 0, 5, 4)); // CS, DC, RST, Ocupado // GDEH0154D67

Luego reemplazamos la inicialización de la pantalla en setup() y nos hacemos cargo de la salida del logo de AZ del programa GxEPD para la visualización de nuestra propia imagen:

Mostrar.inicio();
Mostrar.setRotation(0);
Mostrar.setFullWindow();

// AZLogo
Mostrar.Pantalla de relleno (GxEPD_BLACK);
Mostrar.DrawBitmap(0, 0, AZLogo, 200, 200, GxEPD_WHITE);
mientras (Mostrar.SiguientePágina());

retraso(2000);
Mostrar.Pantalla de relleno (GxEPD_WHITE);
mientras (Mostrar.SiguientePágina());

La biblioteca GxEPD2 ofrece la posibilidad de emitir textos de la misma manera que se acostumbra desde el monitor en serie. Al igual que en la biblioteca de la EPD, la memoria intermedia de la imagen puede escribirse primero y luego salir completamente a la pantalla. Cuando se llama a la función drawPaged(), se pasa otra función junto con otro parámetro:

Mostrar.drawPaged(Título, 0);
Mostrar.Diseñamos y desarrollamos soluciones integrales para tu negocio., 0);

Mira más de cerca el ejemplo de GxEPD2_PagedDisplayUsingCallback. Mostraremos dos áreas parciales.

Para ello, necesitamos dos funciones. Uno para el encabezamiento, cuyo texto es blanco y el fondo es negro:

anular Titular(Construir anular*) {
  int16_t Tbx, Tby; Sistema abierto. Tbw, tbh;
Mostrar.Esta es la página de configuración del teléfono.);
Mostrar.getTextBounds("Texto de prueba", 0, 0, &tbx, &tby, &tbw, &tbh);
 
Mostrar.setText color (GxEPD_WHITE);
Mostrar.setpartial ventana(0, 0, Mostrar.Ancho (), tbh + 3);
Mostrar.Pantalla de relleno (GxEPD_BLACK);
Mostrar.setCursor(0, tbh + 1);
Mostrar.Información("WIFI conectado:");
}

La segunda función emitirá todos los datos Wi-Fi:

anular WifiDataPaged(Construir anular*) {
  int16_t Tbx, Tby; Sistema abierto. Tbw, tbh;
Mostrar.Esta es la página de configuración del teléfono.);
Mostrar.getTextBounds("Texto de prueba", 0, 0, &tbx, &tby, &tbw, &tbh);
 
Mostrar.setText color (GxEPD_BLACK);
Mostrar.setpartial ventana(0, tbh + 3, Mostrar.ancho (), pantalla.altura() - tbh + 3);
Mostrar.Pantalla de relleno (GxEPD_WHITE);
Mostrar.setCursor(0Acerca de Nosotros * 2) + 5);
Mostrar.Información("Dirección IP:");
Mostrar.println (WiFi.LocalIP());
Mostrar.Información("Difusión SSID:");
Mostrar.println (WiFi.Difusión SSID());
Mostrar.Información("Canal:");
Mostrar.println (WiFi.canal());
Mostrar.Información("Fuerza de la señal:");
Mostrar.impresión (WiFi.RSSI());
Mostrar.Información(" Operador dBm");
}

La función del programa debería ser ahora la misma que la de la biblioteca de la EPD. Cargue el programa en el tablero de su elección. No te olvides de comentar la línea correcta antes.

Descargar el programa completo: GxEPD2ESP32ESP8266WifiDataV1undV2

Conclusión

La biblioteca de EPD sólo es adecuada para la pantalla ePaper de 1,54" en la versión 1. Sin embargo, funciona muy bien con él. Cuando se usa, es relativamente fácil cambiar entre ESP32 y ESP8266. Si conectas la pantalla con la versión 2, los resultados ya no son 100 por ciento satisfactorios. Sólo existe la biblioteca directamente del fabricante para esto, que aún debe ser adaptada.

Así que te recomiendo que uses la biblioteca GxEPD2. Necesitas tiempo para trabajar con los ejemplos y entender cómo funciona todo. Pero es flexible en cuanto a la versión de la pantalla y la elección del microcontrolador.


Se admiten muchas más pantallas. La biblioteca es muy pesada y tarda mucho más en ser compilada. Sin embargo, valdrá la pena, ya que se pueden implementar muchas ideas con él. Vale la pena echar un vistazo a los muchos ejemplos.

Espero haber sido capaz de ayudarte a implementar proyectos similares, o inspirar tu creatividad, con esta serie de blogs.

Andreas Wolter


para el blog de AZ-Delivery


DisplaysEsp-32Projekte für anfängerSensoren

15 comentarios

Andreas Wolter

Andreas Wolter

@R.Parusel: ja das ist es in der Tat. Daher auch die Probleme, die aus dem ersten Teil dieser Blogreihe resultierten. Es ist wichtig zu wissen, welches Display das ist, wie viele Farben es unterstützt. Ich würde mich dann durch die Beispiele hangeln. Dort muss man eigentlich nur die passende Zeile für das Board einkommentieren und natürlich auch die Pinbelegung passend konfigurieren. Ich tippe bei Ihrem Board auf die V1.

Grüße,
Andreas Wolter
AZ-Delivery Blog

R.Parusel

R.Parusel

Hallo,
ich habe hier eine 1.54" ePaper mit einem Kontrollerboard V2 und einem Display von V1, auf dem Flachbandkabel steht 2015 08.01. Mit verlaub, alles sehr verwirrend.
Ich versuche schon einige Zeit es zum Laufen zu bekommen. Bisher ohne Erfolg.
Viele Grüsse

Gerd

Gerd

Vielen Dank für deinen ausführlichen Artikel!
Ich habe eine neuere Variante des waveshare 1,54“ BW Displays am esp8266 D1 mini. Aufkleber V2, Rev.2.1.
Mit der Deklaration GxEPD2_BW<GxEPD2_154_D67 funktionieren die partiellen Fenster nicht. Keine Anzeige im partiellen Fenster.
In diesen Fall ist GxEPD2_BW<GxEPD2_150_BW zu verwenden. Siehe https://forum.arduino.cc/t/waveshare-e-paper-displays-with-spi/467865/3125
Um einen Sensor BME280 per i2c anschließen zu können, änderte ich die Pin’s am esp für RST und Busy des ePaper-Moduls. RST an D4 (GPIO 2) und Busy an D6 (GPIO 12).
display(GxEPD2_DRIVER_CLASS(/CS=15/ EPD_CS, /DC=D3/ 0, /RST=D4/ 2, /BUSY=D6/ 12));
Bei dieser Belegung ist ein Widerstand 4k7 von D8 gegen GND und ein Widerstand 1k von D4 an 3,3V anzuschließen.

Andreas Wolter

Andreas Wolter

@Carl Werner: Vielen Dank für den Hinweis. Wurde korrigiert.

Grüße,
Andreas Wolter
AZ-Delivery Blog

Carl Werner

Carl Werner

Die letzte Version des Skriptes (WifiData) ist wohl falsch verlinkt:
es erscheint nochmal die Version für die epd-Bibliothek, statt der für Gxepd2

Andreas Wolter

Andreas Wolter

@Georg: Vielen Dank. Nach meinem Kenntnisstand kann man die SPI-Schnittstelle teilen. Lediglich des CS Pin muss sich unterscheiden. Es gibt für die GxEPD2 Bibliothek ein Beispiel namens GxEPD2_MultiDisplay. Ich würde sagen, es ist sehr wahrscheinlich, dass es funktioniert. 100%ig sicher bin ich mir jedoch nicht.
Hier wurde diese Frage auch gestellt: https://forum.arduino.cc/t/two-pcd8544-on-wemos-d1-mini/484521/2
und mit Ja beantwortet.
Probieren Sie es aus und lassen uns wissen, ob es funktioniert hat.

Grüße,
Andreas Wolter
AZ-Delivery Blog

Joachim

Joachim

Toller Beitrag, herzlichen Dank zunächst! Ich erwäge, zwei Module an einem Board abzuschließen (vermutlich auch zwei größere, bspw. 4,3 Zoll). Das soll später per MQTT durch den home Assistant mit Daten gefüttert werden.
Meldet Frage: ist es grundsätzlich möglich, zwei epaper an ein Board anzuschließen und welches hätte ausreichend Anschlüsse? Das D1 dürfte wohl zu klein dafür sein…

Andreas Wolter

Andreas Wolter

@Dalwinder: There is no complete download of all sketches in a ZIP at this moment. If you click on all download links you will get all files.
It then depends on which microcontroller and display you are currently using.

im Moment gibt es keinen kompletten Download von allen Sketches in einer ZIP. Wenn Sie alle Download-Links anklicken, erhalten Sie alle Dateien.
Es hängt dann davon ab, welchen Mikrocontroller und welches Display Sie momentan verwenden.

Andreas Wolter
AZ-Delivery Blog

Dalwinder

Dalwinder

i want to see how e-paper display works. it is putting me close loop. some time this , some time that file is not included. i need a complete zip to download and see how does it looks like , please give me some way out . THANKS every body over there.

Markus Walsleben

Markus Walsleben

Hallo Herr Taz,
hier meine späte Antwort auf ihre Frage, die ich aber möglicherweise auch nicht richtig verstanden habe.
Die Library binde ich ich PIO-üblich über die Suche und dann “Add to Project” ein.
Dann habe ich in meinem Quelltext nur noch die Einbindung der passenden Variante (“#include ”) und dann definiere ich die Pins mittels
#define CS_PIN 26
#define DC_PIN 16
#define RST_PIN 22
#define BUSY_PIN 21
und der passenden Zeile
GxEPD2_BW<GxEPD2_154_D67, GxEPD2_154_D67::HEIGHT> display(GxEPD2_154_D67(CS_PIN, DC_PIN, RST_PIN, BUSY_PIN)); // GDEH0154D67

Für die Initialisierung habe ich eine eigene Routine:
void initDisplay()
{
display.init(); // uses standard SPI pins, e.g. SCK, MISO, MOSI, SS
// * special handling for Waveshare ESP32 Driver board * //
// ********************************************************* //
SPI.end(); // release standard SPI pins, e.g. SCK, MISO, MOSI, SS
//SPI: void begin(int8_t sck=-1, int8_t miso=-1, int8_t mosi=-1, int8_t ss=-1);
SPI.begin(18, 12, 23, 15); // map and init SPI pins SCK, MISO, MOSI, SS
// * end of special handling for Waveshare ESP32 Driver board * //
// **************************************************************** //
display.setRotation(0);
display.setFullWindow();
display.fillScreen(FillColor);
display.nextPage();
}
Danach ist das Display mit den display-Routinen wie gewünscht zu nutzen.

@Andreas Wolter: Sorry für die Verzögerung, die Mail ist einfach zu weit nach unten gerutscht.

uwetaz

uwetaz

Hallo Hr. Walsleben,
vielleicht hätten Sie einen Tipp für die Portierung nach PlatformIO für mich.
Nachdem mit einem V2-Display das Beispiel GxEPD2_Example in der Arduino IDE bei mir läuft wollte ich das Ganze auch nach PlatformIO portieren. Ich arbeite seit längerem mit den ESPs damit, weiß aber nicht wie ich das mit den Files für die Display selection machen muss. Ich habe zwar im Unterordner .pio\libdeps\esp32dev\GxEPD2 das Beispiel wiedergefunden, aber es gibt die selection Files für jedes Beispiel. Wo muss denn nun ein File angelegt werden? Könnten Sie vielleicht Ihre Struktur hier schreiben?

Das wäre sehr nett!

Christian Seel

Christian Seel

Vielen Dank für das Update zu “epd1in54V2”, ich dachte zunächst schon, das Display sei defekt! Um den Code zum Laufen zu bringen, war allerdings in epdif.h Zeile 34 arduino.h in Arduino.h zu ändern, in Datei epdif.h Zeile 32 spi.h in SPI.h. Vermutlich ist die Windows-IDE bei der Behandlung von Groß- und Kleinschreibung großzügiger als die Linux-Version.

Matthias Kasper

Matthias Kasper

Hallo,
habe dafür ein Gehäuse für den 3D-Druck erstellt. Es muss allerdings ein Board ohne Stiftleisten genutzt und die Leitungen angelötet werden.
Hier geht’s zur Druckvorlage → https://www.thingiverse.com/thing:4738646
Das Gehäuse besteht aus verschiedenen Unter und Oberteilen, die miteinander kombiniert werden können.
Viele Grüße
Matthias

csierra67

csierra67

Great tutorial, many thanks !
With these additonal explanations I have been able to put my display at work and try all of the proposed sketches.
For the information of other users, I own a b/w/r display and the driver that works best is
EPD2_154_Z90c
May save you some trials.

Markus Walsleben

Markus Walsleben

Ich freue mich sehr, dass die Artikelreihe fortgeführt wird. Ja, mit der EPD-Library hatte ich (wohl insb. wegen meines v2-Displays) so meine Probleme und bin deshalb gleich zur GxEPD2 gewechselt.
Hier möchte ich nun meine Erfahrungen teilen und Anmerkungen zum Artikel anbringen.
1. Das betrifft jetzt weder das Display noch eine der Libraries, sondern den Tipp mit dem Kondensator am ESP32. Die gleichen Probleme hatte ich anfangs auch mit der Arduino-IDE. Und diese Probleme waren komischerweise direkt nach dem Wechsel auf PlatformIO weg. Ich kann das nicht erklären, bin aber mit der aktuellen Situation zufrieden. Die Arduino-IDE ist ja auch um viele Längen langsamer, insbesondere beim kompilieren. Mit der GxEPD2 und PlatformIO fällt nicht auf, dass diese größer ist und länger benötigt.

2. Jetzt zum Display als solches. Ein E-Paper-Display wird ja vermutlich gerade in Hinblick auf den Stromsparenden Einsatz verwendet. Also Fälle, in denen der ESP nur zyklisch etwas erledigt, also Werte holt und/oder schickt und dann anzeigt und dann für eine Zeitlang wieder ruht. Dafür ist ja gerade der ESP32 mit dem Deep Sleep sehr gut geeignet. Hier sind dann auch die EPD zusammen mit der GxEPD2-Library sehr gut für vorbereitet, denn in dieser Library gibt es die Funktionen .powerOff() und .hibernate(). Diese schicken die Elektronik des Display schlafen und sorgen so für 1) noch weniger Stromverbrauch und 2) wird so verhindert, dass die beim “Schlafengehen” des ESP noch fließenden Spannungen den Inhalt des Display hässlich verändern.
Mit aktiviertem .hibernate() kann ich das komplette System (ESP+EPD) vom Strom nehmen und das Display zeigt über viele Stunden (ich habe keine Grenze gefunden, vielleicht ja unendlich?) das zuletzt ausgegebene Bild an.

3. Wer den ESP für längere Zeit schlafen legt, wird möglicherweise darüber stolpern, dass der ESP schon nach ~45 Minuten aufwacht. Das liegt am scheinbar oft verwendeten Beispiel zu liegen:

#define uS_TO_S_FACTOR 1000000
#define TIME_TO_SLEEP 7200
RTC_DATA_ATTR int bootCount = 0;

void setup(){
Serial.begin(115200);
delay(200);
++bootCount;
Serial.println("Boot number: " + String(bootCount));
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) + " Seconds");

Serial.println(“Going to sleep now”); esp_deep_sleep_start();

}
void loop(){
}

Die Lösung liegt darin, die Zeile in
esp_sleep_enable_timer_wakeup((uint64_t)(TIME_TO_SLEEP) * uS_TO_S_FACTOR);
zu ändern. Den Tipp fand ich nach langem Suchen hier: https://github.com/espressif/arduino-esp32/issues/796#issuecomment-347516325

Wer seinen ESP also nur für kurze Zeit schlafen legt, wird also damit keine Probleme bekommen. Es kann aber nicht schaden, das immer so zu programmieren.

Deja un comentario

Todos los comentarios son moderados antes de ser publicados