AZ-Touch Mod als analoge Uhr mit Anzeige für Sonnenauf und -untergang

Antes de abordar proyectos más grandes, en mi caso un sistema de control de acuarios completamente automático con algunas características, intento hacer subproyectos a partir de ellos y programar el conjunto más adelante. Esto tiene muchas ventajas, ya que se puede probar y optimizar el código antes de empezar con el panorama general. Este proyecto surgió porque primero quería consultar los datos de la salida y la puesta del sol, así como la zona horaria. Con estos pequeños datos, tuve la idea de crear un reloj analógico en el AZ-Touch wall mod, que también se utiliza en partes para el control del acuario. El AZ-Touch wall mod es perfectamente conveniente para estas tareas con algunas modificaciones.

Ya he utilizado algunas líneas de código en otros proyectos y pueden pasar por un bucle de optimización aquí. Sin embargo, para que el reloj no sea el único, también se visualiza en la pantalla la hora diaria de salida y puesta del sol. Pero para que no sólo se muestren textos simples, se deben utilizar imágenes monocromáticas en la pantalla. Cómo hacer esto y cómo convertir los mapas de bits en datos legibles para el ESP32 NodeMCU, por ejemplo, será el tema será de la publicación del blog de hoy.

El hardware y el software para este blog

Para que pueda reconstruir este blog, necesita los componentes de la Tabla 1:


Cantidad Componente
1 ESP32 NodeMCU Módulo WLAN WiFi Placa de desarrollo con CP2102 (modelo sucesor de ESP8266)
1 AZ-Touch Mod Set de carcasa de pared con la pantalla táctil 2,4 pulgadas para ESP8266 y ESP 32
1 AZ-Touch Mod Set de carcasa de pared con pantalla táctil de 2,8 pulgadas para ESP8266 y ESP32
1 Fuente de alimentación 12V para suministro de energía

Tabla 1: Componentes para el reloj analógico

El software que se necesita:

Además, necesita acceder a openweathermap.org, aunque la versión básica gratuita es completamente suficiente para este proyecto.

El programa LCD Image Converter

Cuando se desarrollan programas, siempre se debe asegurar de que todos entienden la salida en la pantalla. En el caso de los resultados de diagnóstico, es suficiente con el inglés o la lengua materna, pero en el caso de las interfaces gráficas para el usuario final, GUI por sus siglas en inglés, o bien hay que traducir todo a todos los idiomas, o bien se utilizan pictogramas claros.

Para mi reloj analógico, no quise escribirlo todo, especialmente por el espacio limitado, pero quería utilizar los pictogramas para la salida y la puesta del sol, consulte la Figura 1.

Mapas de bits

Figura 1: Mapas de bits para el reloj analógico

El problema es que he creado rápidamente las imágenes con Paint como mapas de bits, terminando con bmp, pero el AZ-Touch o el ESP32 NodeMCU no pueden leerlas. Como se trata de pictogramas simples, ahora se podría escribir una función en el código fuente, que utilice funciones de caracteres, círculos, líneas, etc., esto en la pantalla, pero esto es demasiado matemático y una imagen puede convertirse rápidamente en código máquina legible.

Convertidor de imágenes

Figura 2: El programa LCD Image Converter

Mi elección recayó en el programa LCD Image Converter, consulte la Figura 2, que es un editor de caracteres y fuentes muy sencillo, pero que también ofrece la posibilidad de convertir imágenes en código máquina. Le mostraré este último para imágenes de monocromáticas, pero también se puede utilizar para imágenes en color.

En primer lugar, hay que seleccionar la imagen que se va a convertir a través de Archivo -> Abrir, véase la figura 3.

Mapa de bits abierto

Figura 3: Carga de un archivo de imagen

Después de cargar la imagen, hay dos cambios interesantes en la interfaz. En primer lugar, se ve la imagen seleccionada en el centro y el tamaño de la imagen en la parte inferior derecha, aquí 64 x 64 píxeles.

A continuación, abrimos la interfaz de conversión a través de Opciones -> Conversión ..., véase la Figura 4.

Interfaz de conversión

Figura 4: interfaz de conversión abierta

Para que la imagen se muestra correctamente en la pantalla, en nuestro caso una imagen monocromática, todavía hay que ajustar la configuración. En primer lugar, el perfil se ajusta a "Monochrome" y en la pestaña "Scanning" Arriba a "Buttom", consulte Figura 5.

Actualizar la configuración de escaneo

Figura 5: Ajustar la configuración de escaneo

Esto hace que el código máquina tenga la orientación correcta, de arriba a abajo. A continuación, pase a la pestaña de Procesamiento, véase la figura 6.

Actualizar la configuración de procesamiento

Figura 6: Ajustar la configuración de preprocesamiento

Aquí se activa la opción "Inverse", de lo contrario la imagen no se coloreará en el color seleccionado posteriormente, sino que se coloreará el fondo de la imagen en la pantalla. Ahora pulse el botón "Show Preview" y el resultado se muestra en la siguiente ventana, véase la Figura 7.

Vista previa de salida

Figura 7: Vista previa de la imagen y del código máquina

Es interesante la parte derecha en la nueva ventana de Vista previa, donde se muestran los numerosos datos hexadecimales. Estos son ahora los datos de la imagen en código máquina, que es lo que se va a mostrar después en el AZ-Touch. Copie todo el contenido y cree un nuevo archivo de cabecera, por ejemplo, bitmap.h.

En primer lugar, inserte las siguientes líneas al principio del archivo, véase el Código 1.


 #ifndef _BITMAP_H
 #define _BITMAP_H
 #endif
 
 #ifdef ARDUINO_ARCH_AVR
 #include
 #else
 # include
 #endif
Código 1: Define el bitmap.h


Las primera 3 filas aseguran que el archivo de cabecera se almacena correctamente en el código. Las otras líneas aseguran que el pgmspace.h para microcontroladores ESP o Arduino se cargue correctamente.

Para que la imagen monocromática sunrise pueda ser utilizada posteriormente en el código fuente, hay que crear la variable correspondiente, véase Código 2.

 const no firmado carbonizarse amanecer[] PROGMEM = {
 
 };
Código 2. Crear una matriz para la imagen monocromática


Ahora añada el contenido copiado del convertidor de imágenes LCD a la matriz, véase el Código 3, que refleja el contenido acortado del archivo de cabecera recién creado.

 #ifndef _BITMAP_H
 #define _BITMAP_H
 #endif
 
 #ifdef ARDUINO_ARCH_AVR
 #include
 #else
 # include
 #endif
 
 // Icono de la puesta del sol de 64 * 64 píxeles
 const no firmado carbonizarse amanecer[] PROGMEM = {
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 ....
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };

Código 3: Código máquina para la matriz de la salida del sol, reducido en gran medida

Ahora se realiza el mismo procedimiento con la matriz para todos los los demás gráficos. Al final, dependiendo del número de gráficos, tendrá un archivo de cabecera con muchas líneas. Para los dos gráficos de este proyecto, hay algo menos de 150 líneas de código.

Con esto concluyen los preparativos del reloj analógico.

El reloj analógico en el AZ-Touch

En total, este proyecto más pequeño comprende algo menos de 500 líneas de código. Como siempre, el código está disponible para usted en mi repositorio de Github y está dotado de muchos comentarios, lo que también es una razón para las muchas líneas. Sin embargo, se explicarán algunas de las características y secciones con más detalle para que entienda cómo funciona el código.

Al principio del código fuente, se definen los colores del reloj, véase el código 4.

 / * --- Algunas definiciones de colores, no dude en cambiar --- * /
 #define face tft_orange
 #define numeric_point tft_black
 #define fondo tft_white
 #define hourcolor tft_red
 #define minutecolor tft_black

Código 4: Define los colores del reloj

Aquí puede cambiar el color según se quiera, preste atención a las definiciones en el archivo TFT_eSPI.h en la librería del mismo nombre. Esto simplifica enormemente el intercambio de colores.

Tras la inclusión de las librerías requeridas viene una de las partes más importantes para el proyecto, la configuración de los parámetros WLAN y los datos de la API requeridos para openweathermap.org, consulte el Código 5.

 contaminar Char * Ssid       = "";       // Cambiar SSID de la red
 contaminar Char * contraseña   = "";  // cambiar la contraseña de la red
 
 / * --- variables necesarias para openweathermap.org --- * /
 contaminar Cuerda apical = ""; // Cambiar la tecla API de OpenWeatherMap.org
 contaminar Cuerda localización = "";                   // Cambiar ubicación para OpenWeatherMap.org

