ESP32 und Arduino

Batteriebetriebener ESP32-Sensor: Boards, Spannungsregler und MQTT-Sendeintervalle

Ein praxisnaher Design-Leitfaden für einen batteriebetriebenen ESP32-Sensor: Board-Auswahl, Regler mit niedrigem Ruhestrom, Überwachung der Batteriespannung, schnelle WLAN-Reconnects und MQTT-Sendeintervalle, die die Akkulaufzeit verlängern.

Batteriebetriebener ESP32-Sensorknoten mit LiPo-Zelle und Spannungsteiler, der MQTT-Messwerte in die Cloud sendet
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

Ein batteriebetriebener ESP32-Sensor kann monatelang mit einer einzigen Zelle laufen, aber nur, wenn Hardware und Firmware gemeinsam entworfen werden. Dieser Leitfaden führt durch Board-Auswahl, Spannungsregler, Batterieüberwachung und den Sendezyklus, damit Ihr MQTT-Knoten mit so wenig Energie wie möglich aufwacht, meldet und wieder schlafen geht.

Warum die Akkulaufzeit vor allem eine Designentscheidung ist

Der ESP32 ist kein Low-Power-Chip in dem Sinne, wie es ein Mikrocontroller ohne Funkmodul ist. Bei aktivem WLAN zieht er viel Strom, und Sendeimpulse sind die teuersten Momente seines Lebens. Im Deep Sleep sinkt der Verbrauch des Chips selbst auf Mikroampere. Der Unterschied zwischen einem Knoten, der eine Woche hält, und einem, der eine ganze Saison durchhält, liegt darin, wie viel Zeit er in jedem Zustand verbringt und wie viel die umgebende Schaltung verschwendet, während der Chip schläft.

Daraus ergeben sich drei Stellhebel: Schlafstrom (meist bestimmt durch Regler, USB-Seriell-Chip und LEDs, nicht durch den ESP32), Wachzeit (Boot, WLAN, DHCP, MQTT-Connect, Publish) und Aufwachhäufigkeit (ein halbiertes Intervall verdoppelt ungefähr die Funkenergie). Das Board ist meist der größte Hebel, also beginnen Sie dort.

Ein Board für einen batteriebetriebenen ESP32-Sensor wählen

Entwicklungsboards sind für bequemes Arbeiten am Schreibtisch gebaut. Sie enthalten typischerweise eine ständig aktive USB-UART-Bridge, eine Power-LED und einen Linearregler, der nach Preis statt nach Ruhestrom ausgewählt wurde. Jedes dieser Bauteile kann im Schlaf weit mehr ziehen als der ESP32.

Option Schlafverhalten Geeignet für
Generisches DevKit (ESP32-WROOM + AMS1117 + USB-Bridge) Schlecht: Regler und USB-Chip ziehen dauerhaft Milliampere Nur Firmware-Prototyping
Als Low-Power vermarktete Boards (LiPo-Lader, LDO mit niedrigem Iq, abschaltbares USB) Gut: für Deep Sleep ausgelegt, oft mit Akkuanschluss Kleinserien und Feldpiloten
Nacktes Modul (ESP32-WROOM / ESP32-C3 / ESP32-C6) auf eigener Platine Am besten: Sie wählen jedes Bauteil selbst Produkte und langfristige Installationen
Boards mit ESP32-C3 oder C6 Gut, ein Kern, bei vielen Workloads geringerer Aktivstrom als der klassische ESP32 Einfache Sensoren, die nur WLAN brauchen

Wenn Sie ein Board bewerten, entfernen Sie die Power-LED, prüfen Sie, ob der USB-Seriell-Chip an der 3,3-V-Schiene hängt, und schlagen Sie den Ruhestrom des Reglers nach. Messen Sie dann den Schlafstrom mit einem Multimeter in Reihe zur Batterie oder mit einem Stromprofiler; ein USB-Leistungsmesser ist dafür nicht empfindlich genug.

