ESP8266, Deep Sleep mode test, wake up with a PIR motion detector

Table of Contents

The ESP8266 module has the deep sleep mode which allows to put it in hibernation to save the battery. You can wake up the module at regular intervals to make measurements and publish them on a server. The RESET pin (RST) is also used to wake the ESP8266. For example, the rising edge (the signal) of a motion detector (PIR) can be used. In this tutorial we will see the adaptations to the Arduino code and how to modify the wiring.


Different sleep modes and power consumption of an ESP8266EX module

There are three ways to sleep. They are detailed in the official documentation page 6

  • Modem Sleep Modem-Sleep mode is used in applications that require processor operation, as in PWM or I2S applications. It complies with 802.11 (U-APSD). The Wi-Fi modem is stopped while maintaining a Wi-Fi connection without data transmission to optimize power consumption. Three modes are available, DTIM1 to 3. For example, in the DTIM3 mode, the modem is silenced for 300 ms and then activated for 3 ms. With this mode, the consumption is 15 mA.
  • Light-sleep In addition to suspending the WiFI modem, the CPU is put on hold and reactivated if necessary.
  • Deep-Sleep is the single most simple mode to implement and the most energy efficient for projects that run on battery.

The table from the official documentation gives a little idea of ​​consumption. When the deep-sleep mode is activated, the consumption drops to ~20μA.

esp8266 table deepsleep datasheet espressif

The power consumption of the ESP8266EX (2018) modules is very similar (page 18). Consumption climbs to 170mA with a WiFi connection at 11Mbps.

esp8266ex 2018 table deepsleep datasheet espressif

How to activate the deep-sleep mode

The Deep-sleep mode is activated by connecting the RST pin to the D0 pin.

Pin D0 is therefore no longer available for other use.
On some modules, pin D0 can be identified by GPIO16

wemos d1 mini activate deep-sleep mode esp8266


Other consequences of the deep-sleep mode

By connecting the pins D0 and RST, it is no longer possible to upload a program. Whatever your development environment (Arduino IDE, PlatformIO, ESP Tools), you will need to disconnect the RST pin before you can upload a program. This must be taken into account when designing your circuit. The best is to plan a jumper.

As the WiFi connection is stopped, seeing will no longer be able to access a configuration WEB interface. It will be necessary to provide a condition in your program to disable the deep-sleep mode. For example by adding a micro switch on the circuit.

Enable Deep-Sleep Mode in an Arduino Program

Now that everything is ready hardware side, we will tackle the Arduino code.

The thing to keep in mind is that when you wake the ESP8266 module, the project code is executed from the beginning. This is not a standby as is usual on a computer. Therefore, it is useless to torture one’s mind and to foresee cases of re-connection. It will be enough to execute the various processing in the setup() then to put back the ESP by executing the method ESP.deepsleep(duration, mode_wifi) which takes two parameters:

  1. Standby time in microseconds. For example, 1 second = 1,000,000 microseconds
  2. WiFi mode at restart

If you want to wake the module manually or with an external action, for example a switch connected to the RST pin, just indicate a zero time (0).

On waking, it is possible to choose between 3 modes of operation of the WiFi modem.

  • RF_DEFAULT is the default mode that you do not need to specify. The equivalent is RF_CAL. In this mode, the WiFi modem is enabled normally. That is to say that we can connect to the WiFi network and publish a status on an MQTT broker. This mode consumes a peak consumption that can reach 170mA for about 1 second.
  • An alternative version that consumes less energy is RF_NO_CAL (for NO CALibration). The WiFi modem is activated but no calibration of the radio signal is performed. In theory only because according to the measurements made by Andre, the consumption seems identical.




  • RF_DISABLED. If you do not need the WiFi connection you can keep the WiFi modem in standby. Attention, if this mode is activated, it becomes impossible to connect to the WiFi network. This is the equivalent of the modem-sleep mode described above.

So in summary:

  • ESP.deepsleep(0) suspends the module until it is woken up by a spike on the RST pin
  • ESP.deepsleep(5 * 1000000) wake up the module every 5 seconds
  • ESP.deepsleep(5000000, RF_DISABLED) wakes up the module every 5 seconds without re-activating the WiFi modem

ESP8266EX Deep-Sleep Mode Test

