Zum Inhalt springen
Arduino Tutorials Fortgeschrittene · 1 Std. · 16. Juli 2026

ESP32 Deep Sleep: So sparst du Strom in deinen Projekten

ESP32 Deep Sleep Hero Image

Der ESP32 ist ein leistungsfähiger Mikrocontroller mit WLAN und Bluetooth an Bord – und mit dieser Leistung kommt ein ordentlicher Hunger nach Strom. Genau deshalb ist der ESP32 Deep Sleep so interessant: Er schaltet fast den ganzen Chip ab und senkt den Verbrauch von rund 100 Milliampere auf wenige Mikroampere. Für jedes batteriebetriebene Projekt ist das der Unterschied zwischen zwei Tagen und einem halben Jahr Laufzeit.

So kann dein ESP32 zum Beispiel alle 20 Minuten aufwachen, einen Sensorwert übermitteln und sich dann wieder schlafen legen. In diesem Tutorial erfährst du, wie du dabei vorgehst – und wie du deinen ESP32 nicht nur per Timer weckst, sondern auch per Taster oder Berührung.

Falls du mit dem ESP8266 arbeitest: Der Deep Sleep funktioniert dort ähnlich, aber im Detail deutlich umständlicher. Dazu haben wir ein eigenes Tutorial zum Deep Sleep beim ESP8266.

Wie der Deep Sleep funktioniert

Im Deep Sleep bleibt vom Chip fast nichts übrig. Beide Prozessorkerne aus, WLAN aus, Bluetooth aus, Arbeitsspeicher aus. Übrig bleibt eine kleine Insel namens RTC-Teil, die mit ein paar Mikroampere vor sich hin tickt. Läuft ihre Uhr ab, drückt sie dem Rest des Chips gewissermaßen den Reset-Knopf: Der ESP32 bootet von vorne, inklusive Bootloader-Meldungen im seriellen Monitor.

Für deinen Code hat das zwei Konsequenzen, über die praktisch jeder einmal stolpert:

  • loop() ist tot. Nach jedem Aufwachen beginnt dein Sketch wieder bei setup() – und da er dort auch wieder einschläft, kommt er in loop() nie an. Dein gesamtes Programm lebt also in setup(). Das fühlt sich beim ersten Mal falsch an, ist aber genau richtig.
  • Deine Variablen sind Amnesiepatienten. Ein Zähler, den du mühsam hochzählst, steht nach dem Aufwachen wieder auf seinem Startwert. Dagegen gibt es beim ESP32 ein hübsch simples Gegenmittel – dazu unten mehr.

Und jetzt die gute Nachricht: Beim ESP32 musst du dafür nichts verkabeln. Wer vom ESP8266 kommt, kennt die Brücke zwischen D0 und RST – der ESP32 löst den Neustart intern aus. Du brauchst also nur dein Board und ein USB-Kabel.

Diese Bauteile brauchst du

  • ESP32-Entwicklungsboard Für den Einstieg z. B. ESP32 DevKit V1 oder Lolin32; für sehr niedrigen Deep-Sleep-Verbrauch optional Lolin32 Lite oder FireBeetle.
  • USB-Kabel zum Programmieren Passender Stecker zum verwendeten ESP32-Board (häufig Micro-USB).
  • Taster Nur für die später erwähnten Weck-Beispiele per Taster erforderlich.
  • Widerstand Für die Taster-Schaltung; genauer Widerstandswert im vorliegenden Ausschnitt nicht genannt.

Affiliate-Links: Kaufst du über diese Links, erhält Pollux Labs eine kleine Provision – für dich ohne Mehrkosten.

Für die späteren Beispiele kommen noch ein Taster und ein Widerstand dazu – für den ersten Test brauchst du nichts davon.

Der erste Sketch

Genug Theorie – der folgende Sketch bringt deinen ESP32 zum Schlafen. Kopiere ihn in einen neuen Sketch und lade ihn hoch.