Spannungsregler und Batteriechemie

Der ESP32 braucht etwa 3,0–3,6 V und kann beim WLAN-Senden kurze Spitzen von mehreren hundert Milliampere ziehen. Ihr Versorgungspfad muss diese Spitzen ohne Brownout liefern und im Leerlauf fast nichts verschwenden.

Einzelne LiPo-/Li-Ionen-Zelle (3,0–4,2 V). Die häufigste Wahl. Verwenden Sie einen Low-Dropout-Regler mit einem Ruhestrom im niedrigen Mikroamperebereich und genug Reserve für Sendespitzen. Wenn sich die Zelle Richtung 3,3 V entlädt, fällt der LDO aus der Regelung. Planen Sie daher ein, dass der Knoten bei etwa 3,4–3,5 V Zellspannung nicht mehr zuverlässig meldet, und senden Sie lange vorher eine Warnung bei niedrigem Akkustand.

LiFePO4-Zelle (nominal etwa 3,2–3,3 V). Ihre Spannung liegt über den größten Teil der Entladekurve im Betriebsbereich des ESP32, weshalb manche Designs auf den Regler verzichten; prüfen Sie vorher die maximale Ladespannung gegen die absoluten Grenzwerte.

AA-Zellen. Alkaline-Zellen brechen bei Sendespitzen ein, besonders in der Kälte. Kombinieren Sie sie mit einem Buck-Boost-Wandler mit niedrigem Ruhestrom oder verwenden Sie Lithium-Primärzellen.

Setzen Sie einen Pufferkondensator (einige hundert Mikrofarad) nahe am Modul ein. Er liefert die Sendeimpulse und verhindert, dass der Brownout-Detektor den Chip zurücksetzt, eine der häufigsten Ursachen rätselhafter Neustartschleifen bei Batterieknoten.

Die Batteriespannung überwachen

Ein Sensor, der stillschweigend ausfällt, ist schlimmer als einer, der vorher warnt. Messen Sie die Zelle über einen Spannungsteiler an einem ADC-Pin und nehmen Sie den Wert in jeden MQTT-Payload auf.

Ein Teiler aus zwei gleichen hochohmigen Widerständen (zum Beispiel 2 × 1 MΩ) halbiert die Zellspannung in den ADC-Bereich und zieht dabei nur Mikroampere. Hochohmige Teiler haben eine hohe Quellimpedanz, daher sollten Sie einen kleinen Kondensator (etwa 100 nF) vom ADC-Pin gegen Masse setzen, damit der ADC eine stabile Abtastung erhält. Wenn selbst dieser Leckstrom ins Gewicht fällt, schalten Sie die untere Seite des Teilers mit einem über einen GPIO angesteuerten MOSFET.

Im ESP32-Arduino-Core 2.x und 3.x wendet analogReadMilliVolts() die Werkskalibrierung an und liefert direkt Millivolt, was weit genauer ist, als rohe analogRead()-Werte selbst zu skalieren. Mitteln Sie mehrere Messungen, weil Einzelwerte verrauscht sind. Beim klassischen ESP32 verwenden Sie einen ADC1-Pin (GPIO 32–39), da ADC2 bei aktivem WLAN nicht verfügbar ist.

Ein Firmware-Muster aus Aufwachen, Senden und Schlafen

Die folgende Firmware ist ein vollständiger Arduino-Sketch für einen Batterieknoten. Er wacht aus dem Deep Sleep auf, verbindet sich mit Kanal und BSSID aus dem RTC-Speicher wieder mit dem WLAN, veröffentlicht eine JSON-Nachricht mit der Batteriespannung, trennt sich sauber und schläft erneut. Er nutzt den kostenlosen öffentlichen MQTT-Broker broker.connectmq.com; wählen Sie also ein eindeutiges Topic-Präfix und senden Sie nichts Vertrauliches.

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