It is time to move on to a concrete example. Create a new sketch and paste the following code. You have several parameters

  • SSID the name of the WiFi network to which the module should connect
  • Password the network password
  • durationSleep the duration of the module. Here, it’s 10 seconds.
  • NB_TRYWIFI the number of attempts to connect to the WiFI network.

I used the Tricker library that comes with the ESP8266 SDK, which allows you to run a function at regular intervals to flash the blue LED on the Wemos d1 mini. It is a lighter library than the Thread library that does not require any additional installation.

The module tries to connect 10 times with a wait time of 500ms between each attempt. If the module can not connect to a network, it is in deep sleep until the next alarm clock and so on. This is a solution to avoid draining the battery. Of course, the duration of sleep is too short, but, it is for the example.

When connection is possible, the IP address of the module is displayed on the serial monitor.

This mode of operation can be used to make measurements at regular intervals and send them to an InfluxDB server or database.

#include <ESP8266WiFi.h>
#include <Ticker.h>
Ticker ticker;

const char* ssid       = "enter_your_ssid";         
const char* password   = "enter_your_password";    
#define durationSleep  10             // secondes
#define NB_TRYWIFI     10             // number of try to connect WiFi

void tick()
  int state = digitalRead(BUILTIN_LED);  // get the current state of GPIO1 pin
  digitalWrite(BUILTIN_LED, !state);     // set pin to the opposite state