// Umrechnungsfaktor: 1 Sekunde = 1.000.000 Mikrosekunden
#define uS_ZU_S 1000000ULL

// So lange soll der ESP32 schlafen (in Sekunden)
#define SCHLAFDAUER 10

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

  // Ausgabe einer Nachricht, wenn der ESP32 aufwacht
  Serial.println("Der ESP32 ist aufgewacht!");

  // Hier würde im echten Projekt deine Arbeit passieren:
  // Sensor auslesen, Daten senden ...
  delay(2000);

  // Den Timer als Weckruf einrichten
  esp_sleep_enable_timer_wakeup(SCHLAFDAUER * uS_ZU_S);

  Serial.println("Der ESP32 geht in den Deep-Sleep-Modus...");

  // Warte, bis die Nachricht wirklich gesendet wurde
  Serial.flush();

  // Ab in den Schlaf – nach dieser Zeile passiert nichts mehr
  esp_deep_sleep_start();
}

void loop() {
  // Bleibt leer: Nach dem Deep Sleep startet der ESP32 neu
  // und beginnt wieder bei setup(). Hier kommt er nie an.
}

Der Ablauf ist beim ESP32 zweistufig: Mit esp_sleep_enable_timer_wakeup() legst du fest, wodurch er aufwachen soll, mit esp_deep_sleep_start() schickst du ihn dann schlafen. Das wirkt zunächst umständlicher als der Einzeiler beim ESP8266 – zahlt sich aber gleich aus, denn dadurch kannst du auch mehrere Weckrufe gleichzeitig aktivieren.

Stelle den seriellen Monitor auf 115200 Baud – dann siehst du deinem ESP32 beim Ein- und Ausschlafen zu. Rechne dabei einmal mit: Zwischen zwei „Aufgewacht“-Meldungen liegen nicht 10, sondern rund 12 Sekunden. Die 2 Sekunden Arbeitszeit kommen oben drauf, denn SCHLAFDAUER beschreibt nur den Schlaf selbst, nicht den Abstand zwischen zwei Weckrufen. Bei einem Zehn-Sekunden-Test fällt das kaum auf. Wenn dein Projekt aber jede volle Stunde messen soll und der WLAN-Aufbau mal 5, mal 15 Sekunden dauert, verschiebt sich dein Zeitplan mit jedem Zyklus ein Stück weiter. Im Praxisbeispiel weiter unten rechnen wir die Wachzeit deshalb heraus.

Wie viel Strom sparst du wirklich?

Jetzt wird es unangenehm. Denn zwischen der Zahl im Datenblatt und dem, was dein Multimeter an einem DevKit anzeigt, liegen ungefähr drei Größenordnungen.

Der nackte ESP32-Chip zieht im Deep Sleep etwa 10 Mikroampere. Aktiv mit eingeschaltetem WLAN sind es grob 100 bis 160 Milliampere, bei Sendespitzen auch mal 240 mA. Ein Verhältnis von rund 1:10.000 – klingt fantastisch.

Auf einem gewöhnlichen DevKit wirst du diese 10 µA aber nie messen. Der Grund: Auf dem Board sitzt nicht nur der Chip. Da sind auch ein USB-Seriell-Wandler (CP2102 oder CH340), ein Spannungsregler und meistens noch eine Power-LED. Diese Bauteile wissen nichts vom Deep Sleep und ziehen munter weiter Strom. Besonders der oft verbaute AMS1117-Regler ist ein Kostgänger: Er allein verbraucht im Leerlauf mehrere Milliampere. In der Praxis landest du auf einem ESP32 DevKit V1 deshalb eher bei 5 bis 10 Milliampere – also beim Tausendfachen dessen, was der Chip allein bräuchte.

Was das konkret bedeutet: Eine 2.000-mAh-Batterie hält ein schlafendes DevKit vielleicht zwei Wochen durch. Derselbe Chip auf einem sparsamen Board läuft damit über ein Jahr.

Die Konsequenz für deine Projekte:

  • Zum Lernen und Entwickeln kannst du bei deinem DevKit bleiben. Jeder Sketch aus diesem Tutorial läuft dort korrekt – nur die Stromrechnung sieht eben anders aus als im Datenblatt.
  • Für ein echtes Batterieprojekt lohnt sich ein Board, das für Akkubetrieb gebaut wurde – etwa ein Lolin32 Lite oder ein FireBeetle. Diese Boards sind mit sparsameren Reglern bestückt und kommen im Deep Sleep in die Nähe der Datenblattwerte. Alternativ entfernst du auf deinem DevKit die Power-LED und ersetzt den Regler.

Bevor du nun anfängst, das Schlafintervall zu verlängern: Der größere Hebel liegt fast immer bei der Wachzeit. Rechne es einmal durch. Ein ESP32, der stündlich für 8 Sekunden mit 120 mA funkt, verbraucht dafür rund 6,4 mAh am Tag. Bekommst du die Wachphase auf 3 Sekunden herunter, sind es noch 2,4 mAh – über 60 Prozent gespart, ohne dass dein Projekt seltener misst. Den größten Brocken frisst dabei der WLAN-Verbindungsaufbau, der je nach Router zwischen 3 und 10 Sekunden schwankt. Wer richtig optimieren will, hinterlegt IP-Adresse und Gateway fest im Sketch, statt sie per DHCP zu erfragen.

Wie lange kann der ESP32 schlafen?

Hier macht der ESP32 kurzen Prozess: Praktisch so lange du willst. Während der ESP8266 nach gut einer Stunde am Ende ist und du dir mit mehrfachem Schlafen behelfen musst, rechnet der ESP32 in 64-Bit-Mikrosekunden. Selbst wenn du ihn ein Jahr am Stück schlafen legst, ist das für den Timer kein Problem.

Wichtig ist nur, dass du bei langen Zeiten richtig rechnest:

// Falsch: Das Ergebnis passt nicht in eine normale Zahl (32 Bit)
// und läuft über – der ESP32 wacht viel zu früh auf
esp_sleep_enable_timer_wakeup(6 * 60 * 60 * 1000000);

// Richtig: Das ULL sorgt dafür, dass mit 64 Bit gerechnet wird
esp_sleep_enable_timer_wakeup(6ULL * 60 * 60 * 1000000ULL);

Das ist ein Fehler, der still passiert: Der Code kompiliert anstandslos, dein ESP32 wacht nur einfach nicht nach sechs Stunden auf, sondern nach ein paar Minuten. Deshalb im Sketch oben das ULL hinter dem Umrechnungsfaktor.

Eine Warnung zur Genauigkeit: Die interne Uhr des ESP32 ist im Deep Sleep nicht besonders präzise und schwankt zusätzlich mit der Temperatur. Über einen Tag hinweg können sich daraus einige Minuten Abweichung ergeben. Für „alle 20 Minuten ein Messwert“ ist das völlig egal – für „jeden Tag exakt um 8:00 Uhr“ brauchst du eine echte Uhrzeit aus dem Internet oder ein RTC-Modul.

Ein Gedächtnis für deinen ESP32: RTC_DATA_ATTR

Kommen wir zurück auf die Amnesie von oben. Die kleine RTC-Insel, die deinen ESP32 im Schlaf bewacht, hat nämlich auch etwas Platz zum Ablegen: rund 8 Kilobyte, die überleben, solange die Stromversorgung steht.

Diesen Platz zu nutzen kostet dich genau ein Wort. Stelle RTC_DATA_ATTR vor eine globale Variable – fertig:

#define uS_ZU_S 1000000ULL
#define SCHLAFDAUER 10

