Mon voyage dans le nuage (28) – M5Stack : ESP32 + écran + boîtier élégant
Le module de base M5Stack contient une carte ESP32, ainsi qu'un écran couleur graphique d'une résolution de 320 x 240 pixels, le tout parfaitement intégré dans un boîtier élégant. J'étais curieux de découvrir si je pouvais réaliser rapidement une petite application réseau avec ce module...
Lors de mes tout derniers voyages dans le nuage, j’ai utilisé le module contrôleur ESP32 pour développer de petites applications pour l'Internet des objets. Le processeur dispose des interfaces Wi-Fi et Bluetooth, d’une mémoire généreuse et il est en outre programmable grâce à l'environnement de développement intégré (IDE) Arduino. De plus, ces modules sont des outils de développement réellement très bon marché et faciles à associer à des cartes d’essai. Avec quelques composants supplémentaires (LED RVB, capteur photoélectrique, cavaliers) et les bibliothèques Arduino nécessaires, même un débutant peut rapidement se lancer dans un projet simple pour envoyer des valeurs lues sur un capteur vers une plate-forme connectée au nuage, et les afficher à l'écran.
Le module ESP32 de base peut recevoir un petit écran (excellente option) pour afficher des messages d'état (No Network, par exemple). La carte Lolin (abordée dans mon précédent voyage dans le nuage) possède un tel écran intégré. Il y a quelques semaines, mon collègue Mathias Claußen, cheville ouvrière de notre labo, a attiré mon attention sur le système de développement ESP32 M5Stack. Le module de base comporte une petite carte ESP32 incorporée dans un boîtier élégant et compact ; presque toute la surface avant est occupée par un écran graphique couleur d'une résolution de 320 x 240 pixels. Au-dessous de l'écran se trouvent trois boutons-poussoirs et le boîtier comporte plusieurs connecteurs et ports d'extension sur ses faces latérales. Il existe également des modules ou shields supplémentaires (GPS, par exemple), très faciles à insérer au-dessus ou au-dessous du module de base. Vous pouvez donc assembler vos propres configurations par empilement. Mon collègue Clemens Valens a présenté il y a quelque temps le système M5Stack dans l'un de ses bancs d'essai.
J'ai trouvé sur le web un tutoriel montrant comment intégrer toutes les bibliothèques nécessaires dans la configuration de mon IDE Arduino. Il contenait d'ailleurs quelques démonstrations succinctes. J'ai rapidement constaté que les développeurs avaient encapsulé les fonctions du pilote d'écran (ainsi que la scrutation du bouton-poussoir) dans un objet baptisé M5. Après avoir incorporé la bibliothèque avec
et ajouté la procédure
dans le croquis, vous pouvez appliquer (par exemple) les commandes
pour faire fonctionner l’écran.
Il existe également sur GitHub un listage dit « API Reference ». Mais je n'y ai pas trouvé tout ce que je cherchais. J'ai dû, par exemple, effectuer quelques expérimentations pour déterminer les valeurs de paramètres pour définir la taille de police (M5.Lcd.setTextSize) (N.B. : les valeurs comprises entre 2 et 5 permettent d'obtenir un résultat).
Au final, j'ai pu transposer, sur le M5Stack, un petit projet, développé à l'origine pour la carte Lolin OLED. Cette application lit les valeurs de luminosité issues d'une photorésistance et les envoie vers la plateforme OpenSenseMap dans le nuage (voir ici). Je lis la tension aux bornes de la photorésistance (circuit) reliée au connecteur d'extension situé à droite du M5Stack (voir photo).
Vous pouvez télécharger ma première application M5Stack en cliquant sur le lien en bas de page. Par ailleurs, une petite batterie est incorporée dans le produit (il en existe une autre, de plus grande capacité). Cette batterie intégrée permet de disposer d'un ensemble portable, mais le M5Stack n’aura qu'une heure d’autonomie.
Pour ce genre de situation, l'écran du M5Stack a à peu près la bonne taille pour afficher de petits messages texte. J'ai rapidement écarté l'idée d'écrire une petite appli sur PC qui communique avec le M5Stack par UDP ou TCP/IP. Il est en effet bien plus facile d'entrer le message texte et de l’adresser à l'écran - le principe marche aussi bien pour un PC que pour n'importe quel appareil mobile.
J'avais déjà programmé un serveur web ESP32 pour mon blog consacré à l'Internet des objets, avec une page web en HTML, utilisée pour indiquer le SSID et le mot de passe de votre propre réseau Wi-Fi. Pour pouvoir entrer ces informations à l’aide d'un navigateur, vous devez vous connecter à un réseau « local » créé automatiquement par l’ESP32 et indiquer l’adresse 192.168.4.1 pour accéder à ce dernier (ESP32 en mode Point d’accès). Une fois les données de connexion du réseau du routeur parvenues à l’ESP32, celui-ci peut se connecter et obtenir une autre adresse (par exemple, dans mon cas 192.168.0.38).
Pour créer cette application, je me suis basé sur l'un de mes croquis précédents. J'ai étendu la fonction de serveur web pour que, lors de l'accès à cette deuxième adresse, soit créée une page web contenant un champ de texte unique (c'est-à-dire le message adressé au DJ), avec un bouton de validation pour envoyer le texte. Le serveur web ESP32 ayant reçu le message texte du navigateur web client, le contenu apparaît à l'écran du M5Stack.
Deuxièmement, mon code était un peu lourd, avec un surnombre de fonctions spécifiques pour les deux sites web et pour l’évaluation des demandes. Il serait préférable ici d'utiliser une bibliothèque appropriée pour les deux sites - pour saisir jusqu'à huit valeurs de configuration ou seulement un petit message texte.
Troisièmement, j'ai voulu cesser de faire fonctionner l’ESP32 à la fois comme un point d'accès et en mode station. Non seulement c'était potentiellement instable, mais ce choix contribuait à accroître la consommation d'énergie.
Après avoir consacré un certain temps à apporter des changements et des modifications au code, j'ai finalement obtenu la solution que vous pouvez télécharger en bas de page.
Pour résoudre le problème du scintillement de l'écran, j'ai utilisé un petit tampon de caractères ; en réalité, il y en a jusqu'à quatre, pouvant être utilisés facultativement pour différentes positions du curseur. Dans le cas de mon application, le premier tampon n'est chargé que de l'affichage du témoin de fonctionnement (caractère alternativement commuté entre 0 et 1). Un deuxième tampon contient un texte indiquant l'état (connecté/non connecté) ; l'adresse permettant d'accéder à l’ESP32 apparaît également ici. Le troisième tampon contient le corps du message. Les fonctions nécessaires pour définir les paramètres du Tampon DisplayBuffer (position, taille de police, longueur du texte) et pour écrire le texte sont bien sûr décrites en détail dans le code source.
Pour traiter le serveur web, j'ai d'abord créé une petite classe Param - qui permet de gérer un ensemble de huit paramètres max. avec un nom, une valeur et un type. Via les lignes
je « transfère » deux objets de cette classe dans le croquis de l'application. Le premier reçoit le texte du message (Messages.PValue[0]). Le deuxième sert à gérer les paramètres (NetworkConfig.PValue[0] est le SSID, NetworkConfig.PValue[1] est le mot de passe). Ce type d'objet permet de transférer simultanément un ensemble de chaînes à d'autres bibliothèques. En outre, nous pouvons écrire des fonctions qui renvoient un objet Param (donc plusieurs chaînes en même temps).
Ma nouvelle bibliothèque webserver utilise ce principe. Les lignes
donnent accès aux fonctions du serveur web via l'objet myWebserver. La ligne
sépare le paramètre GET, qui code les valeurs saisies par l'utilisateur (dans la ligne d'adresse du navigateur après le "?") dans un formulaire web transmis. Les valeurs obtenues sont ensuite écrites dans l'objet NetworkConfig et accessibles à l’aide de NetworkConfig.PValue[x]. Inversement, vous pouvez utiliser myWebserver.SerializeToHTMLInputTable(NetworkConfig) pour obtenir un tableau HTML contenant les champs d'entrée nécessaires où l'utilisateur pourra indiquer les valeurs de NetworkConfig (SSID, mot de passe).
Le module ESP32 de base peut recevoir un petit écran (excellente option) pour afficher des messages d'état (No Network, par exemple). La carte Lolin (abordée dans mon précédent voyage dans le nuage) possède un tel écran intégré. Il y a quelques semaines, mon collègue Mathias Claußen, cheville ouvrière de notre labo, a attiré mon attention sur le système de développement ESP32 M5Stack. Le module de base comporte une petite carte ESP32 incorporée dans un boîtier élégant et compact ; presque toute la surface avant est occupée par un écran graphique couleur d'une résolution de 320 x 240 pixels. Au-dessous de l'écran se trouvent trois boutons-poussoirs et le boîtier comporte plusieurs connecteurs et ports d'extension sur ses faces latérales. Il existe également des modules ou shields supplémentaires (GPS, par exemple), très faciles à insérer au-dessus ou au-dessous du module de base. Vous pouvez donc assembler vos propres configurations par empilement. Mon collègue Clemens Valens a présenté il y a quelque temps le système M5Stack dans l'un de ses bancs d'essai.
Comment commander l'écran ?
Dans mes bancs d'essai, j'essaie toujours de créer un petit exemple d'application, même si, comme toujours, le temps manque. Ma première idée a été de construire un croquis tout simple pour écrire du texte à l'écran. Pour la connexion au réseau, il suffit de reprendre la partie correspondante de mes projets précédents - l’ESP32 est programmable à l’aide de l’IDE Arduino bien connu.J'ai trouvé sur le web un tutoriel montrant comment intégrer toutes les bibliothèques nécessaires dans la configuration de mon IDE Arduino. Il contenait d'ailleurs quelques démonstrations succinctes. J'ai rapidement constaté que les développeurs avaient encapsulé les fonctions du pilote d'écran (ainsi que la scrutation du bouton-poussoir) dans un objet baptisé M5. Après avoir incorporé la bibliothèque avec
#include <M5Stack.h>
et ajouté la procédure
M5.begin();
dans le croquis, vous pouvez appliquer (par exemple) les commandes
M5.Lcd.setCursor(x, y);
M5.Lcd.setTextSize(2);
M5.Lcd.print(“Hello World!”);
M5.Lcd.setTextSize(2);
M5.Lcd.print(“Hello World!”);
pour faire fonctionner l’écran.
Il existe également sur GitHub un listage dit « API Reference ». Mais je n'y ai pas trouvé tout ce que je cherchais. J'ai dû, par exemple, effectuer quelques expérimentations pour déterminer les valeurs de paramètres pour définir la taille de police (M5.Lcd.setTextSize) (N.B. : les valeurs comprises entre 2 et 5 permettent d'obtenir un résultat).
Au final, j'ai pu transposer, sur le M5Stack, un petit projet, développé à l'origine pour la carte Lolin OLED. Cette application lit les valeurs de luminosité issues d'une photorésistance et les envoie vers la plateforme OpenSenseMap dans le nuage (voir ici). Je lis la tension aux bornes de la photorésistance (circuit) reliée au connecteur d'extension situé à droite du M5Stack (voir photo).
Vous pouvez télécharger ma première application M5Stack en cliquant sur le lien en bas de page. Par ailleurs, une petite batterie est incorporée dans le produit (il en existe une autre, de plus grande capacité). Cette batterie intégrée permet de disposer d'un ensemble portable, mais le M5Stack n’aura qu'une heure d’autonomie.
Messages via un serveur web
Un simple portage « vite fait, bien fait » d'un projet précédent aurait pu convenir, mais il n’aurait pas permis de tirer pleinement parti de l'écran, de l'implantation soignée et de la portabilité du système M5Stack. J'ai donc réfléchi à ce que je pouvais faire. Nous avons une petite installation de DJ à la maison. De temps en temps, nos amis et connaissances utilisent les platines, et nous nous servons d'un système de caméra pour enregistrer le tout. J'ai parfois besoin de communiquer avec celui qui tient les platines et j'ai souvent pensé qu'il serait bien plus commode de pouvoir lui adresser un message plutôt que de faire des moulinets avec mes bras pour attirer son attention.Pour ce genre de situation, l'écran du M5Stack a à peu près la bonne taille pour afficher de petits messages texte. J'ai rapidement écarté l'idée d'écrire une petite appli sur PC qui communique avec le M5Stack par UDP ou TCP/IP. Il est en effet bien plus facile d'entrer le message texte et de l’adresser à l'écran - le principe marche aussi bien pour un PC que pour n'importe quel appareil mobile.
J'avais déjà programmé un serveur web ESP32 pour mon blog consacré à l'Internet des objets, avec une page web en HTML, utilisée pour indiquer le SSID et le mot de passe de votre propre réseau Wi-Fi. Pour pouvoir entrer ces informations à l’aide d'un navigateur, vous devez vous connecter à un réseau « local » créé automatiquement par l’ESP32 et indiquer l’adresse 192.168.4.1 pour accéder à ce dernier (ESP32 en mode Point d’accès). Une fois les données de connexion du réseau du routeur parvenues à l’ESP32, celui-ci peut se connecter et obtenir une autre adresse (par exemple, dans mon cas 192.168.0.38).
Pour créer cette application, je me suis basé sur l'un de mes croquis précédents. J'ai étendu la fonction de serveur web pour que, lors de l'accès à cette deuxième adresse, soit créée une page web contenant un champ de texte unique (c'est-à-dire le message adressé au DJ), avec un bouton de validation pour envoyer le texte. Le serveur web ESP32 ayant reçu le message texte du navigateur web client, le contenu apparaît à l'écran du M5Stack.
Bibliothèques WiFiWebserver et DisplayBuffer
Trois éléments m'ont donné du fil à retordre pour mon premier prototype. Tout d'abord, le message affiché à l'écran scintillait de manière notable. Au passage, il n'y a pas de commande spécifique dans l'API M5Stack pour effacer l’écran. Pour supprimer le texte affiché, vous devez l’écraser à l’aide d’une chaîne de caractères contenant des espaces, puis écrire le nouveau texte.Deuxièmement, mon code était un peu lourd, avec un surnombre de fonctions spécifiques pour les deux sites web et pour l’évaluation des demandes. Il serait préférable ici d'utiliser une bibliothèque appropriée pour les deux sites - pour saisir jusqu'à huit valeurs de configuration ou seulement un petit message texte.
Troisièmement, j'ai voulu cesser de faire fonctionner l’ESP32 à la fois comme un point d'accès et en mode station. Non seulement c'était potentiellement instable, mais ce choix contribuait à accroître la consommation d'énergie.
Après avoir consacré un certain temps à apporter des changements et des modifications au code, j'ai finalement obtenu la solution que vous pouvez télécharger en bas de page.
Pour résoudre le problème du scintillement de l'écran, j'ai utilisé un petit tampon de caractères ; en réalité, il y en a jusqu'à quatre, pouvant être utilisés facultativement pour différentes positions du curseur. Dans le cas de mon application, le premier tampon n'est chargé que de l'affichage du témoin de fonctionnement (caractère alternativement commuté entre 0 et 1). Un deuxième tampon contient un texte indiquant l'état (connecté/non connecté) ; l'adresse permettant d'accéder à l’ESP32 apparaît également ici. Le troisième tampon contient le corps du message. Les fonctions nécessaires pour définir les paramètres du Tampon DisplayBuffer (position, taille de police, longueur du texte) et pour écrire le texte sont bien sûr décrites en détail dans le code source.
Pour traiter le serveur web, j'ai d'abord créé une petite classe Param - qui permet de gérer un ensemble de huit paramètres max. avec un nom, une valeur et un type. Via les lignes
Param Messages = Param();
Param NetworkConfig = Param();
Param NetworkConfig = Param();
je « transfère » deux objets de cette classe dans le croquis de l'application. Le premier reçoit le texte du message (Messages.PValue[0]). Le deuxième sert à gérer les paramètres (NetworkConfig.PValue[0] est le SSID, NetworkConfig.PValue[1] est le mot de passe). Ce type d'objet permet de transférer simultanément un ensemble de chaînes à d'autres bibliothèques. En outre, nous pouvons écrire des fonctions qui renvoient un objet Param (donc plusieurs chaînes en même temps).
Ma nouvelle bibliothèque webserver utilise ce principe. Les lignes
#include <WiFiWebserver.h>
WiFiWebserver myWebserver = WiFiWebserver();
WiFiWebserver myWebserver = WiFiWebserver();
donnent accès aux fonctions du serveur web via l'objet myWebserver. La ligne
NetworkConfig = myWebserver.DeSerializeFromGETParameter(GETParameter, NetworkConfig);
sépare le paramètre GET, qui code les valeurs saisies par l'utilisateur (dans la ligne d'adresse du navigateur après le "?") dans un formulaire web transmis. Les valeurs obtenues sont ensuite écrites dans l'objet NetworkConfig et accessibles à l’aide de NetworkConfig.PValue[x]. Inversement, vous pouvez utiliser myWebserver.SerializeToHTMLInputTable(NetworkConfig) pour obtenir un tableau HTML contenant les champs d'entrée nécessaires où l'utilisateur pourra indiquer les valeurs de NetworkConfig (SSID, mot de passe).