Fix: ESP8266 deep sleep never wakes up (ESP.deepSleep)
ESP.deepSleep() needs GPIO16 (D0) wired to RST to wake. Add the wire (or close the D1 mini SLEEP jumper), and remove it while uploading if uploads fail.
Community draft — report a mistake
What you see
Going to sleep for 60 seconds...
(nothing — the board stays asleep until RESET is pressed)
--- after wiring D0 to RST, at 74880 baud ---
ets Jan 8 2013,rst cause:5, boot mode:(3,6)
...
Reset reason : 5 = Deep-Sleep WakeGoing to sleep for 60 seconds... (nothing — the board stays asleep until RESET is pressed) --- after wiring D0 to RST, at 74880 baud --- ets Jan 8 2013,rst cause:5, boot mode:(3,6) ... Reset reason : 5 = Deep-Sleep Wake
ESP.deepSleep() switches off almost everything except a small timer. On the ESP8266 that timer can’t restart the CPU directly. It drives GPIO16 low, and only a wire from GPIO16 (D0) to the RST pin turns that into a reset that wakes the chip.
Without the wire the board sleeps until you press RESET. Add the D0-to-RST link and it wakes on schedule, with rst cause:5 in the boot log.
Quick fix — try in order
- 1
Connect D0 (GPIO16) to RST
During deep sleep only the RTC runs. When the timer expires it pulses GPIO16 low; that pulse must reach the RST pin to restart the chip. NodeMCU: a jumper wire D0 → RST. D1 mini: the same wire, or bridge the “SLEEP” solder jumper on boards that have one.
- 2
Remove the wire while uploading if needed
On some boards the D0–RST link interferes with auto-reset and uploads fail. Unplug it, upload, plug it back. A 470 Ω–1 kΩ resistor instead of a plain wire also helps.
- 3
Stay under the maximum sleep time
The timer overflows after roughly 3.5 hours. Use
ESP.deepSleep(ESP.deepSleepMax());as the longest; for longer periods wake, count and sleep again. - 4
Check the wake reason with the diagnostic sketch
After a timed wake it reports “Deep-Sleep Wake”. If it says “External System” the wake came from a button on RST instead.
- 5
ESP-01: no GPIO16 on the header
GPIO16 isn't brought out on the ESP-01. It needs a fine wire soldered to the chip's pin 8 — or use a D1 mini instead.
Diagnostic sketch
// FlashReady diagnostic: why did my ESP8266 reset?
// Prints the SDK reset reason (with the exception details after a crash), the real flash
// chip size versus the size chosen in Tools -> Flash Size, then a heartbeat every 5 s.
// Open Serial Monitor at 115200. The ROM's own boot line ("rst cause:..") is printed at 74880
// baud and shows up as a few garbage characters first - that is normal.
#include <user_interface.h>
void setup() {
Serial.begin(115200);
delay(200);
Serial.println();
Serial.println("=== FlashReady ESP8266 reset report ===");
rst_info *info = ESP.getResetInfoPtr();
// SDK numbering: 0 power-on, 1 hardware WDT, 2 exception, 3 soft WDT, 4 soft restart,
// 5 deep-sleep wake, 6 external reset (RST pin). Not the same numbers as the ROM's "rst cause".
Serial.printf("Reset reason : %u = %s\n", info->reason, ESP.getResetReason().c_str());
Serial.printf("Reset info : %s\n", ESP.getResetInfo().c_str());
if (info->reason == REASON_EXCEPTION_RST) {
Serial.printf("Exception : (%u) at epc1=0x%08x - paste the stack into the Exception Decoder\n",
info->exccause, info->epc1);
}
uint32_t real = ESP.getFlashChipRealSize();
uint32_t ide = ESP.getFlashChipSize();
Serial.printf("Flash (chip) : %u KB (id 0x%06x)\n", real / 1024, ESP.getFlashChipId());
Serial.printf("Flash (IDE) : %u KB\n", ide / 1024);
if (real != ide) {
Serial.println("WARNING : Tools -> Flash Size does not match the chip. Fix it and re-upload.");
}
Serial.printf("Core / SDK : %s / %s\n", ESP.getCoreVersion().c_str(), ESP.getSdkVersion());
Serial.printf("Free heap : %u bytes\n", ESP.getFreeHeap());
Serial.println("=======================================");
}
void loop() {
static uint32_t last = 0;
if (millis() - last >= 5000) {
last = millis();
Serial.printf("alive, uptime %lu s\n", millis() / 1000);
}
}// FlashReady diagnostic: why did my ESP8266 reset?
// Prints the SDK reset reason (with the exception details after a crash), the real flash
// chip size versus the size chosen in Tools -> Flash Size, then a heartbeat every 5 s.
// Open Serial Monitor at 115200. The ROM's own boot line ("rst cause:..") is printed at 74880
// baud and shows up as a few garbage characters first - that is normal.
#include <user_interface.h>
void setup() {
Serial.begin(115200);
delay(200);
Serial.println();
Serial.println("=== FlashReady ESP8266 reset report ===");
rst_info *info = ESP.getResetInfoPtr();
// SDK numbering: 0 power-on, 1 hardware WDT, 2 exception, 3 soft WDT, 4 soft restart,
// 5 deep-sleep wake, 6 external reset (RST pin). Not the same numbers as the ROM's "rst cause".
Serial.printf("Reset reason : %u = %s\n", info->reason, ESP.getResetReason().c_str());
Serial.printf("Reset info : %s\n", ESP.getResetInfo().c_str());
if (info->reason == REASON_EXCEPTION_RST) {
Serial.printf("Exception : (%u) at epc1=0x%08x - paste the stack into the Exception Decoder\n",
info->exccause, info->epc1);
}
uint32_t real = ESP.getFlashChipRealSize();
uint32_t ide = ESP.getFlashChipSize();
Serial.printf("Flash (chip) : %u KB (id 0x%06x)\n", real / 1024, ESP.getFlashChipId());
Serial.printf("Flash (IDE) : %u KB\n", ide / 1024);
if (real != ide) {
Serial.println("WARNING : Tools -> Flash Size does not match the chip. Fix it and re-upload.");
}
Serial.printf("Core / SDK : %s / %s\n", ESP.getCoreVersion().c_str(), ESP.getSdkVersion());
Serial.printf("Free heap : %u bytes\n", ESP.getFreeHeap());
Serial.println("=======================================");
}
void loop() {
static uint32_t last = 0;
if (millis() - last >= 5000) {
last = millis();
Serial.printf("alive, uptime %lu s\n", millis() / 1000);
}
}Why it happens
Why doesn't the ESP8266 wake by itself?
Unlike the ESP32, the ESP8266 has no internal wake path from deep sleep. The RTC timer can only drive GPIO16, and only a reset restarts the CPU — hence the external D0-to-RST link.
It wakes but the battery still drains fast
NodeMCU boards keep the CH340 and AMS1117 regulator powered, drawing several mA. For battery projects use a bare ESP-12 or a D1 mini with a low-quiescent regulator.
Never put D0 on a button
With D0 wired to RST, using D0 as an input or output resets the board. Leave it for deep sleep only.
Board-specific notes
Wemos D1 mini: See the D1 mini page for where D0 and RST are on the header.
Did this fix it?
Thanks — that helps us keep this page right.