// Diese Variable überlebt den Deep Sleep
RTC_DATA_ATTR uint32_t zyklen = 0;

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

  zyklen++;
  Serial.print("Aufwachen Nr. ");
  Serial.println(zyklen);

  esp_sleep_enable_timer_wakeup(SCHLAFDAUER * uS_ZU_S);
  Serial.flush();
  esp_deep_sleep_start();
}

void loop() {}

Das war alles. Kein Lesen, kein Schreiben, keine Prüfsumme – die Variable verhält sich wie eine ganz normale globale Variable, sie vergisst nur nichts. Beim ersten Start nach dem Anschließen der Stromversorgung wird sie automatisch auf ihren Startwert gesetzt, danach zählt sie über jeden Schlaf hinweg weiter.

Ausgabe im Seriellen Monitor beim ESP32 Deep Sleep

Ein kleines Experiment zeigt dir, wo die Grenze verläuft: Drücke den Reset-Knopf – der Zähler läuft weiter. Ziehe kurz das USB-Kabel – er fängt bei eins an. Der RTC-Speicher hängt eben am Strom, nicht am Prozessor.

Der praktische Nutzen: Du kannst messen und senden entkoppeln. Lass deinen ESP32 jede Minute aufwachen und den Sensorwert im RTC-Speicher sammeln – aber erst bei jedem zehnten Mal das WLAN einschalten und alle zehn Werte auf einmal verschicken. Deine Messreihe bleibt minutengenau, der teure Verbindungsaufbau passiert nur noch einmal pro Viertelstunde. In vielen Projekten ist das der Unterschied zwischen Wochen und Monaten Laufzeit.

Alles zusammen: die Sensor-Station

Zeit, das Versprechen aus der Einleitung einzulösen. Dieser Sketch macht deinen ESP32 zu einer Messstation, die sich alle 20 Minuten kurz meldet: aufwachen, Sensor lesen, ins WLAN, Wert abschicken, weiterschlafen.

Achte beim Lesen auf die Funktion schlafen() – dort steckt die eigentliche Erfahrung drin. Sie ist erstens die Notbremse für den Fall, dass dein Router streikt: Ohne sie würde der ESP32 in der while-Schleife hängen bleiben und mit vollen 120 mA auf eine Verbindung warten, die nie kommt – eine Batterie ist so über Nacht leer. Nach 15 Sekunden brechen wir stattdessen ab und versuchen es in 20 Minuten erneut. Zweitens zieht sie die Wachzeit vom Schlafintervall ab, damit die Messungen nicht mit jedem Zyklus weiter verrutschen.

#include <WiFi.h>
#include <HTTPClient.h>

const char* ssid = "DEIN_WLAN_NAME";
const char* password = "DEIN_WLAN_PASSWORT";
const char* serverUrl = "http://example.com/daten";

// Das gewünschte Intervall in Sekunden (20 Minuten)
const uint32_t INTERVALL = 20 * 60;

// Nach so vielen Millisekunden geben wir den Verbindungsversuch auf
const uint32_t WLAN_TIMEOUT = 15000;

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.println("Aufgewacht.");

  // 1. Sensor auslesen
  // Hier liest du deinen echten Sensor aus – zum Testen
  // nehmen wir einen analogen Eingang des ESP32
  int sensorwert = analogRead(34);
  Serial.print("Sensorwert: ");
  Serial.println(sensorwert);

  // 2. Mit dem WLAN verbinden
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  uint32_t startZeit = millis();
  while (WiFi.status() != WL_CONNECTED) {
    delay(100);
    Serial.print(".");

    // Die Notbremse: Nach 15 Sekunden ohne Erfolg schlafen wir weiter
    if (millis() - startZeit > WLAN_TIMEOUT) {
      Serial.println();
      Serial.println("Keine WLAN-Verbindung – neuer Versuch beim naechsten Mal.");
      schlafen();
    }
  }

  Serial.println();
  Serial.print("Verbunden. IP: ");
  Serial.println(WiFi.localIP());

  // 3. Den Wert senden
  HTTPClient http;
  http.begin(serverUrl);
  http.addHeader("Content-Type", "application/json");

  String daten = "{\"wert\":" + String(sensorwert) + "}";
  int statusCode = http.POST(daten);

  Serial.print("Antwort des Servers: ");
  Serial.println(statusCode);

  http.end();

  // 4. Wieder schlafen legen
  schlafen();
}

void schlafen() {
  // Das WLAN sauber abschalten, bevor es in den Schlaf geht
  WiFi.disconnect(true);

  // Die Zeit abziehen, die wir wach waren – so bleibt das
  // Intervall tatsächlich bei 20 Minuten
  uint32_t wachSekunden = millis() / 1000;
  uint32_t schlafSekunden = INTERVALL;

  if (wachSekunden < INTERVALL) {
    schlafSekunden = INTERVALL - wachSekunden;
  }

  Serial.print("Schlafe fuer ");
  Serial.print(schlafSekunden);
  Serial.println(" Sekunden.");
  Serial.flush();

  // Sekunden in Mikrosekunden umrechnen (64 Bit!)
  esp_sleep_enable_timer_wakeup((uint64_t)schlafSekunden * 1000000ULL);
  esp_deep_sleep_start();
}

void loop() {
  // Bleibt leer – siehe oben
}

Ein Rat: Stelle INTERVALL für den ersten Testlauf auf 30. Sonst debuggst du im 20-Minuten-Takt, und das ist ungefähr so unterhaltsam, wie es klingt.

Aufwecken ohne Timer

Hier spielt der ESP32 seinen größten Vorteil aus. Nicht jedes Projekt braucht ein festes Intervall – ein Briefkastenmelder soll sich nicht alle 20 Minuten melden, sondern genau dann, wenn die Klappe aufgeht. Der ESP32 kann auf mehrere Arten geweckt werden, und du kannst sie sogar kombinieren.

Per Taster: ext0

Die einfachste Variante weckt deinen ESP32 über einen einzelnen Pin:

#include <driver/rtc_io.h>

#define WECK_PIN GPIO_NUM_33

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.println("Aufgewacht!");

  // Den Pin auch im Schlaf auf HIGH halten,
  // damit ein Tastendruck ihn sauber auf LOW ziehen kann
  rtc_gpio_pullup_en(WECK_PIN);
  rtc_gpio_pulldown_dis(WECK_PIN);

  // Wecke auf, sobald der Pin auf LOW geht (also 0)
  esp_sleep_enable_ext0_wakeup(WECK_PIN, 0);

  Serial.println("Gute Nacht – weck mich mit dem Taster.");
  Serial.flush();
  esp_deep_sleep_start();
}

void loop() {}

Verbinde dafür einen Taster zwischen GPIO 33 und GND. Dein ESP32 schläft nun endlos und wacht erst bei einem Tastendruck auf. Zwischen zwei Ereignissen verbraucht dein Projekt praktisch nichts.

Wichtig: Nicht jeder Pin eignet sich. Es funktionieren nur die sogenannten RTC-GPIOs, denn nur die sind im Schlaf noch wach. Beim klassischen ESP32 sind das die Pins 0, 2, 4, 12–15, 25–27 und 32–39. Ein Taster an GPIO 21 wird deinen ESP32 nie wecken.

Per mehreren Tastern: ext1

Sollen mehrere Pins wecken können, nimmst du ext1. Statt einer Pin-Nummer übergibst du hier eine Bitmaske:

// Wecke auf, wenn GPIO 32 ODER GPIO 33 auf HIGH geht
#define WECK_PINS ((1ULL << 32) | (1ULL << 33))

esp_sleep_enable_ext1_wakeup(WECK_PINS, ESP_EXT1_WAKEUP_ANY_HIGH);

Per Berührung

Der klassische ESP32 hat kapazitive Touch-Pins – ein Stück Draht oder Alufolie an einem Touch-Pin genügt, und dein Projekt wacht auf, wenn du es berührst:

void aufgewachtDurchTouch() {
  // Diese Funktion wird beim Aufwachen aufgerufen –
  // sie darf leer bleiben
}

// Im setup(), vor dem Schlafenlegen:
touchAttachInterrupt(T3, aufgewachtDurchTouch, 40);  // T3 = GPIO 15
esp_sleep_enable_touchpad_wakeup();

Die 40 ist der Schwellwert – je niedriger, desto stärker musst du berühren. Diesen Wert wirst du für deinen Aufbau experimentell finden müssen.

Warum bin ich eigentlich aufgewacht?

Wenn du Timer und Taster kombinierst, willst du beim Aufwachen natürlich wissen, was von beidem dich geweckt hat. Auch dafür gibt es eine Funktion:

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

  switch (esp_sleep_get_wakeup_cause()) {
    case ESP_SLEEP_WAKEUP_TIMER:
      Serial.println("Der Timer war es – Routinemessung.");
      break;
    case ESP_SLEEP_WAKEUP_EXT0:
      Serial.println("Der Taster wurde gedrueckt!");
      break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD:
      Serial.println("Jemand hat mich beruehrt.");
      break;
    default:
      // Kein Weckruf: Das war ein Kaltstart oder der Reset-Knopf
      Serial.println("Kaltstart.");
      break;
  }

  // ... hier geht es weiter
}

Damit baust du Projekte, die beides können: sich einmal pro Stunde routinemäßig melden – und sofort Alarm schlagen, wenn etwas passiert.

Wenn es nicht funktioniert

Die häufigsten Stolpersteine:

  • Der ESP32 wacht viel zu früh auf: Deine Rechnung ist übergelaufen. Setze ULL hinter den Umrechnungsfaktor, siehe oben.
  • Der Taster weckt ihn nicht: Du nutzt vermutlich keinen RTC-GPIO. Wechsle auf einen Pin aus der Liste oben.
  • Im seriellen Monitor steht nur Zeichensalat: Stelle die Baudrate auf 115200.
  • Der Verbrauch sinkt kaum: Das liegt fast immer am Board, nicht an deinem Code – siehe den Abschnitt zum Stromverbrauch.

Ein Hinweis noch, falls du kein klassisches ESP32-Board benutzt: Die neueren Varianten ESP32-C3, -S2 und -S3 beherrschen den Timer-Weckruf und den RTC-Speicher genauso. Beim Aufwecken über Pins unterscheiden sie sich aber – der ESP32-C3 kennt zum Beispiel weder ext0 noch Touch-Pins und nutzt stattdessen esp_deep_sleep_enable_gpio_wakeup(). Die ersten Sketches dieses Tutorials laufen überall, für die Taster-Beispiele lohnt ein Blick ins Datenblatt deines Boards.

Fazit

Der Einstieg in den Deep Sleep des ESP32 ist erfreulich einfach. Interessant wird er dort, wo du ihn mit den Weckrufen kombinierst: ein Projekt, das stündlich Bericht erstattet und trotzdem sofort reagiert, wenn jemand den Taster drückt, ist mit dem ESP32 keine Bastelei, sondern vorgesehen.

Drei Dinge nimmst du aus diesem Tutorial mit: Nach jedem Aufwachen beginnt alles von vorn bei setup(). Was den Schlaf überleben soll, braucht ein RTC_DATA_ATTR. Und wenn deine Batterie trotzdem zu schnell leer ist, liegt es seltener an deinem Code als an deinem Board und an einer zu langen Wachphase.

Mehr Projekte für Arduino, ESP32, Raspi & Co
Werde Mitglied bei Pollux Labs und finde dein nächstes Projekt. Zum Beispiel:
Über 100 Maker sind bereits Mitglied bei Pollux Labs
  • ESP32 Internetradio
  • Arduino Wetterstation
  • ESP8266 & Raspi Webserver
  • Automatische Bewässerung
  • ... und viele mehr!