Código 5: Acceso a la WLAN y la información de la API openweathermap.org

En este punto, introduzca los datos requeridos para que el ESP32 NodeMCU se pueda conectar posteriormente a Internet y también descargar los datos meteorológicos de openweathermap.org. Aquí ya debería haberse registrado en openweathermap.org.

La función setup() activa el TFT, la WLAN con los datos almacenados, sincroniza la hora de la ESP32 NodeMCU con el servidor NTP y dibuja los gráficos básicos en la pantalla. Para ver qué parte de la función setup () se está procesando actualmente, hay una especie de salida de estado en la pantalla, consulte la Figura 8.

AZ-TOUCH PRE OUTPUTE

Figura 8: Estado desde el inicio del programa

Así podrá ver que inmediatamente dónde el programa no puede progresar y dónde no se puede ver el reloj analógico. Esto ayuda enormemente cuando el AZ-Touch no está conectado al PC. Si todo se completa con éxito, el reloj se muestra con todos los datos después de 5 segundos, consulte la Figura 9.

Programa AZ-TOUCH

Figura 9: AZ-Touch con todos los datos

Como verá rápidamente, no sucede mucho en la función loop () en términos de alcance, consulte el Código 6. Sólo se llaman cuatro funciones requeridas y se envían los datos al monitor en serie.

 /*
 * =================================================================
 * Función: bucle
 * Devoluciones: Void
 * Descripción: Bucle principal para permitir que el trabajo funcione.
 * =================================================================
 */
 vacío círculo()
 {
   Tiempo de dibujo();
   Updateopenweathermapdata();
   Actualizar();
   Updateunsunset();
 
   // salida en serie
   SI(pprevsegundo != segundo() || Bfirstrun)
  {
     De serie.impresión(Daysoftthweek[día laborable()] + "., ");
     De serie.impresión(Getddigits(hora()) );
     De serie.impresión(":");
     De serie.impresión(Getddigits(minuto()) );
     De serie.impresión(":");
     De serie.Prender(Getddigits(segundo()) );
     pprevsegundo = segundo();
  }
 
   SI(Bfirstrun)
     Bfirstrun = falso;
 }

Código 6: La función loop () del proyecto

¡Pero aquí se presenta la ventaja! La función loop () no está sobrecargada y se puede intercambiar rápidamente el código. Las funciones tienen nombres únicos, por lo que rápidamente sabrá qué función hace cada paso. Sin embargo, me gustaría discutir todas las funciones de la función loop () en este instante.

DrawTime () hace que las manecillas del reloj se redibujen cada vez que cambia la hora o los minutos. Si se observa con detenimiento la función en el código fuente, primero se sobrescribe el antiguo puntero con el color de fondo de la pantalla y luego se dibuja el nuevo puntero. Aquí es donde está la mayor de las matemáticas para los punteros, ya que los punteros deben organizarse en el ángulo correcto de acuerdo con el tiempo. Dado que no dibujamos cada píxel individualmente en el código fuente, sino que definimos una línea con un punto de inicial y otro final, debemos calcular el punto final de los punteros a través de las funciones angulares seno y coseno, empezando desde el centro del reloj. Una vez hecho esto, se utiliza drawLine () para dibujar el puntero en el reloj.

No tema al exminar la función DrawTime () y las funciones llamadas en ella, incluso si el resultado final funciona.

Inmediatamente después de DrawTime () sigue la función UpdateOpenWeatherMapData (), que, como su nombre lo indica, solicita los datos actuales de OpenWeatherMap.org. Esto se realiza en tres pasos principales:

  1. Preparar y enviar la solicitud al cliente.
  2. Esperar una respuesta y preprocesar los datos requeridos, aquí el formato JSON.
  3. Preparar los datos a partir del formato JSON y almacenar los datos importantes

Esta parte del código es un poco más compleja porque se prepara un telegrama HTTPS para OpenWeatherMap.org, aquí a través de la función RequestData (), y la respuesta debe ser formateada correctamente. Para este propósito, deben eliminarse los datos innecesarios del telegrama de respuesta. Posteriormente, UpdateOpenWeatmapData () convierte la cadena JSON recibida en la clase correcta y extrae los datos de la zona horaria, la salida y la puesta del sol. Estos nuevos datos se comparan con los existentes y se activa una actualización de la interfaz GUI o de la zona horaria si hay algún cambio. Como los datos requeridos no cambian cada segundo, el trabajo descrito anteriormente solo se llevará a cabo cada 30 minutos.

Para asegurar que nuestro reloj analógico siempre muestre la hora correcta, el reloj interno del ESP32 NodeMCU se sincroniza con el servidor NTP cada 15 minutos utilizando la función ESP32 cada 15 minutos, por lo que nuestro reloj siempre debe correr al segundo.

Por último, está la función UpdateSunriseSunset (), que, en contraste con las funciones anteriores, es probablemente la más sencilla. Si la función UpdateOpenWeatherMapData () ha cambiado la salida y la puesta del sol, se borra la hora antigua de la pantalla y se introduce la nueva.

Por muy sencillo que parezca en teoría,las tres primeras funciones de la función loop () son bastante complejas. Por un lado, porque aquí se utilizan muchas matemáticas, y por otro lado, porque obtener los datos de OpenWeatherMap.org no es trivial. Una gran ayuda para obtener los datos fue la buena y detallada documentación de la API de OpenWeatherMap.org y el hecho de que ya he creado una función RequesData () similar para otro proyecto. Esto debería ser casi universalmente utilizable si desea solicitar datos de otro sitio para otro proyecto. Dado que no soy amigo de las transferencias http, la función RequestData () utiliza la variante más segura https, que también se puede utilizar para http.

El código fuente completo puede encontrarse aquí.

Preparación del proyecto

Antes de compilar el programa y frustrarse después porque falla. En el directorio del proyecto encontrará un archivo con el nombre User_Setup.h. Por favor, reemplácelo en la carpeta C: \ User \SU Nombre\ Documents \ Arduino \ Libraries \ TFT_eSPI, consulte la Figura 10. Tiene sentido cambiar el nombre del archivo allí con el mismo nombre, por ejemplo, User_Setup_old.h., primero.

Configuración de usuario

Figura 10: Sobrescribir User_Setup.h

Con los nuevos mods de AZ-Touch, no importa si usa la versión de 2,4 "o 2,8". Dado que ambas tienen la misma resolución, el código fuente se puede usar directamente para ambas versiones sin necesidad de realizar más ajustes.

¿Qué queda por hacer ahora? Bien, como se describió anteriormente, tiene que sobrescribir  los datos de WLAN y OpenWeatherMap.org con sus datos. Además, puede cambiar los colores a su voluntad o utilizar sus propios pictogramas para el reloj según las instrucciones anteriores. Para aquellos de ustedes que disfrutan de las matemáticas, puede dar a los punteros otras formas, no hay límites para la creatividad. Dado que todavía hay un poco de espacio en la pantalla, incluso sería concebible mostrar la fecha y el día de la semana en el reloj. Esta información ya está disponible en el código fuente, sólo hay que visualizarla en la posición correcta en la pantalla.

Espero que se divierta mucho con el reloj y que se despierte el interés en proyectos de IOT simples o más complejos.

Puede encontrar más proyectos para AZ-Delivery de mi parte en https://github.com/M3taKn1ght/Blog-Repo.

MuestraProyectos para principiantes

13 comentarios

Siegl

Siegl

Hallo
Vielen Dank für die schnelle Hilfe.Ich werde es versuchen.

Andreas Wolter

Andreas Wolter

@Siegl:
eigene Headerdateien müssen sich im gleichen Ordner befinden, wie die .ino Sketchdatei. Wenn man den Sketch öffnet, wird diese Datei ebenfalls in die IDE geladen. Man sieht dann im oberen Bereich einen Reiter mit dem Namen der Datei. Um den Sketchordner zu öffnen, kann man in der Arduino IDE im Menü “Sketch” den Punkt “Sketch-Ordner anzeigen” wählen, oder die Tastenkombination STRG+K. Die Headerdatei sollte dann noch per #include “headerdatei.h” eingebunden werden (wie es Jörn Weise im Sketchdatei getan hat). Dabei ist darauf zu achten, dass man den Namen dieser Headerdatei in Anführungszeichen setzt, statt in Pfeilklammern. Im Quellcode wurde der Hinweis hinterlassen, wie man die Datei einbindet: //This is a file in the same dir from this program(!!!)