void setup() {
  ticker.attach(0.5, tick);

  WiFi.begin(ssid, password);
  int _try = 0;
  while (WiFi.status() != WL_CONNECTED) {
    if ( _try >= NB_TRYWIFI ) {
        Serial.println("Impossible to connect WiFi network, go to deep sleep");
        ESP.deepSleep(durationSleep * 1000000);
  Serial.println("Connected to the WiFi network");
  Serial.print ( "IP address: " );
  Serial.println ( WiFi.localIP() );

  ESP.deepSleep(durationSleep * 1000000);

void loop() {

Wake the module using a contactor, PIR motion detector, microwave radar …

Now, what can be interesting is to wake up the module when an event is detected using a contactor or a switch, an infrared motion detector (PIR detector) or a microwave radar.

The problem is that to wake the ESP8266, you have to send a single rising edge to the Reset pin. When using a switch or the signal of a PIR detector, the signal sent is not correct and it causes a multitude of restarts of the module. The peak power consumption is at the start of the module. If we want to avoid waste and save the battery from unnecessary energy costs, we must solve this problem.

I have tested many montages, but it is the one proposed by Tomsim on Stackoverflow that gives the best result.

esp8266 capacitor wakeup circuit npn transistor

Here, Tomsim also retrieves the state of the button from pin D2. The RST pin is connected to pin D0 with a diode. It is not mandatory. Avoid sending a high signal from pin D0 to avoid an unintentional reset. If you want to manually restart from the program the Arduino module, use the ESP.reset() method instead.

Depending on the sensor used, here are two circuits that you can test.

Equipment used

Here is the material used for this tutorial

100pcs 8 Values Diode Bag Assortment Kit 1N4148 FR107 1N5408 For Arduino
AE__banggood Banggood
Geekcreit® 1uF-2200uF 125pcs 25 Values Electrolytic Capacitors Assorted Kit Set
AE__banggood Banggood
560 Pcs 1 ohm to 10M ohm 1/4W 1% Metal Film Resistor...
AE__banggood Banggood
200pcs 10 Values Transistor Assortment Kit Transistors Box Pack 20pcs Each Value...
AE__banggood Banggood
Geekcreit® MB-102 MB102 Solderless Breadboard + Power Supply + Jumper Cable Kits...
AE__banggood Banggood
Wemos® D1 Mini V3.0.0 WIFI Internet Of Things Development Board Based ESP8266...
AE__banggood Banggood
Last update was on: 30 November 2022 2 h 08 min

Circuit with NPN transistor (2N2222, BC457 …)

The first circuit is the simplest. An NPN type transistor will be used to send a signal to the RST pin as soon as a signal is sent by a present sensor or a mechanical switch.

The signal is recovered on the basis of the NPN transistor (pin 2). The signal from the transmitter (pin 1) is recovered on the RESET pin. You can add a reminder but that does not seem obligatory. The collector (pin 3) is connected to the GND.

BC547 transistor npn esp8266 deep-sleep wakeup


Necessary material

pir motion sensor wakeup deep-sleep esp8266 npn transistor

Circuit with filter capacitor upstream of the NPN transistor, in case of multiple reset
If you have multiple reboot problems with the ESP8266, you can test this second timeline based on the Tomsim principle.

The trick is to install upstream a small capacitor of 1μf then connect the output of the capacitor to ground through a resistor. When a signal is sent by the contactor or the sensor, the capacitor charges and produces only one output signal to power the base of the transistor. Residual energy is removed via the resistor.

The rest of the circuit remains the same. I tested several resistance values from 1kΩ to 10kΩ successfully.

Necessary material

pir motion sensor wakeup deep-sleep esp8266 npn transistor capacitor filter

An extra WiFi MQTT alarm system

Now that you can wake up the ESP8266 with a presence detector, it’s easy to send a status change to a home automation server or MQTT broker. Here is a small example of a program that sends a state change when the ESP8266 module wakes up.

esp8266 deep-sleep pir motion detector wakeup interrupt


Before testing the program, change the following settings:
  • The SSID and password of the WiFi network
  • The IP address of the MQTT broker
  • NB_TRYWIFI, the number of attempts to connect to the WiFI network.

Upon awakening, the module attempts to connect 10 times (NB_TRYWIFI) to the WiFi network. If the connection fails, the module goes to sleep to avoid draining the battery. If successful, it connects to the MQTT broker and publishes the state on the DeepSleepDemo / PIR topic for one second. The blue LED is off and then the module goes back to the next motion detection.

One could improve the code and measure the time between two detections of movement to avoid multiple alerts.

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

#include <Ticker.h>
Ticker ticker;

#define NB_TRYWIFI    10

const char* ssid         = "enter_your_ssid";
const char* password     = "enter_your_password";
const char* mqtt_server  = "enter_mqtt_ip";

WiFiClient espClient;
PubSubClient client(espClient);

void tick()
  //toggle state
  int state = digitalRead(BUILTIN_LED);  // get the current state of GPIO1 pin
  digitalWrite(BUILTIN_LED, !state);     // set pin to the opposite state

void sendMQTTMessage(){
  if (!client.connected()) {
  client.publish("DeepSleepDemo/PIR", "1");
  client.publish("DeepSleepDemo/PIR", "0");

void setup() {
  int start = millis();
  // Fait clignoter la LED intégré durant la connexion au réseau WiFi - Blink Bleu Led during WiFi connexion
  ticker.attach(0.5, tick);
  // Raison du réveil - restart reason
  Serial.println(""); Serial.print("Reason startup :");Serial.println(ESP.getResetReason());
  WiFi.begin(ssid, password);

  Serial.println("Connecting to WiFi.");
  int _try = 0;
  while (WiFi.status() != WL_CONNECTED) {
    if ( _try >= NB_TRYWIFI ) {
        Serial.println("Impossible to connect WiFi network, go to deep sleep");
  Serial.println("Connected to the WiFi network");
  Serial.println("Send PIR Status to MQTT broker");
  client.setServer(mqtt_server, 1883);
  // Durée du réveil - waking time
  Serial.println("Waking time: ");Serial.print(millis()-start);Serial.println("ms");

  digitalWrite(BUILTIN_LED, LOW);
  Serial.println("Go to deep sleep");

void loop() {

boolean reconnect() {
  if (client.connect("ESP8266Client")) {
    Serial.println("Connected to server");
    return client.connected();
  Serial.println("I think connection failed!");
  return 0;

Errors when uploading an Arduino program when deep-sleep mode is enabled

Many ESP8266 development board manufacturers now incorporate a soldering jumper to enable deep-sleep mode. It’s cleaner and there is nothing to plan on the circuit. Here the Wemos d1 mini v3.x.x (left) and the Wemos d1 mini Pro 2018 (right).

In both cases, it is very easy to follow the track which connects the pins RST and D0.

wemos d1 mini version 3.0.0 bottom wemos lolin d1 mini pro bottom

However, this option must be reserved when the project is completed. Indeed, every time we have to update the program, it will be necessary to disconnect the pins D0 and RST. If necessary, remove the jumper using a desoldering pump.

A typical case of error message when the deep-sleep mode is not disconnected.

esp8266 deep-sleep download espcomm_upload_mem failed

If the RST pin is connected to a sensor that can cause a Reset during program installation, you may encounter the FLASH_DOWNLOAD_DATA error.

esp8266 deep sleep flash_download_data


Other optimizations

Of course the consumption announced by activating the Deep-Sleep mode does not take into account the rest of the assembly. If you use a sensor that draws power directly from the battery, the range will be directly affected. This is the case, for example, when using the 5V or 3V3 pins.

If you want to reduce the power consumption of the devices, you can use a digital output, provided that the necessary power is low. The Imax current available for each output can not exceed 12mA (page 18).

Another solution is to activate the energy saving mode that is offered by most I2C sensors. This is case by case, you will have to search the library or develop your own driver by referring to the official documentation of the manufacturer.



Click to rate this post!
[Total: 7 Average: 4.7]

Thanks for your reading

Did you like this project ? Don't miss any more projects by subscribing to our weekly newsletter!

Are you having a problem with this topic?

Maybe someone has already found the solution, visit the forum before asking your question
  1. First off, thank you for the great insight on how to conserve energy on our beloved ESP8266, however you state that the BC547 transistor’s collector (pin 3) is connected to the GND, but in the pictorial schematic you have it tied to the RESET pin of the ESP8266.

    And when I look the data sheet for a BC547 (which you have named as BC457 for the link to the product) , leg 1 is the collector and leg 3 is the emitter.

    So either the pictorial of the transistor showing the numbering of the legs is wrong, or the pictorial of your schematic is wired up wrong to correctly bias the transistor to the way you wanted

  2. Thank you for the article but unfortunately the example doesn’t work for me:( D1 Mini doesn’t want to wake up. I’ve tried to change polarity of transistor after reading Mark Roles’ comment, but got the same result

  3. On this one: “Errors when uploading an Arduino program when deep-sleep mode is enabled” there are different forum posts saying using a resistor (470R, 350R or even 220R seems to work) or a diode works perfect.

    I used a 470ohm resistor to connect the deepsleep ‘solderpads’ (or you can connect RST to D0(=GPOIO16) via this resistor, and now I can either upload a sketch or just use the d1 mini like it should, with having the device already setup as it will be in the final project.

  4. Great article! Very well explained. Have you tried having a nodemcu that is in deep sleep and it’s subscribing to an mqtt topic. When it wakes up, it checks for new messages on that topic and performs an action and then goes back to deep sleep? Thanks again

  5. Hey, just got this working here, thanks for the write-up! Found the same issue as mark, the BC457 pinout image shown doesn’t seem to match the circuit. Switching it around to match the schematic diagram did work however. Cheers!

  6. for my < ver 3 wemos D1 mini I can leave RST and D0 connected and I can download new code

  7. Didn’t work for me. The PIR sensor wakes up the ESP without any reason. I tried changin emitter and connector legs but same.. Any suggestions?

  8. Finally I solved the issue. I’m using Nodemcu and tried the first circuit. The problem was, PIR sensor triggered the Nodemcu rapidly, and forever. I solved this issue by using another one kohm resistor between middle leg of the transistor and the signal leg of the PIR sensor. Thus, the signal strength of PIR sensor is lowered and it doesn’t trigger forever. It does only once, when movement is detected.

  9. Hi all, When I transferred from breadboard to circuit board I could not get the second schematic (with capacitor) to work at all, it worked on the breadboard okay, then eventually I noticed I had wired the breadboard ‘wrongly’ but it worked, I realised the resistor to ground was coming off the positive side of the cap in the original breadboard scheme but in fact it should have been coming off the negative side of the cap, when I switched those around on the circuit board it all started working right. Confirmation is also in the last picture. I’m not sure who the author of this piece is but may I say thank you/merci for a rewarding challenge 🙂

  10. Hi!

    I tried your example, but it didn’t work for me, I used same components as you except the PIR, which i use is a HC-SR501 and the transistor from that i tried with bc337 and bc547 too. Is it possible i use PIR or transistor or both? Or something else the problem.

  11. First of all thanks for this great review. After i changed the posetive and negative around on the NPN ( i used a 2n2222) it works like a charm.

    For my specific project (bathroom) i want to also add a humidity sensor. My hope is that i can still use a timer aswell. So i want the ESP to wake up every minute to check and log the humidity to MQTT (to switch on the ventilation if needed) but if somebody walks in I want the ESP to wake up immediate so i can turn on tights. Obviously it would not be very usefull if it takes (in worst case a minute) for the lights to switch on.

    With the help of this articel I’ve got the PIR to work. But as soon as the timer goes off it’s keeps resetting itself like every 100ms. I’ve tried different things which capacitors an extra NPN and even diodes but i can’t find a way to make both the timer and the PIR work as a trigger at the same time. Any help would be greatly appriciated.

    • Hello Laurens. Have you considered switching to an esp32? I wonder if there is not a problem with the power supply of your ESP8266 which causes it to restart every 100ms (it is a hypothesis). It’s much easier to manage multiple sleep / wake sources with the ESP32

      • Hi Christophe,

        I haven’t considered ESP32 so thanks for the tip. Might be a nice POC for the future.

        Currently I’m working on a solution by using an ATTiny13 (It’s still in breadboard status).

        I connected the PIR to the ATTiny and programmed an interupt on it so it will wake up when the PIR goes HIGH. I also programmed a watchdog so if the PIR doesn’t switch on it still wakes every 2 minutes. When the ATTiny wakes up i send a High to a transitor which connects the ESP to GND and so it I’ll boot. From the ATTiny I also forward the digitalRead of the PIR to a GPIO on the ESP so the ESP knows if the ATTiny woke up because of the timer or the PIR. First step of the ESP is to put a Signal high back to the ATTiny so the ATTiny knows the ESP Is a wake. Then it reads the PIR value and the DHT Sensor puts it on a MQTT Topic. Last step before the ESP.deepSleep command is to put the signal to Attiny to LOW so the Attiny Knows it can go to sleep as well.

        The Attiny is an extra component but it does solve the issue for about 40 cents and the circuit consumes less power because the ESP is not sleeping but completely turned off. THe Attiny only consumes about 5 uF while sleeping so that’s kind of the best you can get i think.

        Extra bonus is that my family thinks I’m some kind of wizard when they see me program such a small chip :).



        • Hello Laurens. That’s a great idea ! the best of both worlds 🙂 It’s true that the ATTiny is great, it’s a shame that there is only Espressif which offers economical WiFi connectivity. The other MCU makers have passed by.

  12. Thanks for the project description and example.
    I am attempting to use the RTC DS3231 in my project and haven’t found a way to wire it, but maybe a mod of your schematic will allow it to work.
    If I hook the SQW output to the Base of the transistor(where you have the pir signal) will that trigger a wakeup when the alarm goes off?
    Any help is appreciated.

    John B.

  13. The Fritzing view of the breadboard with the capacitor not only gets the pinout of the transistor wrong, the resistor is also shown at the wrong leg of the electrolytic capacitor.

  14. Hello Christophe, Joining late here so a bit off.
    =Does the Fritzing reflect Uwe’s comment.
    Thanks for a well written article. I realize this kind of attempt
    is a bit tenuous with all sorts of software that is interfaced that
    we only see the api’s for.

  15. Hello Christophe, i tried as the per the article and i have a problem. The setup only works for the first motion, after that if the esp goes to sleep it is not restarting.
    i followed Fritzing with capacitor connection, i connected the PIR out pin to ceramic capacitor’s one end and i use the same end to connect to ground via 1k resistor. [ sample connection diagram ]. i have no idea why it works only for the first time.

    Debugging: i removed the capacitor from the breadboard and placed it again after few seconds, then it works, but again only once.

    I would need your help, thank you.

  16. Hi Christophe, thanks a lot for this tutorial. I have rebuilt your projekt and it works well. But I have a problem with the MQTT messaging: My MQTT-Broker ‘mosquitto Version 2.0.10’, running on a raspberry reports only the first message (the “1”). The second message got lost in the nirwana. I have checked the return codes of both messages
    rc = client.publish(“DeepSleepDemo/PIR”, “0”). In both cases I got a 1 = messages was sent. All works correctly.
    Therefore the Problem must be in the message processing.
    As a MQTT-subscriber I used two independent ways: 1. the Windows program MQTTx 2. a small program on a ESP8266 D1 Mini. Both programs display message one only.

    Can you give me a hint, why mosquitto denies to foreward the second message? I appreciate your support. Thank you very much.

Leave a Reply

Read more
DIY Projects
DIY Projects
%d bloggers like this: