ESP32 et Arduino

ESP32 DHT22 MQTT : publier température et humidité en JSON

Câblez un DHT22 à un ESP32, lisez température et humidité de façon fiable, publiez du JSON vers broker.connectmq.com et affichez les mesures en direct dans l'explorateur de topics ConnectMQ.

Capteur DHT22 câblé à un ESP32 sur une breadboard envoyant ses mesures vers le cloud dans un projet esp32 dht22 mqtt
Essayez-le sur votre propre broker MQTTObtenez un broker MQTT privé et managé avec l’offre Free et partez d’exemples de code prêts à l’emploi.
Essayer gratuitement Exemples de code Aucune carte bancaire requise

Un capteur ESP32 DHT22 MQTT est le premier projet IoT classique, et il mérite d'être bien construit. Dans ce tutoriel, vous allez câbler un DHT22, le lire sans les habituelles erreurs NaN, publier température, humidité et indice de chaleur en JSON vers broker.connectmq.com, puis suivre les mesures en direct dans l'explorateur de topics ConnectMQ.

Ce dont vous avez besoin

  • Une carte de développement ESP32 (n'importe quel ESP32 classique, S3, C3 ou C6).
  • Un DHT22 (aussi vendu sous le nom AM2302), soit le capteur nu à 4 broches, soit un module à 3 broches.
  • Une résistance de 10 kOhm si vous utilisez le capteur nu. Les modules l'intègrent généralement.
  • Des fils de connexion et une breadboard.
  • Arduino IDE 2.x avec le paquet de cartes esp32.
  • Les bibliothèques du gestionnaire de bibliothèques : DHT sensor library d'Adafruit, Adafruit Unified Sensor et PubSubClient de Nick O'Leary.

Câbler le DHT22 à l'ESP32

Broche DHT22 Numéro de broche du capteur nu Broche ESP32 Remarques
VCC 1 3V3 3,3 V fonctionne ; gardez des fils courts
DATA 2 GPIO 4 Pull-up de 10 kOhm entre DATA et 3V3
NC 3 non connectée Capteur nu uniquement
GND 4 GND

GPIO 4 est un choix sûr sur un ESP32 classique car elle ne joue aucun rôle au démarrage. Évitez les GPIO 0, 2, 12 et 15 pour les capteurs : leur état au reset influe sur le démarrage. Sur le C3 et le C6, choisissez n'importe quelle GPIO libre qui n'est pas une broche de strapping et modifiez la constante DHT_PIN.

Éloignez le capteur de quelques centimètres de l'ESP32. Le régulateur et la radio de la carte chauffent en fonctionnement, et un DHT22 collé directement sur la carte affichera un ou deux degrés de trop.

Le comportement du DHT22

Le DHT22 utilise un protocole à un fil avec un timing strict. Deux caractéristiques déterminent le code :

  1. Il ne peut être lu que toutes les 2 secondes. Une lecture plus rapide renvoie des valeurs en cache ou des erreurs. Pour de la télémétrie MQTT, une mesure toutes les 10 à 60 secondes suffit largement.
  2. Les lectures échouent occasionnellement. Une interruption Wi-Fi au mauvais moment corrompt le timing des bits, et la bibliothèque renvoie NaN. Un code de production doit le détecter et réessayer plutôt que publier des données invalides.

La précision est d'environ un demi-degré Celsius et de quelques pourcents d'humidité relative. Si vous avez besoin d'une meilleure précision en humidité ou d'une mesure de pression, le tutoriel ESP32 BME280 utilise un capteur I2C moins sensible au timing.

Conception des topics et du payload

Utilisez un préfixe unique pour que vos données n'entrent pas en collision avec celles des autres utilisateurs du serveur MQTT public gratuit :

Topic Retained Payload
connectmq/demo/dht7w3p/telemetry Non {"temperature":22.4,"humidity":48.1,"heatIndex":22.1,"rssi":-61}
connectmq/demo/dht7w3p/status Oui online ou offline (last will)

Un objet JSON par mesure garde ensemble les valeurs liées : un consommateur ne voit ainsi jamais une température associée à une humidité mesurée à un autre moment.

Le sketch ESP32 DHT22 MQTT complet

#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>

// ---------- paramètres ----------
const char* WIFI_SSID     = "YOUR_WIFI_SSID";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";
const char* MQTT_HOST     = "broker.connectmq.com";
const uint16_t MQTT_PORT  = 1883;
const char* PREFIX        = "connectmq/demo/dht7w3p";   // remplacez par votre propre identifiant aléatoire
const uint8_t DHT_PIN     = 4;
const uint32_t INTERVAL_MS = 15000;

DHT dht(DHT_PIN, DHT22);
WiFiClient   net;
PubSubClient mqtt(net);
String clientId, topicTelemetry, topicStatus;
unsigned long lastRead = 0;

void connectWifi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Wi-Fi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(400);
    Serial.print(".");
  }
  Serial.printf(" connected, IP %s\n", WiFi.localIP().toString().c_str());
}

