ESP32 et Arduino

ESP32 DS18B20 MQTT : plusieurs sondes de température sur un seul bus

Câblez plusieurs sondes DS18B20 sur une seule GPIO d'ESP32, identifiez leurs adresses ROM, lisez-les sans bloquer et publiez chaque sonde sur son propre topic sur broker.connectmq.com.

Trois sondes DS18B20 étanches partageant un seul fil vers un ESP32 dans un montage de suivi de température esp32 ds18b20 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 montage ESP32 DS18B20 MQTT permet à une seule broche GPIO de lire de nombreuses sondes de température étanches et de publier chacune sur son propre topic. Dans ce tutoriel, vous allez câbler plusieurs capteurs DS18B20 sur un même bus 1-Wire, les identifier par leur adresse ROM, les lire sans bloquer le client MQTT et publier vers broker.connectmq.com avec un topic par sonde.

Pourquoi le DS18B20 convient bien à la surveillance multipoint

Le DS18B20 est un capteur de température numérique doté d'une adresse ROM unique de 64 bits gravée en usine. Comme chaque sonde a sa propre adresse, des dizaines peuvent partager les mêmes trois fils : alimentation, masse et données. Il est donc idéal pour des usages comme :

  • Les températures de départ et de retour d'un système de chauffage.
  • Plusieurs étagères d'un réfrigérateur ou d'une chambre froide.
  • Les mesures d'un aquarium, d'un bassin et de l'air ambiant depuis un seul contrôleur.
  • La surveillance des points chauds d'un pack de batteries ou d'un boîtier.

Les versions étanches en inox sont bon marché et robustes, avec une précision d'environ un demi-degré sur la plage habituelle. La contrepartie est la vitesse : une conversion complète sur 12 bits prend jusqu'à 750 ms, d'où l'importance des lectures non bloquantes dès que MQTT entre en jeu.

Composants et bibliothèques

  • Une carte de développement ESP32.
  • Au moins deux capteurs DS18B20 (boîtier TO-92 ou sonde étanche).
  • Une résistance de 4,7 kOhm pour le pull-up du bus.
  • Arduino IDE 2.x avec le paquet de cartes esp32.
  • Bibliothèques : OneWire (de Paul Stoffregen, ou le fork maintenu fourni pour l'ESP32), DallasTemperature de Miles Burton et PubSubClient.

Câbler plusieurs sondes sur une broche d'ESP32

Toutes les sondes se branchent en parallèle :

Fil de la sonde (couleurs usuelles) Se connecte à Remarques
Rouge (VDD) 3V3 de l'ESP32 Utilisez l'alimentation normale, pas le mode parasite
Noir (GND) GND de l'ESP32
Jaune (DATA) GPIO 4 de l'ESP32 Une seule résistance de 4,7 kOhm entre DATA et 3V3 pour tout le bus

N'utilisez qu'une seule résistance de pull-up pour le bus, placée près de l'ESP32. Les couleurs de fils varient selon les fournisseurs : vérifiez la fiche technique de vos sondes. Pour des longueurs de plus de quelques mètres, utilisez du câble à paire torsadée, conservez une topologie de bus linéaire plutôt qu'en étoile et envisagez un pull-up plus fort, par exemple 2,2 kOhm.

Organisation des topics par sonde

Chaque sonde publie sur un topic contenant son adresse ROM, de sorte que les topics restent stables quel que soit l'ordre d'énumération du bus :

Topic Retained Exemple de payload
connectmq/demo/dsb2q6h/ds18b20/28ff641e8316034f/temperature Oui 21.62
connectmq/demo/dsb2q6h/ds18b20/summary Non {"28ff641e8316034f":21.62,"28aa1b2c3d4e5f60":4.12}
connectmq/demo/dsb2q6h/status Oui online / offline

Les topics par sonde sont retained : un tableau de bord ouvert plus tard affiche immédiatement la dernière valeur de chaque sonde. Le topic de synthèse est pratique pour les consommateurs qui veulent un seul message par cycle. Les deux restent dans la limite de huit niveaux de topic autorisée sur la zone publique.

Le sketch ESP32 DS18B20 MQTT

#include <WiFi.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>

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/dsb2q6h";   // utilisez votre propre identifiant aléatoire
const uint8_t ONE_WIRE_PIN = 4;
const uint8_t MAX_PROBES   = 10;
const uint32_t INTERVAL_MS = 10000;
const uint32_t CONVERSION_MS = 750;                       // résolution 12 bits

OneWire oneWire(ONE_WIRE_PIN);
DallasTemperature sensors(&oneWire);
WiFiClient   net;
PubSubClient mqtt(net);

DeviceAddress probes[MAX_PROBES];
char probeIds[MAX_PROBES][17];
uint8_t probeCount = 0;
String clientId, topicStatus;

unsigned long lastRequest = 0;
bool conversionPending = false;

void addressToHex(const DeviceAddress addr, char* out) {
  for (uint8_t i = 0; i < 8; i++) sprintf(out + i * 2, "%02x", addr[i]);
  out[16] = '\0';
}

void discoverProbes() {
  sensors.begin();
  probeCount = 0;
  uint8_t found = sensors.getDeviceCount();
  for (uint8_t i = 0; i < found && probeCount < MAX_PROBES; i++) {
    if (sensors.getAddress(probes[probeCount], i)) {
      sensors.setResolution(probes[probeCount], 12);
      addressToHex(probes[probeCount], probeIds[probeCount]);
      Serial.printf("Probe %u: %s\n", probeCount, probeIds[probeCount]);
      probeCount++;
    }
  }
  sensors.setWaitForConversion(false);   // nous attendons nous-mêmes, sans bloquer
  Serial.printf("%u probe(s) found\n", probeCount);
}

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

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

void publishReadings() {
  String summary = "{";
  for (uint8_t i = 0; i < probeCount; i++) {
    float c = sensors.getTempC(probes[i]);
    bool valid = (c != DEVICE_DISCONNECTED_C) && (c != 85.0f);   // 85.0 = valeur à la mise sous tension

    String topic = String(PREFIX) + "/ds18b20/" + probeIds[i] + "/temperature";
    char value[16];
    if (valid) snprintf(value, sizeof(value), "%.2f", c);
    else       snprintf(value, sizeof(value), "error");
    mqtt.publish(topic.c_str(), value, true);

    if (i) summary += ",";
    summary += "\"" + String(probeIds[i]) + "\":" + (valid ? String(value) : String("null"));
  }
  summary += "}";
  String topic = String(PREFIX) + "/ds18b20/summary";
  mqtt.publish(topic.c_str(), summary.c_str());
  Serial.println(summary);
}

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

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

  connectWifi();
  mqtt.setServer(MQTT_HOST, MQTT_PORT);
  mqtt.setBufferSize(1024);   // de quoi contenir une synthèse de 10 sondes maximum
  connectMqtt();
}

