ESP32 und Arduino

ESP32 DS18B20 MQTT: mehrere Temperaturfühler an einem Bus

Schließen Sie mehrere DS18B20-Fühler an einen einzigen ESP32-GPIO an, ermitteln Sie ihre ROM-Adressen, lesen Sie sie ohne Blockieren aus und veröffentlichen Sie jeden Fühler auf einem eigenen Topic bei broker.connectmq.com.

Drei wasserdichte DS18B20-Fühler an einer gemeinsamen Leitung zu einem ESP32 in einem ESP32-DS18B20-MQTT-Aufbau zur Temperaturüberwachung
Probieren Sie es auf Ihrem eigenen MQTT-Broker ausHolen Sie sich im Free-Tarif einen privaten, verwalteten MQTT-Broker und starten Sie mit fertigen Codebeispielen.
Kostenlos testen Codebeispiele Keine Kreditkarte erforderlich

Mit einem ESP32-DS18B20-MQTT-Aufbau liest ein einziger GPIO-Pin viele wasserdichte Temperaturfühler aus und veröffentlicht jeden auf einem eigenen Topic. In diesem Tutorial verdrahten Sie mehrere DS18B20-Sensoren an einem 1-Wire-Bus, identifizieren sie über ihre ROM-Adresse, lesen sie aus, ohne den MQTT-Client zu blockieren, und veröffentlichen an broker.connectmq.com mit einem Topic pro Fühler.

Warum sich der DS18B20 für Mehrpunktmessungen eignet

Der DS18B20 ist ein digitaler Temperatursensor mit einer eindeutigen 64-Bit-ROM-Adresse, die ab Werk eingebrannt ist. Weil jeder Fühler eine eigene Adresse hat, können sich Dutzende dieselben drei Leitungen teilen: Versorgung, Masse und Daten. Das macht ihn ideal für Aufgaben wie:

  • Vor- und Rücklauftemperaturen einer Heizungsanlage.
  • Mehrere Fächer in einem Kühlschrank oder Kühlraum.
  • Aquarium-, Teich- und Lufttemperatur an einem einzigen Controller.
  • Überwachung von Hotspots in Akkupacks oder Gehäusen.

Die wasserdichten Edelstahlversionen sind günstig und robust, mit einer Genauigkeit von etwa einem halben Grad im typischen Bereich. Der Nachteil ist die Geschwindigkeit: Eine vollständige 12-Bit-Wandlung dauert bis zu 750 ms – deshalb sind nicht blockierende Lesevorgänge wichtig, sobald MQTT ins Spiel kommt.

Bauteile und Bibliotheken

  • Ein ESP32-Entwicklungsboard.
  • Zwei oder mehr DS18B20-Sensoren (TO-92 oder wasserdichter Fühler).
  • Ein 4,7-kOhm-Widerstand als Pull-up für den Bus.
  • Arduino IDE 2.x mit dem esp32-Board-Paket.
  • Bibliotheken: OneWire (von Paul Stoffregen oder der für den ESP32 gebündelte, gepflegte Fork), DallasTemperature von Miles Burton und PubSubClient.

Mehrere Fühler an einen ESP32-Pin anschließen

Alle Fühler werden parallel angeschlossen:

Fühlerader (typische Farben) Anschluss an Hinweise
Rot (VDD) ESP32 3V3 Normale Versorgung verwenden, nicht den parasitären Modus
Schwarz (GND) ESP32 GND
Gelb (DATA) ESP32 GPIO 4 Ein 4,7-kOhm-Widerstand von DATA nach 3V3 für den gesamten Bus

Verwenden Sie nur einen einzigen Pull-up-Widerstand für den Bus, platziert in der Nähe des ESP32. Die Aderfarben variieren je nach Lieferant, prüfen Sie also das Datenblatt Ihrer Fühler. Bei Leitungslängen über einige Meter verwenden Sie verdrilltes Kabel, halten einen linearen Bus statt einer Sternverkabelung ein und erwägen einen stärkeren Pull-up wie 2,2 kOhm.

Topic-Aufbau pro Fühler

Jeder Fühler veröffentlicht auf einem Topic, das seine ROM-Adresse enthält, sodass die Topics stabil bleiben, egal in welcher Reihenfolge der Bus aufgezählt wird:

Topic Retained Beispiel-Payload
connectmq/demo/dsb2q6h/ds18b20/28ff641e8316034f/temperature Ja 21.62
connectmq/demo/dsb2q6h/ds18b20/summary Nein {"28ff641e8316034f":21.62,"28aa1b2c3d4e5f60":4.12}
connectmq/demo/dsb2q6h/status Ja online / offline

Die Topics pro Fühler sind retained, damit ein später geöffnetes Dashboard sofort den letzten Wert jedes Fühlers zeigt. Das Summary-Topic ist praktisch für Konsumenten, die eine Nachricht pro Zyklus möchten. Beide bleiben innerhalb der acht Topic-Ebenen, die auf dem öffentlichen MQTT-Broker erlaubt sind.