const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASS = "YOUR_WIFI_PASSWORD";
const char* MQTT_HOST = "broker.connectmq.com";
const uint16_t MQTT_PORT = 1883;
const char* TOPIC = "connectmq/demo/7f3a91/garden-node/telemetry";

const uint64_t SLEEP_SECONDS = 600;     // alle 10 Minuten senden
const int BATTERY_PIN = 34;             // ADC1-Pin, Teiler 2 x 1 MOhm
const float DIVIDER_RATIO = 2.0;

RTC_DATA_ATTR uint32_t bootCount = 0;
RTC_DATA_ATTR uint8_t savedBssid[6];
RTC_DATA_ATTR int32_t savedChannel = 0;

WiFiClient net;
PubSubClient mqtt(net);

float readBatteryVolts() {
  uint32_t sum = 0;
  for (int i = 0; i < 16; i++) sum += analogReadMilliVolts(BATTERY_PIN);
  return (sum / 16.0f) * DIVIDER_RATIO / 1000.0f;
}

bool connectWifi() {
  WiFi.mode(WIFI_STA);
  WiFi.persistent(false);
  if (savedChannel > 0) {
    WiFi.begin(WIFI_SSID, WIFI_PASS, savedChannel, savedBssid);
  } else {
    WiFi.begin(WIFI_SSID, WIFI_PASS);
  }
  unsigned long start = millis();
  while (WiFi.status() != WL_CONNECTED) {
    if (millis() - start > 10000) {
      savedChannel = 0;                 // beim nächsten Mal vollständigen Scan erzwingen
      return false;
    }
    delay(20);
  }
  savedChannel = WiFi.channel();
  memcpy(savedBssid, WiFi.BSSID(), 6);
  return true;
}

void goToSleep() {
  mqtt.disconnect();
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
  esp_sleep_enable_timer_wakeup(SLEEP_SECONDS * 1000000ULL);
  esp_deep_sleep_start();
}

void setup() {
  bootCount++;
  float battery = readBatteryVolts();   // lesen, bevor das Funkmodul die Zelle belastet

  if (!connectWifi()) goToSleep();

  String clientId = "esp32-batt-" + String((uint32_t)ESP.getEfuseMac(), HEX);
  mqtt.setServer(MQTT_HOST, MQTT_PORT);
  mqtt.setSocketTimeout(5);
  if (!mqtt.connect(clientId.c_str())) goToSleep();

  char payload[96];
  snprintf(payload, sizeof(payload),
           "{\"battery\":%.2f,\"boot\":%lu,\"rssi\":%d}",
           battery, (unsigned long)bootCount, WiFi.RSSI());
  mqtt.publish(TOPIC, payload);
  mqtt.loop();
  delay(50);                            // TCP-Stack Zeit zum Leeren geben
  goToSleep();
}

void loop() {}

Einige Details sind hier wichtig:

  • Die Batterie wird vor dem WLAN-Start gemessen. Unter Sendelast bricht die Zellspannung ein, sodass eine danach gemessene Spannung niedriger erscheint als in Wirklichkeit.
  • Jeder Fehlerpfad endet im Schlaf. Sind WLAN oder Broker nicht erreichbar, versucht der Knoten es nicht endlos weiter und leert dabei die Zelle. Er versucht es beim nächsten Aufwachen erneut.
  • Zwischengespeicherter Kanal und BSSID ermöglichen es dem Funkmodul, den vollständigen Scan zu überspringen, was jedes Aufwachen verkürzt. Ändert sich der Access Point, leert der Timeout den Cache, und der nächste Start scannt normal.
  • Eine statische IP (über WiFi.config()) spart zusätzlich den DHCP-Roundtrip. Nutzen Sie sie, wenn Sie das Netzwerk kontrollieren.

Einen tieferen Blick auf Schlafmodi, Aufweckquellen und das Speichern von Zuständen zwischen den Wachphasen bietet der Leitfaden zu ESP32 Deep Sleep MQTT.

Das Sendeintervall wählen

Das richtige Intervall hängt davon ab, wie schnell sich der Wert ändert und wie veraltet ein Messwert sein darf.

Messgröße Typisch sinnvolles Intervall Hinweise
Raum- oder Gewächshaustemperatur 5–15 Minuten Ändert sich langsam; mehrere Messungen pro Aufwachen mitteln
Bodenfeuchte 30–60 Minuten Sehr langsam; häufiger messen, aber nur bei Änderung senden
Füllstand eines Wassertanks 10–30 Minuten Bei Überschreiten eines Schwellenwerts sofort senden
Tür oder Bewegung Ereignisgesteuert Per GPIO aufwecken (ext0/ext1), nicht per Timer
Batteriespannung Bei jedem Aufwachen Kostet kaum etwas; unverzichtbar für die Wartung

Zwei Techniken strecken das Energiebudget weiter. Bündeln: Kurz ohne WLAN aufwachen, einen Messwert erfassen, ihn im RTC-Speicher ablegen und nur bei jedem N-ten Aufwachen verbinden, um den Stapel als ein JSON-Array zu veröffentlichen. Bei Änderung melden: Den neuen Wert mit dem zuletzt veröffentlichten im RTC-Speicher vergleichen und das Funkmodul komplett auslassen, wenn er sich nicht über ein Totband hinaus bewegt hat. Senden Sie aber immer mindestens einen periodischen Heartbeat, damit Sie einen ruhigen Sensor von einem toten unterscheiden können.

MQTT-Einstellungen, die Energie sparen

Die Protokollentscheidungen auf Geräteseite kosten unmittelbar Sendezeit:

  • QoS 0 für Routine-Telemetrie. QoS 1 fügt einen PUBACK-Roundtrip hinzu und hält das Funkmodul länger aktiv. Nutzen Sie es nur für Messwerte, deren Verlust Sie sich nicht leisten können; MQTT-QoS-Stufen erklärt behandelt die Abwägung.
  • Retained messages für den letzten Wert. Veröffentlichen Sie Telemetrie mit Retain-Flag, dann sieht auch ein Dashboard, das sich zwischen zwei Wachphasen verbindet, sofort den letzten Messwert.
  • Saubere, kurze Sessions. Ein schlafender Knoten braucht kein persistentes Abonnement. Verbinden Sie sich mit Clean Session, veröffentlichen Sie und trennen Sie die Verbindung.
  • Kompakte Payloads. Kurze JSON-Schlüssel genügen bei wenigen Messwerten pro Stunde.
  • TLS kostet einen Handshake. Verschlüsselte Verbindungen auf Port 8883 brauchen spürbar länger zum Aufbau als unverschlüsseltes TCP auf 1883 und halten das Funkmodul länger aktiv. In der Produktion lohnt sich dieser Kompromiss, und ESP32 MQTT über SSL/TLS zeigt, wie Sie den Handshake so günstig wie möglich halten.

Feld-Checkliste vor der Installation

  1. Den Deep-Sleep-Strom des fertigen Boards messen.
  2. Die Wachzeit pro Zyklus protokollieren und nach Ausreißern durch WLAN-Wiederholungen suchen.
  3. Sicherstellen, dass der Knoten einen Kaltstart bei der niedrigsten erwarteten Zellspannung ohne Brownout-Schleifen übersteht.
  4. Batteriespannung und einen Boot-Zähler in jeder Nachricht veröffentlichen.
  5. Im Dashboard Alarme für niedrige Batteriespannung und ausbleibende Nachrichten einrichten.
  6. Das Gehäuse abdichten, die Antenne aber von Metall und Batterien fernhalten.
  7. Vom öffentlichen MQTT-Broker zu privaten Zugangsdaten wechseln, bevor irgendetwas außerhalb Ihres Schreibtischs installiert wird.

Vom öffentlichen MQTT-Broker in die Produktion

Der kostenlose öffentliche MQTT-Broker unter broker.connectmq.com ist für Tests und Prototypen gedacht und ideal, solange Sie Intervalle abstimmen, weil Sie die eingehenden Nachrichten ohne Registrierung mit mosquitto_sub verfolgen können. Für echte Installationen wechseln Sie zu einem privaten Broker, damit niemand sonst Ihre Daten lesen kann. ConnectMQ gibt jedem Broker generierte Zugangsdaten und eine daran gebundene Client ID; nur der Connect-Aufruf ändert sich:

mqtt.setServer("broker.connectmq.com", 8883);   // mit WiFiClientSecure und der CA ISRG Root X1
mqtt.connect("YOUR_CLIENT_ID", "YOUR_USERNAME", "YOUR_PASSWORD");

Im ConnectMQ-Portal können Sie mit dem Live-Topic-Explorer und Schwellenwert-Alarmregeln die Batteriespannung der gesamten Flotte beobachten und sich benachrichtigen lassen, wenn ein Knoten unter Ihre Austauschschwelle fällt. In der Fabrikhalle, wo batteriebetriebene Nachrüstsensoren etwa Temperatur oder Vibration an Bestandsmaschinen erfassen, empfiehlt sich eine Topic-Struktur entlang der Anlagenhierarchie, zum Beispiel acme/werk-augsburg/halle-3/linie-2/motor-7/batterie, damit Wartungsteams sofort sehen, wo ein Akku zu tauschen ist. Wenn Sie viele Knoten bauen, zeigt das umfassendere ESP32-IoT-Tutorial, wie sich die Geräteseite in ein vollständiges Projekt einfügt, und der Leitfaden zum Cloud-MQTT-Broker erklärt, was Ihnen ein verwalteter MQTT-Broker abnimmt.

Starten Sie mit ConnectMQ

Bauen Sie den Prototyp Ihres Batterieknotens noch heute gegen broker.connectmq.com und erstellen Sie dann unter app.connectmq.com einen privaten Broker im kostenlosen Serverless-Tarif, ohne Kreditkarte. Es ist ein verwalteter MQTT-Broker, sodass Sie Ihre Zeit in Energiebudgets statt in Broker-Wartung investieren.

Häufig gestellte Fragen

Wie lange kann ein batteriebetriebener ESP32-Sensor mit einer LiPo-Zelle laufen?

Das hängt vom Schlafstrom des Boards, der Dauer jeder Wachphase und dem Sendeintervall ab. Ein Board mit Regler mit niedrigem Ruhestrom und ohne ständig aktiven USB-Chip, das alle paar Minuten für einen kurzen Publish aufwacht, kann monatelang laufen; ein Standard-DevKit hält mit derselben Zelle womöglich nur Tage.

Sollte ich für einen MQTT-Sensor Deep Sleep oder Light Sleep verwenden?

Verwenden Sie Deep Sleep, wenn der Knoten periodisch meldet und keine Verbindung halten muss. Light Sleep behält den RAM und kann eine WLAN-Anmeldung aufrechterhalten, sein Ruhestrom ist aber viel höher; er eignet sich daher für Knoten, die schnell auf Befehle reagieren müssen.

Warum startet mein batteriebetriebener ESP32 neu, sobald das WLAN startet?

Meist reagiert der Brownout-Detektor auf den Spannungseinbruch während der Sendeimpulse. Setzen Sie einen Pufferkondensator nahe am Modul ein, verwenden Sie einen Regler, der den Spitzenstrom liefern kann, und prüfen Sie den Innenwiderstand der Batterie, besonders bei Kälte.

Kann ich die Batteriespannung messen, ohne Strom zu verschwenden?

Ja. Verwenden Sie einen hochohmigen Teiler mit kleinem Kondensator am ADC-Pin oder schalten Sie den Teiler zwischen den Messungen per MOSFET ab, und lesen Sie ihn mit analogReadMilliVolts() an einem ADC1-Pin aus.

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.