void loop() {
  if (WiFi.status() != WL_CONNECTED) connectWifi();
  if (!mqtt.connected()) connectMqtt();
  mqtt.loop();                                // continue de tourner pendant les conversions

  unsigned long now = millis();
  if (!conversionPending && now - lastRequest >= INTERVAL_MS) {
    sensors.requestTemperatures();            // lance la conversion sur toutes les sondes à la fois
    lastRequest = now;
    conversionPending = true;
  }
  if (conversionPending && now - lastRequest >= CONVERSION_MS) {
    conversionPending = false;
    publishReadings();
  }
}

Tester les sondes

Abonnez-vous à l'ensemble du préfixe :

mosquitto_sub -h broker.connectmq.com -p 1883 -i ds-view-2q6h -t "connectmq/demo/dsb2q6h/#" -v

Tenez une sonde dans la main et regardez son topic grimper pendant que les autres restent stables. C'est aussi le moyen le plus rapide de savoir quelle sonde physique correspond à quelle adresse ROM : étiquetez chaque câble au fur et à mesure. N'oubliez pas que la zone de test publique est visible de tous : elle convient aux expériences plutôt qu'à une vraie surveillance. Consultez la page du serveur MQTT public gratuit pour connaître ses limites.

Comment fonctionne la lecture non bloquante

requestTemperatures() envoie une seule commande « convert » à toutes les sondes simultanément : dix sondes prennent donc les mêmes 750 ms qu'une seule. Avec setWaitForConversion(false), l'appel rend la main immédiatement et la boucle continue d'appeler mqtt.loop() pendant que les sondes travaillent. Ce n'est qu'une fois le temps de conversion écoulé que le sketch lit chaque sonde par son adresse, ce qui prend quelques millisecondes par sonde.

Si vous n'avez pas besoin de pas de 0,0625 degré, réduisez la résolution. À 10 bits, la conversion prend environ 188 ms et le pas devient 0,25 degré, ce qui suffit largement pour surveiller une pièce ou un réfrigérateur.

Donner des noms parlants aux sondes

Les adresses ROM sont stables mais peu lisibles. Deux approches fonctionnent bien :

  1. Correspondance dans le firmware. Gardez une petite table adresse vers nom, comme flow, return ou freezer, et utilisez le nom dans le topic. C'est simple, mais chaque remplacement de sonde impose un reflashage.
  2. Correspondance en aval. Gardez l'adresse dans le topic et laissez le consommateur, par exemple un flow Node-RED ou le tableau de bord, traduire les adresses en noms. Remplacer une sonde revient alors à modifier une correspondance, pas le firmware.