void connectMqtt() {
  while (!mqtt.connected()) {
    Serial.print("MQTT... ");
    if (mqtt.connect(clientId.c_str(), topicStatus.c_str(), 1, true, "offline")) {
      Serial.println("connected");
      mqtt.publish(topicStatus.c_str(), "online", true);
    } else {
      Serial.printf("failed (state %d), retry in 5 s\n", mqtt.state());
      delay(5000);
    }
  }
}

bool readDht(float& t, float& h) {
  for (int attempt = 0; attempt < 3; attempt++) {
    h = dht.readHumidity();
    t = dht.readTemperature();          // Celsius
    if (!isnan(h) && !isnan(t)) return true;
    delay(2100);                        // le DHT22 exige 2 s entre deux lectures
  }
  return false;
}

void setup() {
  Serial.begin(115200);
  dht.begin();

  clientId       = "esp32-dht22-" + String((uint32_t)ESP.getEfuseMac(), HEX);
  topicTelemetry = String(PREFIX) + "/telemetry";
  topicStatus    = String(PREFIX) + "/status";

  connectWifi();
  mqtt.setServer(MQTT_HOST, MQTT_PORT);
  mqtt.setBufferSize(512);
  connectMqtt();
}

void loop() {
  if (WiFi.status() != WL_CONNECTED) connectWifi();
  if (!mqtt.connected()) connectMqtt();
  mqtt.loop();

  if (millis() - lastRead < INTERVAL_MS) return;
  lastRead = millis();

  float t, h;
  if (!readDht(t, h)) {
    Serial.println("DHT22 read failed three times, skipping this cycle");
    mqtt.publish(topicStatus.c_str(), "sensor-error", true);
    return;
  }

  float heatIndex = dht.computeHeatIndex(t, h, false);   // false = Celsius
  char payload[160];
  snprintf(payload, sizeof(payload),
           "{\"temperature\":%.1f,\"humidity\":%.1f,\"heatIndex\":%.1f,\"rssi\":%d}",
           t, h, heatIndex, WiFi.RSSI());

  if (mqtt.publish(topicTelemetry.c_str(), payload)) {
    Serial.println(payload);
  } else {
    Serial.println("publish failed");
  }
}

Une remarque sur le topic de statut : après une erreur de capteur, le sketch publie sensor-error comme statut retained, et la connexion réussie suivante le remplace par online. Si vous préférez un topic de santé distinct, ajoutez-en un ; l'essentiel est qu'un capteur défaillant soit visible au lieu de rester silencieux.

Choisir un intervalle et économiser l'énergie

L'intervalle de 15 secondes du sketch convient à une démo sur un bureau. Pour de vraies pièces, réfléchissez à l'usage des données. Le suivi du confort nécessite rarement plus d'une mesure par minute, tandis qu'une alarme de serre ou de local serveur peut en vouloir une toutes les 30 secondes. Publier moins souvent réduit le trafic sur le broker et rend les données plus faciles à représenter.

Si le nœud fonctionne sur batterie, garder le Wi-Fi connecté en permanence est le plus gros poste de consommation. Une meilleure structure consiste à : sortir du deep sleep, alimenter le capteur, attendre deux secondes, lire, se connecter au Wi-Fi et au broker, publier, se déconnecter proprement, puis appeler esp_deep_sleep_start() avec un réveil par timer. Dans ce mode, le last will est moins utile, car chaque mise en veille ressemble à une déconnexion : publiez plutôt une valeur retained lastSeen et laissez le tableau de bord signaler les capteurs qui ne se sont pas manifestés depuis quelques intervalles. Alimentez le DHT22 depuis une broche GPIO si vous voulez le couper complètement pendant la veille, et n'oubliez pas d'attendre les deux secondes complètes après la mise sous tension avant la première lecture.

Tester en ligne de commande

Abonnez-vous avec le client Mosquitto, en utilisant un client ID unique quelconque :

mosquitto_sub -h broker.connectmq.com -p 1883 -i dht-viewer-7w3p -t "connectmq/demo/dht7w3p/#" -v

Soufflez sur le capteur et l'humidité grimpe en une ou deux mesures. N'oubliez pas que la zone publique est partagée et lisible par tous : elle convient pour une démo sur un bureau, mais pas pour des données que vous voulez garder privées. Le guide du serveur MQTT public gratuit en liste les limites.

Visualiser les données ESP32 DHT22 MQTT dans l'explorateur de topics

La ligne de commande est rapide, mais une vue graphique est plus agréable quand vous faites tourner plusieurs capteurs. Créez un compte gratuit sur app.connectmq.com, choisissez l'offre gratuite Serverless, créez un broker et copiez le nom d'utilisateur, le mot de passe et le client ID générés. Modifiez ensuite le sketch pour vous connecter avec identifiants en TLS :

#include <WiFiClientSecure.h>

WiFiClientSecure net;              // remplace WiFiClient
PubSubClient mqtt(net);

// ISRG Root X1 (Let's Encrypt) au format PEM, copié depuis letsencrypt.org
static const char ROOT_CA[] = R"PEM(
-----BEGIN CERTIFICATE-----
...paste ISRG Root X1 here...
-----END CERTIFICATE-----
)PEM";