Der ESP32-DS18B20-MQTT-Sketch

#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";   // eigene zufällige ID verwenden
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;                       // 12-Bit-Auflösung

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);   // wir warten selbst, ohne zu blockieren
  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 = Einschaltwert

    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);   // Platz für eine Zusammenfassung von bis zu 10 Fühlern
  connectMqtt();
}

void loop() {
  if (WiFi.status() != WL_CONNECTED) connectWifi();
  if (!mqtt.connected()) connectMqtt();
  mqtt.loop();                                // läuft während der Wandlungen weiter

  unsigned long now = millis();
  if (!conversionPending && now - lastRequest >= INTERVAL_MS) {
    sensors.requestTemperatures();            // startet die Wandlung auf allen Fühlern gleichzeitig
    lastRequest = now;
    conversionPending = true;
  }
  if (conversionPending && now - lastRequest >= CONVERSION_MS) {
    conversionPending = false;
    publishReadings();
  }
}

Die Fühler testen

Abonnieren Sie das gesamte Präfix:

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

Nehmen Sie einen Fühler in die Hand und beobachten Sie, wie sein Topic steigt, während die anderen konstant bleiben. So finden Sie auch am schnellsten heraus, welcher physische Fühler zu welcher ROM-Adresse gehört: Beschriften Sie dabei jedes Kabel. Denken Sie daran, dass der öffentliche MQTT-Broker für jeden sichtbar ist und sich daher für Tests und Experimente statt für echte Überwachung eignet; die Seite zum kostenlosen öffentlichen MQTT-Broker nennt seine Grenzen.

So funktioniert das nicht blockierende Auslesen

requestTemperatures() sendet einen einzigen „Convert“-Befehl gleichzeitig an alle Fühler, sodass zehn Fühler dieselben 750 ms brauchen wie einer. Mit setWaitForConversion(false) kehrt der Aufruf sofort zurück, und die Schleife ruft weiter mqtt.loop() auf, während die Fühler arbeiten. Erst nach Ablauf der Wandlungszeit liest der Sketch jeden Fühler per Adresse aus, was pro Fühler einige Millisekunden dauert.

Wenn Sie keine Schritte von 0,0625 Grad benötigen, verringern Sie die Auflösung. Bei 10 Bit dauert die Wandlung etwa 188 ms, und die Schrittweite beträgt 0,25 Grad – für Raum- oder Kühlschranküberwachung mehr als genug.

Fühlern sprechende Namen geben

ROM-Adressen sind stabil, aber nicht gut lesbar. Zwei Ansätze funktionieren gut:

  1. Zuordnung in der Firmware. Führen Sie eine kleine Tabelle von Adresse zu Name, etwa flow, return oder freezer, und verwenden Sie den Namen im Topic. Einfach, doch jeder Fühlertausch bedeutet neues Flashen.
  2. Zuordnung nachgelagert. Behalten Sie die Adresse im Topic und lassen Sie den Konsumenten, zum Beispiel einen Node-RED-Flow oder das Dashboard, Adressen in Namen übersetzen. Ein Fühlertausch bedeutet dann, eine Zuordnung zu bearbeiten, nicht die Firmware.

Der zweite Ansatz skaliert besser. Er entspricht auch der Art, wie ein Modbus-RS485-Gateway üblicherweise rohe Register-Kennungen veröffentlicht und die Bedeutung einer höheren Schicht überlässt. In industriellen Anlagen, etwa bei der Überwachung von Hydraulik- oder Kühlkreisläufen, übernimmt diese Schicht oft der Unified Namespace (UNS): Die Rohwerte werden dort unter einem Pfad entlang der ISA-95-Hierarchie neu veröffentlicht, zum Beispiel acme/werk-linz/presswerk/linie-2/hydraulik/vorlauf-temperatur.

Einen ausgefallenen oder fehlenden Fühler erkennen

Ein Fühler, der stillschweigend aufhört zu melden, ist schlimmer als einer, der einen Fehler meldet, denn ein Retained-Topic zeigt den letzten guten Wert für immer an. Der Sketch geht damit auf zwei Arten um. Erstens veröffentlicht er den String error auf dem Retained-Topic des Fühlers, wenn der Lesevorgang -127 oder 85 liefert, sodass der veraltete Wert überschrieben wird. Zweitens enthält die Summary-Nachricht für diesen Fühler null, was die meisten Konsumenten als Lücke und nicht als Null behandeln.

Sie können noch weiter gehen und die Anzahl der beim Start gefundenen Fühler veröffentlichen, zum Beispiel auf einem Retained-Topic ds18b20/count, und sie in Ihrem Dashboard mit der erwarteten Anzahl vergleichen. Wird ein Kabel durchtrennt, sinkt die Anzahl bei der nächsten Neuerkennung, und die Abweichung ist offensichtlich. Für kritische Anwendungen sollten Sie außerdem das Alter der Nachrichten überwachen: Hat sich ein Fühler-Topic seit drei Intervallen nicht geändert, behandeln Sie das Gerät als gestört, auch wenn sein Status noch online lautet.

