Avant de m'attaquer à des projets plus importants, dans mon cas un système de contrôle d'aquarium entièrement automatique avec quelques fonctionnalités, j'essaie d'en faire des sous-projets et de programmer l'ensemble plus tard. Cette méthode présente de nombreux avantages, car elle permet de tester et d'optimiser le code avant de s'attaquer à l'ensemble du projet. Ce projet a vu le jour parce que je voulais d'abord interroger les données relatives au lever et au coucher du soleil, ainsi qu'au fuseau horaire. Avec cette petite quantité de données, j'ai eu l'idée de créer une horloge analogique sur le module mural Az-Touch, qui sera également utilisé en partie pour le contrôle de l'aquarium. Avec quelques modifications, le modulateur mural Az-Touch est parfaitement adapté à ces tâches.
J'ai déjà utilisé certaines lignes de code dans d'autres projets et je peux exécuter une boucle d'optimisation ici. Mais pour que l'horloge ne soit pas la seule chose, l'heure quotidienne du lever et du coucher du soleil est également visualisée sur l'écran. Mais pour ne pas montrer uniquement des textes simples, il faut utiliser des images monochromes sur l'écran. La manière de procéder et de convertir les bitmaps en données lisibles pour le NodeMCU ESP32, par exemple, sera le sujet du billet d'aujourd'hui.
Le matériel et les logiciels de ce blog
Pour construire ce blog, vous avez besoin des composants du tableau 1 :
Tableau 1: Composants pour l'horloge analogique
Vous avez besoin d'un logiciel:
- Arduino IDE (https://www.arduino.cc/en/Main/Software), téléchargez la dernière version ici.
- La bibliothèque TFT_eSPI, NTPClient, ArduinoJson, WiFi, TimeLib avec toutes les dépendances
- Le programme LCD Image Converter (https://sourceforge.net/p/lcd-image-converter/activity/?page=0&limit=100#604634eaa7028b0bbaf4db72) dans la version 20190317.
En outre, vous devez avoir accès à openweathermap.org, dont la version de base gratuite est tout à fait suffisante pour ce projet.
L'image LCD programme Converter
Lors de l'élaboration des programmes, il faut toujours veiller à ce que chacun comprenne ce qui est affiché. Dans le cas des sorties de diagnostic, l'anglais ou la langue maternelle suffit, mais dans le cas des interfaces graphiques pour l'utilisateur final, GUI en abrégé, soit tout doit être traduit dans chaque langue, soit des pictogrammes clairs sont utilisés.
Pour mon horloge analogique, je ne voulais pas tout écrire, surtout à cause de l'espace limité, mais je voulais utiliser des pictogrammes pour le lever et le coucher du soleil, voir figure 1.
Figure 1 : Bitmaps pour l'horloge analogique
Le problème est que j'ai rapidement créé les images avec Paint en tant que bitmaps, se terminant par bmp, mais l'Az-Touch ou le NodeMCU ESP32 ne peuvent pas les lire. Comme il s'agit toujours de simples pictogrammes, on pourrait maintenant écrire dans le code source une fonction qui utilise des fonctions de dessin, des cercles, des lignes, etc. pour les dessiner sur l'écran, mais cela représente beaucoup trop de mathématiques et une image peut rapidement être convertie en code machine lisible.
Figure 2 : Le programme LCD Image Converter
Mon choix s'est porté sur le programme LCD Image Converter, voir figure 2, qui est à la fois un éditeur de caractères et de polices très simple, mais qui offre également la possibilité de convertir des images en code machine. Je vous montrerai cette dernière pour les images monochromes, mais elle peut également être utilisée pour les images en couleur.
Tout d'abord, l'image à convertir doit être sélectionnée via Fichier -> Ouvrir, voir Figure 3.
Figure 3 : Chargement d'un fichier image
Après avoir chargé l'image, vous avez deux changements intéressants dans l'interface. Tout d'abord, vous voyez l'image sélectionnée au milieu et la taille de l'image en bas à droite, ici 64 x 64 pixels.
Ensuite, nous ouvrons l'interface de conversion via Options -> Conversion..., voir figure 4.
Figure 4 : Interface de conversion ouverte
Pour que l'image s'affiche correctement sur l'écran, dans notre cas une image monochrome, il faut encore régler les paramètres. Tout d'abord, le profil est réglé sur Monochrome et dans l'onglet "Scanning" Top to Buttom, voir figure 5.
Figure 5 : Régler les paramètres de numérisation
Cela permet au code machine d'avoir une orientation correcte, de haut en bas. Ensuite, passez à l'onglet Prétraitement, voir figure 6.
Figure 6 : Ajustez les paramètres de prétraitement
Ici, l'option Inverse est activée, sinon l'image ne sera pas colorée ultérieurement dans la couleur choisie, mais le fond sera coloré par l'image à l'écran. Appuyez maintenant sur le bouton Show Preview et le résultat s'affiche dans la fenêtre suivante, voir figure 7.
Figure 7 : Aperçu de l'image et du code machine.
Ce qui est intéressant ici, c'est la partie droite de la nouvelle fenêtre Preview, où sont affichées les nombreuses données hexagonales. Il s'agit maintenant des données de l'image en code machine, ce qui sera affiché plus tard sur l'Az-Touch. Copiez l'ensemble du contenu et créez un nouveau fichier d'en-tête, par exemple bitmap.h.
Tout d'abord, insérez les lignes suivantes au début du fichier, voir le code 1.
Les 3 premières lignes font en sorte que le fichier d'en-tête soit stocké correctement dans le code. Les autres lignes garantissent que le fichier pgmspace.h pour les microcontrôleurs ESP ou Arduino est chargé correctement.
Pour que l'image monochrome sunrise puisse être utilisée plus tard dans le code source, la variable correspondante doit être créée, voir Code 2.
CONTAM non signé Carboniser lever du soleil[] PROGMEM = {
};
Ajoutez maintenant le contenu copié du convertisseur d'image LCD au tableau, voir le code 3, qui reflète le contenu raccourci du fichier d'en-tête nouvellement créé.
// icône Sunset 64 * 64 pixels
CONTAM non signé Carboniser lever du soleil[] 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
};
Code 3 : Code machine pour le tableau du lever du soleil, fortement raccourci.
La même procédure avec le tableau, est maintenant faite pour tous les autres graphiques. Au final, en fonction du nombre de graphiques, vous aurez un fichier d'en-tête avec de nombreuses lignes. Pour les deux graphiques de ce projet, il y a environ 150 lignes de code.
Ceci conclut les préparatifs de l'horloge analogique.
L'horloge analogique de l'AZ-Touch
Au total, ce petit projet comprend un peu moins de 500 lignes de code. Comme d'habitude, le code est disponible pour vous sur mon dépôt Github et comporte de nombreux commentaires, ce qui explique aussi les nombreuses lignes. Toutefois, certaines fonctions et sections seront expliquées plus en détail afin que vous compreniez le fonctionnement du code.
Au tout début du code source, les définitions des couleurs de l'horloge sont définies, voir code 4.
/ * --- Quelques définitions de couleur, n'hésitez pas à changer --- * /
Code 4 : Définitions pour les couleurs de l'horloge
Ici vous pouvez changer la couleur comme vous le souhaitez, faites attention aux définitions dans le fichier TFT_eSPI.h dans la bibliothèque du même nom. Cela simplifie énormément l'échange de couleurs.
Après l'inclusion des bibliothèques requises, vient l'une des parties les plus importantes du projet, le réglage des paramètres WLAN et des données API requises pour openweathermap.org, voir Code 5.
contam Char * SSID = ""; // change SSID du réseau
contam Char * le mot de passe = ""; // modifier le mot de passe du réseau
/ * - - a besoin de variables pour OpenWeatherMap.org --- * /
contam Chaîne de caractères apical = ""; // change la clé API de OpenWeathermap.org
contam Chaîne de caractères emplacement = ""; // change l'emplacement pour OpenWeatherMap.org
Code 5 : Accès WLAN et informations API openweathermap.org
À ce stade, veuillez insérer les données nécessaires pour que le NodeMCU ESP32 puisse se connecter ultérieurement à Internet et télécharger les données météorologiques depuis openweathermap.org. Ici, vous devriez déjà vous être enregistré sur openweathermap.org.
La fonction setup() active le TFT, le WLAN avec les données stockées, synchronise l'heure du NodeMCU ESP32 avec le serveur NTP et dessine les graphiques de base sur l'écran. Pour que vous puissiez voir quelle partie de la fonction setup() est en cours de traitement, il y a une sorte de sortie d'état sur l'écran, voir la Figure 8.
Figure 8 : Statut du démarrage du programme
Vous pouvez alors voir immédiatement où le programme ne progresse pas et où vous ne pouvez pas voir l'horloge analogique. Cela aide beaucoup lorsque l'Az-Touch n'est pas connecté au PC. Si tout s'est déroulé avec succès, l'horloge avec toutes les données s'affiche après 5 secondes, voir figure 9.
Figure 9 : Az-Touch avec toutes les données
Comme vous le constaterez rapidement, il ne se passe pas grand-chose dans la fonction loop() en termes de portée, voir code 6. Seules quatre fonctions requises sont appelées et les données sont envoyées au moniteur série.
/*
* =================================================================
* Fonction: boucle
* Retourne: vide
* Description: Boucle principale pour laisser travailler le programme
* =================================================================
*/
annuler boucle()
{
Titrine();
UpdateOpenWeatherMapData();
Mettre à jour();
Up usernsunset();
// sortie série
SI(pprevsecond != seconde() || Bfirtrun)
{
En série.imprimer(JoursIntheek[jour de la semaine()] + "., ");
En série.imprimer(Getdigits(heure()) );
En série.imprimer(":");
En série.imprimer(Getdigits(minute()) );
En série.imprimer(":");
En série.Imprimeur(Getdigits(seconde()) );
pprevsecond = seconde();
}
SI(Bfirtrun)
Bfirtrun = faux;
}
Code 6 : La fonction loop() du projet
Mais c'est précisément là que réside l'avantage ! La fonction loop() n'est pas surchargée et vous pouvez échanger rapidement du code. Les fonctions ont des noms uniques, ce qui vous permettra de savoir rapidement quelle fonction effectue quelle étape. Cependant, j'aimerais discuter de toutes les fonctions de la fonction loop() à ce stade.
DrawTime() fait en sorte que les aiguilles de l'horloge soient redessinées chaque fois que l'heure ou la minute change. Si vous regardez de plus près la fonction dans le code source, l'ancien pointeur est d'abord remplacé par la couleur de fond de l'affichage, puis le nouveau pointeur est dessiné. C'est ici qu'interviennent le plus les mathématiques pour les aiguilles, car celles-ci doivent être disposées selon le bon angle en fonction de l'heure. Étant donné que dans le code source nous ne dessinons pas chaque pixel individuellement, mais définissons une ligne avec un point de départ et un point d'arrivée, nous devons calculer le point d'arrivée du pointeur via les fonctions d'angle sinus et cosinus, en partant du centre de l'horloge. Une fois cette opération effectuée, le pointeur est dessiné dans l'horloge à l'aide de drawLine().
N'ayez pas peur d'examiner de plus près la fonction DrawTime() et les fonctions qu'elle appelle, même si le résultat final fonctionne.
Directement après DrawTime() suit la fonction UpdateOpenWeatherMapData(), qui, comme son nom l'indique, demande les données actuelles à openweathermap.org. Cela se fait en trois étapes essentielles :
- Préparer et envoyer la demande pour le client
- Attendez la réponse et pré-traitez les données requises, dans ce cas le format JSON.
- Préparez les données à partir du format JSON et sauvegardez les données importantes.
Cette partie du code est un peu plus complexe, car un télégramme https est préparé pour openweathermap.org, ici via la fonction RequestData(), et la réponse doit être formatée correctement. À cette fin, les données inutiles doivent être éliminées du télégramme de réponse. Ensuite, UpdateOpenWeatherMapData() convertit la chaîne JSON reçue dans la classe correcte et extrait les données relatives au fuseau horaire, au lever et au coucher du soleil. Ces nouvelles données sont comparées aux données existantes et une mise à jour de l'interface graphique ou du fuseau horaire est déclenchée en cas de changement. Comme les données dont nous avons besoin ne changent pas toutes les secondes, le travail décrit ci-dessus n'est effectué que toutes les 30 minutes.
Pour que notre horloge analogique indique toujours l'heure exacte, l'horloge interne du NodeMCU ESP32 est synchronisée avec le serveur NTP toutes les 15 minutes au moyen de la fonction UpdateNTPTime().
Enfin, il y a la fonction UpdateSunriseSunset(), qui, contrairement aux fonctions précédentes, est probablement la plus simple. Si la fonction UpdateOpenWeatherMapData() a entraîné une modification du lever et du coucher du soleil, l'ancienne heure affichée est supprimée et la nouvelle heure est saisie.
Aussi simple que cela puisse paraître en théorie, les trois premières fonctions de la fonction loop() sont assez complexes. D'une part, parce que beaucoup de calculs mathématiques sont utilisés ici, et d'autre part parce que l'obtention des données de openweathermap.org n'est pas triviale. La bonne documentation détaillée de l'API d'openweathermap.org et le fait que j'avais déjà créé une fonction RequestData() similaire pour un autre projet m'ont beaucoup aidé à obtenir les données. Cela devrait être presque universellement utilisable si vous voulez demander des données d'un autre site pour un autre projet. Comme je ne suis pas un ami des transmissions http, la fonction RequestData() utilise la variante https, plus sûre, qui peut également être utilisée pour http.
Vous pouvez trouver le code source complet ici
Préparation du projet
Avant de compiler le programme et d'être frustré qu'il échoue. Dans le répertoire du projet, vous trouverez un fichier appelé User_Setup.h. Veuillez remplacer ce fichier dans le dossier C:\User\IHR-Name\Documents\Arduino\libraries\TFT_eSPI, voir figure 10. Il est judicieux de renommer d'abord le fichier avec le même nom, par exemple User_Setup_old.h, à cet endroit.
Figure 10 : Ecraser le fichier User_Setup.h
Avec les nouveaux mods Az-Touch, il importe peu que vous utilisiez la variante 2,4" ou 2,8". Comme les deux ont la même résolution, le code source peut être utilisé directement pour les deux variantes sans autres ajustements.
Que reste-t-il à faire maintenant ? Maintenant, comme décrit ci-dessus, vous devez écraser les données pour WLAN et openweathermap.org avec vos données. En outre, vous pouvez modifier les couleurs à votre guise ou utiliser vos propres pictogrammes pour l'horloge en suivant les instructions ci-dessus. Pour ceux d'entre vous qui aiment les mathématiques, vous pouvez donner d'autres formes aux mains, il n'y a pas de limites à votre créativité. Comme il y a encore un peu de place sur l'écran, il serait même concevable d'afficher la date et le jour de la semaine dans l'horloge. Ces informations sont déjà disponibles dans le code source, il suffit de les visualiser au bon endroit dans l'affichage.
J'espère que vous vous amuserez beaucoup avec l'horloge et que l'intérêt pour des projets IoT simples ou plus complexes sera éveillé.
Vous trouverez d'autres projets pour Az-Delivery à l'adresse suivante : https://github.com/M3taKn1ght/Blog-Repo.
15 commentaires
Andreas Wolter
@Frank: der Code wurde ergänzt. Vielen Dank für den Hinweis.
Grüße,
Andreas Wolter
AZ-Delivery Blog
Frank
Seid gegrüßt,
leider ist der Fehler, den Rudolf gefunden hatte, noch immer nicht im Quellcode (auf Github) behoben worden. Da fehlt nach wie vor die entscheidende Zeile:
WiFiClientSecure client;
client.setInsecure(); <—— um diese Zeile geht es
Nach dem Einfügen funktionierte das Programm bei mir auch gleich wie es sollte und die Verbindung wurde gemacht.
Meine Anzeige habe ich um Wochentag und Datum ergänzt. Die Farben habe ich umgedreht. Der Hintergrund ist Schwarz und die Anzeigen sind hell. Das Lesen bzw. Anschauen finde ich so abends angenehmer für die Augen.
Liebe Grüße
Siegl
Hallo
Vielen Dank für die schnelle Hilfe.Ich werde es versuchen.
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
Hallo
Ich benötige noch einmal Hilfe.
Wie bekomme ich die “bitmap.h”in das Programm eingebunden ?
Danke
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
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
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
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
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
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
Der Link zu den vollständigen Quellcodes wurde aktiviert. Wir entschuldigen uns für die Verspätung.
flai
Eine sehr schöne und inspirative Umsetzung. Vielen Dank für die Bereitstellung des Codes und die ausführlichen Erläuterungen.
Wolfgang Specht
Hallo ,
wo finde ich den kompletten Quellcode. Der Link im Text funktioniert nicht(ist Schwarz hinterlegt).
Bitte um Info
MfG
Werner
Hallo Forum,
bitte bei “Den kompletten Quellcode finden Sie hier” Link einfügen.