La seconde approche passe mieux à l'échelle. Elle correspond aussi à la façon dont une passerelle Modbus RS485 publie généralement les identités brutes des registres et laisse une couche supérieure leur donner un sens.

Détecter une sonde défaillante ou absente

Une sonde qui cesse silencieusement de remonter des données est pire qu'une sonde qui signale une erreur, car un topic retained continue d'afficher indéfiniment la dernière bonne valeur. Le sketch gère ce cas de deux façons. D'abord, il publie la chaîne error sur le topic retained de la sonde lorsque la lecture renvoie -127 ou 85, ce qui écrase la valeur périmée. Ensuite, le message de synthèse contient null pour cette sonde, ce que la plupart des consommateurs traitent comme un trou plutôt que comme un zéro.

Vous pouvez aller plus loin en publiant le nombre de sondes détectées au démarrage, par exemple sur un topic retained ds18b20/count, et en le comparant au nombre attendu dans votre tableau de bord. Si un câble est coupé, le nombre baisse à la redécouverte suivante et l'écart saute aux yeux. Pour les usages critiques, surveillez aussi l'âge des messages : si le topic d'une sonde n'a pas changé depuis trois intervalles, considérez l'appareil comme défaillant même si son statut indique toujours online.

Liste de vérification pour le dépannage

Symptôme Cause Correctif
0 sonde détectée Pull-up manquant ou mauvaise broche Ajouter 4,7 kOhm entre DATA et 3V3, vérifier ONE_WIRE_PIN
Mesure à -127 Sonde déconnectée ou bus bruité Vérifier les soudures, raccourcir le câble, diminuer la valeur du pull-up
Mesure à 85,0 Lecture avant la fin de la conversion, ou micro-coupure d'alimentation Conserver l'attente de 750 ms, utiliser l'alimentation normale
Sondes manquantes sur les longues distances Câblage en étoile ou capacité trop élevée Utiliser un bus linéaire en paire torsadée
Message de synthèse absent Payload plus grand que le buffer Augmenter setBufferSize
Sondes détectées seulement après redémarrage Sonde branchée à chaud Appeler discoverProbes() périodiquement ou sur commande

Configuration de production

Lorsque les sondes surveillent quelque chose d'important, comme un congélateur, passez à un broker authentifié. Créez-en un sur app.connectmq.com, passez à WiFiClientSecure sur le port 8883 avec le certificat ISRG Root X1 et connectez-vous avec YOUR_CLIENT_ID, YOUR_USERNAME et YOUR_PASSWORD. Dans le portail ConnectMQ, ajoutez une règle d'alerte à seuil sur le topic de la sonde du congélateur, et vous disposez d'une alarme de surchauffe de base sans écrire de code backend. Si vous mesurez la consommation électrique en plus de la température, le moniteur d'énergie SCT-013 publie selon une organisation compatible, et le projet ESP32 DHT22 ajoute l'humidité en un point.

Démarrer avec ConnectMQ

La surveillance multisonde exige un broker toujours disponible quand une sonde franchit un seuil. ConnectMQ est un broker MQTT managé avec TLS, retained messages, un explorateur de topics en direct et des règles d'alerte, et l'offre gratuite Serverless ne demande pas de carte bancaire. Pointez ce sketch vers votre propre broker et parcourez le hub tutoriel IoT ESP32 pour le projet suivant.

Questions fréquentes

Combien de capteurs DS18B20 une broche d'ESP32 peut-elle gérer ?

Le protocole autorise de nombreux périphériques par bus, et dix à vingt fonctionnent de manière fiable avec un bon câblage et une alimentation normale. La longueur de câble et la topologie vous limiteront bien avant l'espace d'adressage.

Pourquoi un DS18B20 indique-t-il parfois 85 degrés ?

85,0 est la valeur de réinitialisation du scratchpad à la mise sous tension. Elle apparaît lorsque la lecture a lieu avant la fin d'une conversion, souvent après une micro-coupure d'alimentation. Traitez-la comme une erreur.

Chaque sonde doit-elle avoir son propre topic MQTT ?

Des topics retained par sonde simplifient les tableaux de bord et gardent la dernière valeur disponible. Un message de synthèse par cycle est un complément utile pour les consommateurs qui veulent toutes les valeurs ensemble.

Puis-je utiliser l'alimentation parasite pour économiser un fil ?

C'est possible, mais moins fiable sur les longues distances et avec de nombreuses sondes. Utilisez l'alimentation normale à trois fils chaque fois que possible.

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.