// dans setup(), avant connectMqtt() :
net.setCACert(ROOT_CA);
mqtt.setServer("broker.connectmq.com", 8883);

// dans connectMqtt() :
mqtt.connect("YOUR_CLIENT_ID", "YOUR_USERNAME", "YOUR_PASSWORD",
             topicStatus.c_str(), 1, true, "offline");

Ouvrez votre broker dans le portail ConnectMQ et allez dans l'explorateur de topics en direct. Votre topic de télémétrie apparaît dans l'arborescence, et chaque nouvelle mesure se met à jour sur place. Depuis le même portail, vous pouvez ajouter une règle d'alerte à seuil, par exemple une humidité supérieure à 70 %, et consulter les alertes déclenchées dans le journal des alertes. Pour des graphiques à long terme, faites tourner Node-RED, Telegraf ou un petit abonné Python qui se connecte au broker en tant que client MQTT et écrit dans la base de données de votre choix. Dans une maison connectée, Home Assistant peut aussi s'abonner à ce topic via un capteur MQTT, et Jeedom et Domoticz savent aussi communiquer en MQTT.

Dépannage

  1. Chaque lecture renvoie NaN. Vérifiez la résistance de pull-up et que DATA est bien reliée à la broche définie dans DHT_PIN. L'absence de pull-up est la cause la plus fréquente avec les capteurs nus.
  2. NaN occasionnels. Normal sous charge Wi-Fi. La boucle de nouvelle tentative s'en charge ; ne réduisez pas l'écart de 2 secondes.
  3. Température figée ou lente à évoluer. Le DHT22 réagit lentement et met plusieurs dizaines de secondes à se stabiliser. Cela vient du capteur, pas de MQTT.
  4. Mesures supérieures de quelques degrés. Échauffement dû à la carte. Éloignez le capteur avec un câble court.
  5. Les câbles longs provoquent des erreurs. Le protocole à un fil est sensible. Gardez le câble court ou diminuez légèrement la valeur du pull-up.
  6. État MQTT -2. La connexion TCP a échoué ; vérifiez le Wi-Fi et que le port 1883 sortant est autorisé.

Pour formater des payloads plus volumineux en toute sécurité, consultez ArduinoJson pour les payloads MQTT de l'ESP32. Si vous avez besoin de plusieurs points de température sans humidité, le projet multi-capteurs DS18B20 est plus adapté.

Démarrer avec ConnectMQ

Un nœud DHT22 devient utile lorsque ses données arrivent dans un endroit fiable. ConnectMQ, un broker MQTT managé, vous offre un broker MQTT cloud avec TLS sur le port 8883, MQTT 3.1.1 et 5.0, un explorateur de topics en direct et des règles d'alerte, ainsi qu'une offre gratuite Serverless sans carte bancaire. Flashez la version TLS de ce sketch avec vos identifiants, puis poursuivez avec le tutoriel IoT ESP32 pour d'autres projets de capteurs et d'appareils.

Questions fréquentes

À quelle fréquence un ESP32 doit-il publier les mesures du DHT22 via MQTT ?

Toutes les 10 à 60 secondes, c'est la norme pour le suivi d'une pièce. Le DHT22 ne peut pas être lu plus souvent que toutes les 2 secondes, et sa réponse lente rend une publication plus rapide inutile.

Puis-je utiliser un DHT11 à la place d'un DHT22 ?

Oui. Remplacez DHT22 par DHT11 dans le constructeur. Le DHT11 offre une précision et une plage moindres : le DHT22 ou un BME280 sont préférables pour tout ce qui dépasse la démo.

Faut-il publier température et humidité sur des topics séparés ?

Les deux approches fonctionnent. Un objet JSON unique garde ensemble les valeurs d'un même instant, tandis que des topics séparés sont pratiques pour les outils qui attendent une seule valeur par topic.

Pourquoi utiliser un topic de statut retained avec un last will ?

Le broker publie le message retained offline si l'ESP32 disparaît sans se déconnecter : n'importe quel tableau de bord peut ainsi distinguer un capteur hors service d'un capteur simplement silencieux.

Articles liés

Exemple MQTT ESP-IDF : construire un client esp-mqtt à partir de zéro

Construisez un projet ESP-IDF à partir d'un dossier vide avec le composant esp-mqtt : configuration du Wi-Fi en mode station, gestionnaire d'événements MQTT, publication et abonnement, propriétés MQTT 5 et TLS avec le bundle de certificats.

9 min de lecture

Horodatage NTP ESP32 MQTT : ajouter une heure précise à chaque message

Synchronisez l'horloge de l'ESP32 avec NTP, formatez des horodatages ISO 8601 et epoch en millisecondes, et joignez-les aux payloads MQTT pour que les mesures conservent leur véritable heure de capture même lorsqu'elles sont publiées en retard.

8 min de lecture

Tous les articles →

Votre broker MQTT privé, à quelques clics

Créez un compte, récupérez les identifiants de votre broker et connectez votre premier appareil — aucun serveur à installer, mettre à jour ou dimensionner.