Objectifs
- Construire un tableau de bord autonome : l'M5Stack Core s'abonne à un courtier MQTT et affiche température, humidité et batterie en temps réel sur son écran 320×240.
- Utiliser PubSubClient avec le Wi-Fi 2,4 GHz, reconnexion automatique et callback de réception.
- Publier soi-même l'état de la batterie (IP5306) et le RSSI sur des topics d'état.
- Structurer l'affichage en zones (jauge, valeurs, pastille de connexion) redessinées uniquement à la réception.
Matériel
- 1 M5Stack Core + Wi-Fi 2,4 GHz.
- 1 courtier MQTT accessible (ex. Mosquitto sur un Raspberry Pi du réseau, port 1883).
- Bibliothèques : M5Unified, PubSubClient (gestionnaire Arduino).
- Un second émetteur pour tester (autre ESP32, ou la commande mosquitto_pub).
Code complet
#include <M5Unified.h>
#include <WiFi.h>
#include <PubSubClient.h>
const char* SSID = "VOTRE_WIFI";
const char* PASS = "VOTRE_MDP";
const char* BROKER = "192.168.1.50"; // Mosquitto sur le réseau
WiFiClient esp;
PubSubClient mqtt(esp);
float temperature = 0; float humidite = 0;
bool connecte = false;
void callback(char* topic, byte* payload, unsigned int n) {
char buf[64]; unsigned int l = (n < 63) ? n : 63;
memcpy(buf, payload, l); buf[l] = 0;
if (!strcmp(topic, "salon/temperature")) temperature = atof(buf);
if (!strcmp(topic, "salon/humidite")) humidite = atof(buf);
}
void setup {
Serial.begin(115200);
auto cfg = M5.config;
M5.begin(cfg);
WiFi.begin(SSID, PASS);
while (WiFi.status != WL_CONNECTED) { delay(300); Serial.print("."); }
mqtt.setServer(BROKER, 1883);
mqtt.setCallback(callback);
M5.Display.setTextSize(2);
}
void publierEtat {
char b[16];
snprintf(b, sizeof(b), "%d", M5.Power.getBatteryLevel);
mqtt.publish("m5core/batterie", (const uint8_t*)b, strlen(b));
}
void dessiner {
M5.Display.fillScreen(TFT_BLACK);
M5.Display.fillCircle(305, 15, 8, connecte ? TFT_GREEN : TFT_RED);
M5.Display.setTextColor(TFT_CYAN);
M5.Display.setCursor(10, 10); M5.Display.printf("T : %5.1f C", temperature);
M5.Display.setCursor(10, 45); M5.Display.printf("H : %5.1f %%", humidite);
M5.Display.setTextColor(TFT_WHITE);
M5.Display.setCursor(10, 80); M5.Display.printf("Bat : %d %%", M5.Power.getBatteryLevel);
M5.Display.drawRect(10, 110, 300, 22, TFT_WHITE);
M5.Display.fillRect(12, 112, 296 * constrain(temperature, 0, 40) / 40, 18, TFT_ORANGE);
}
uint32_t tPrec = 0;
void loop {
if (!mqtt.connected) {
connecte = mqtt.connect("m5core-dashboard");
if (connecte) mqtt.subscribe("salon/#");
}
mqtt.loop;
if (millis - tPrec > 2000) { tPrec = millis; publierEtat; dessiner; }
vTaskDelay(10 / portTICK_PERIOD_MS);
}
Vérification attendue
- La pastille en haut à droite passe au vert quand le client est connecté au courtier (le vérifier avec mosquitto_sub -t '$SYS/broker/clients/connected').
- mosquitto_pub -t salon/temperature -m 23.5 met à jour la valeur et la jauge orange sur l'écran en moins d'une seconde.
- Le topic m5core/batterie reçoit le niveau de batterie toutes les 2 s.
Erreurs fréquentes
- Courtier injoignable : vérifier IP, port 1883 ouvert, et que le courtier écoute sur le réseau (pas seulement localhost).
- mqtt.loop jamais appelé hors setup : les messages n'arrivent jamais et la connexion est déclarée perdue par le courtier (keepalive).
- Topics mal orthographiés ou Qos/encodage : publier en ASCII simple pour tester avant de complexifier.
- Se déconnecter du Wi-Fi sans reconnexion : garder le test !mqtt.connected dans loop avec reconnexion, sinon l'écran fige l'ancienne valeur.
- Surcharger l'affichage à chaque message : redessiner au plus une fois par seconde (timer) pour garder la réactivité des boutons.
- Oublier que l'ADC2 est mort avec le Wi-Fi actif : brancher les capteurs analogiques sur l'ADC1 (G32-39).