Sometimes, an IoT device will perform small chunks of work, and then will otherwise be idle. For instance, a weather station with sensors for temperature, pressure, and humidity (such as the BME280) may only need to take a reading every 15 minutes and broadcast to the cloud — something that requires 10 seconds to accomplish. If the device is powered by a battery, then you want it to enter a deep sleep state in between the work cycles in order to maximize battery life.
But, how would you force an ESP8266 to go to sleep, but wake up when it needs to? The solution is to combine the low-power state of the ESP8266 with the internal Real-Time Clock (RTC) and the device’s Reset pin. While in deep sleep mode, the processor stops and the RAM is powered down (saving precious battery life), but the RTC continues to function. At a certain time, an alarm in the RTC changes the state of a GPIO pin in order to trigger a device reset, which has the effect of waking the device up (albeit, from a full reset instead of resuming from where it left off).
This may sound like a complicated orchestration, but fortunately, the SDK provides an abstraction layer over this functionality so that you only need to call a function (and NodeMCU provides a Lua wrapper around this SDK functionality).
The first thing is that you need to connect GPIO16 to the RESET pin using a small resistor (i.e., 300–1k — see Rudy’s description in the comments). GPIO16 belongs to the RTC module on the silicon, so that’s the only GPIO that the RTC can control directly while in low-power mode. The RESET pin is triggered by a low logic signal, so when the RTC’s alarm fires, it will transition GPIO16 from high to low in order to perform the reset (i.e., wake the device up).
Finally, you need code to actually put the device to sleep. Your start up scripts should go through the motions of connecting to Wi-Fi, collecting sample data (or whatever work the device is to do), and then when it comes time to sleep, execute the following:
node.dsleep(15 * 60 * 1000000)
The dsleep() function accepts microseconds as its parameter (1,000,000 microseconds = 1 second), and the multiplication performed inline here is just to make it clearer that we’re sleeping for 15 minutes total. With the current 1.5.1 SDK, the maximum value accepted is 4,294,967,295, which is about 71 minutes. Earlier SDK versions had a lower limit, closer to 35 minutes. One common way to extend this is to maintain a counter in NVM (i.e., Flash or RTC Memory), and increment the counter each time that the device wakes up. If it reaches a certain threshold, then do the work, otherwise go back to sleep.
Note: As of the time of this writing, the Master branch of the NodeMCU Firmware project in GitHub is based on SDK 1.4, while the Dev branch is based on 1.5.1. You must be aware of the underlying SDK that the firmware is based on, because that impacts the maximum deep sleep timer value that can be used.
Another use of deep sleep is to sleep until externally triggered. So, instead of using the internal RTC, your device may have an external RTC, or a button that the user must press, or some other mechanism that runs while the ESP8266 is asleep, and then triggers a device reset in much the same way (by transitioning the RESET pin from high to low).
In this case, you don’t need to connect GPIO16 to the RESET pin, and you don’t need to specify an alarm value when calling dsleep(). Or, rather, use a value of zero to specify that the ESP should sleep forever (until reset, that is):
This permits very long idle periods (hours, days, or weeks possible) so long as you have a reliable method of waking the device up by triggering the RESET pin.