Checkliste zur Fehlerbehebung

Symptom Ursache Lösung
0 Fühler gefunden Fehlender Pull-up oder falscher Pin 4,7 kOhm von DATA nach 3V3 ergänzen, ONE_WIRE_PIN prüfen
Messwert -127 Fühler getrennt oder gestörter Bus Verbindungen prüfen, Kabel kürzen, Pull-up-Wert verringern
Messwert 85.0 Vor Abschluss der Wandlung gelesen oder Spannungseinbruch Die 750 ms Wartezeit beibehalten, normale Versorgung nutzen
Einzelne Fühler fehlen bei langen Leitungen Sternverkabelung oder zu hohe Kapazität Linearen Bus mit verdrilltem Kabel verwenden
Summary-Nachricht fehlt Payload größer als der Puffer setBufferSize erhöhen
Fühler werden erst nach Neustart erkannt Fühler im laufenden Betrieb angesteckt discoverProbes() regelmäßig oder auf Befehl aufrufen

Einrichtung für die Produktion

Wenn die Fühler etwas Wichtiges überwachen, etwa einen Gefrierschrank, wechseln Sie zu einem authentifizierten Broker. Erstellen Sie einen unter app.connectmq.com, wechseln Sie auf WiFiClientSecure an Port 8883 mit dem Zertifikat ISRG Root X1 und verbinden Sie sich mit YOUR_CLIENT_ID, YOUR_USERNAME und YOUR_PASSWORD. Legen Sie im ConnectMQ-Portal eine Alarmregel mit Schwellwert auf dem Topic des Gefrierschrank-Fühlers an, und Sie haben einen einfachen Übertemperaturalarm, ohne Backend-Code zu schreiben. Wenn Sie neben der Temperatur auch den Stromverbrauch messen, veröffentlicht der SCT-013-Energiemonitor in einem kompatiblen Aufbau, und das ESP32-DHT22-Projekt ergänzt die Luftfeuchtigkeit an einem einzelnen Messpunkt.

Starten Sie mit ConnectMQ

Mehrpunktüberwachung braucht einen Broker, der immer verfügbar ist, wenn ein Fühler einen Schwellwert überschreitet. ConnectMQ ist ein verwalteter MQTT-Broker mit TLS, Retained Messages, einem Live-Topic-Explorer und Alarmregeln, und der kostenlose Serverless-Plan erfordert keine Kreditkarte. Richten Sie diesen Sketch auf Ihren eigenen Broker aus und finden Sie im Überblick zum ESP32-IoT-Tutorial Ihr nächstes Projekt.

Häufig gestellte Fragen

Wie viele DS18B20-Sensoren verkraftet ein ESP32-Pin?

Das Protokoll erlaubt viele Geräte pro Bus, und zehn bis zwanzig funktionieren mit guter Verdrahtung und normaler Versorgung zuverlässig. Kabellänge und Topologie setzen Ihnen weit früher Grenzen als der Adressraum.

Warum zeigt ein DS18B20 manchmal 85 Grad an?

85.0 ist der Einschalt-Resetwert des Scratchpads. Er erscheint, wenn der Lesevorgang vor Abschluss einer Wandlung erfolgt, oft nach einem Spannungseinbruch. Behandeln Sie ihn als Fehler.

Sollte jeder Fühler ein eigenes MQTT Topic haben?

Retained-Topics pro Fühler machen Dashboards einfach und halten den letzten Wert verfügbar. Eine Summary-Nachricht pro Zyklus ist eine nützliche Ergänzung für Konsumenten, die alle Werte zusammen möchten.

Kann ich parasitäre Versorgung nutzen, um eine Ader zu sparen?

Das ist möglich, aber bei langen Leitungen und vielen Fühlern weniger zuverlässig. Verwenden Sie wann immer möglich die dreiadrige normale Versorgung.

Verwandte Artikel

ESP32 NTP MQTT Zeitstempel: genaue Uhrzeit in jeder Nachricht

Synchronisieren Sie die ESP32-Uhr per NTP, formatieren Sie Zeitstempel in ISO 8601 und Epoch-Millisekunden und hängen Sie sie an MQTT-Payloads, damit Messwerte ihren echten Erfassungszeitpunkt behalten, auch wenn sie verspätet veröffentlicht werden.

8 Min. Lesezeit

Alle Artikel →

Ihr privater MQTT-Broker ist nur wenige Klicks entfernt

Konto anlegen, Broker-Zugangsdaten erhalten und das erste Gerät verbinden — ohne Server, die installiert, gepatcht oder skaliert werden müssen.