Ich hoffe, ich konnte helfen.
Grüße,
Andreas Wolter

Siegl

Siegl

Hallo
Ich benötige noch einmal Hilfe.
Wie bekomme ich die “bitmap.h”in das Programm eingebunden ?
Danke

Siegl

Siegl

Arduino: 1.8.16 (Windows Store 1.8.51.0) (Windows 10), Board: “ESP32 Dev Module, Disabled, Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS), 240MHz (WiFi/BT), QIO, 80MHz, 4MB (32Mb), 921600, None”

Hallo
Ich bekomme immer diese Fehlermeldung.Was mache ich falsch?

In file included from C:\Users\User\Documents\Arduino\libraries\TFT_eSPI-master/TFT_eSPI.h:39:0,

from C:\Users\User\Documents\Arduino\sketch_oct05aopa\sketch_oct05aopa.ino:18:

C:\Users\User\Documents\Arduino\libraries\TFT_eSPI-master/User_Setup_Select.h:22:74: fatal error: User_Setup.h: No such file or directory

compilation terminated.

exit status 1

Fehler beim Kompilieren für das Board ESP32 Dev Module.

Dieser Bericht wäre detaillierter, wenn die Option
“Ausführliche Ausgabe während der Kompilierung”
in Datei → Voreinstellungen aktiviert wäre.

Rudolf

Rudolf

Habe den Fehler gefunden

/*

============= Function: RequestData Returns: String Description: Request to openWeathermap.org to get latest data =============
*/
String RequestData()
{
WiFiClientSecure client;
client.setInsecure(); <—————- diese Zeile fehlt im Programm. Ohne kann er keinen client.connect(clientAdress,443 ) aufbauen und es kommt zu “Failed to connect”
Jörn Weise

Jörn Weise

Hallo flai,
Vielen Dank für die Blumen. Wie bereits im Blog beschrieben, ist das nur ein Teilprojekt die etwas größeres, aber wie immer sollte man größere Projekte immer in kleinere Zwischenschritte unterteilen und manchmal kommt dabei auch etwas neues mit kleinen Änderungen raus.

Gruß
Weise

Willi Wegemann

Willi Wegemann

Hallo,
bekomme Fehler "cannot declare variable ‘ntpUPD’ tobe of abstract type ‘WiFiUPD’ " beim compilieren.
Wer weiss Rat ?
W.Wegemann
p.s. habe #include Time statt TimLib . Konnte TimeLib nicht finden. Server streikt

Rudolf

Rudolf

Hi

Habe das problem das ich keine Daten von http://api.openweathermap.org rein bekomme.
wenn ich die Adresse direkt aufrufe geht es

Wifi connecting…
Wifi connected, IP address: 192.168.0.24
Failed to connect
Received data:
Failed to connect
Received data:
Update time: SUCCESS

Kann wer helfen ?

Danke Rudolf

Wolfgang Specht

Wolfgang Specht

Hallo,
ich habe ein Problem bei der Herstellung der WiFi Verbindung.
Es kommt die Meldung Failied to connect.
Die Hardware läuft mit fehlerfrei mit anderen Prorammen.

MfG

Andreas Wolter

Andreas Wolter

Der Link zu den vollständigen Quellcodes wurde aktiviert. Wir entschuldigen uns für die Verspätung.

flai

flai

Eine sehr schöne und inspirative Umsetzung. Vielen Dank für die Bereitstellung des Codes und die ausführlichen Erläuterungen.

Wolfgang Specht

Wolfgang Specht

Hallo ,
wo finde ich den kompletten Quellcode. Der Link im Text funktioniert nicht(ist Schwarz hinterlegt).
Bitte um Info

MfG

Werner

Werner

Hallo Forum,

bitte bei “Den kompletten Quellcode finden Sie hier” Link einfügen.

Deja un comentario

Todos los comentarios son moderados antes de ser publicados

Artículos de blog

  1. Ahora instalamos el esp32 a través de la administración.
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. Transporte Aéreo - programación de ESP mediante redes locales inalámbricas