Deep sleep is low power mode that can drop microcontroller currents to virtually zero, thus saving battery life.

To enable deep-sleep in the NodeMCU board we have to connect the D0 pin t the RST pin. This will allow us to use the node.dsleep() function. The dsleep function behaves like a convenient timed restart mechanism.

The maximum sleep time is 4294967295us, ~71 minutes. This is an SDK limitation. Firmware from before 05 Jan 2016 have a maximum sleep time of ~35 minutes.

We can read more about dsleep in the documentation page.

The time unit is microseconds (μs), a microsecond is one millionth of a second.

So, if we want our board to sleep for one minute:

1m * 60s * 1000ms * 1000μs = 60000000μs

You need to have an init file, as the routine is that after Xμs the processor will reset itself and follow standard procedure by calling the init.lua script.

-- init.lua calls sensor routine
tmr.alarm(0, 1000, 0, function()
    print("Initializing temperature sensor")
    dofile("sensor.lua")
end)

Then, to sample temperature and humidity using a DHT-11:

-- time between readings, 1minute
sleep_time_microseconds = 60 * 1000 * 1000

function get_sensor_data()
    pin = 3
    status, temp, humi, temp_decimial, humi_decimial = dht.read11(pin)
    if status == dht.OK then
        print("DHT Temperature:"..temp..";".."Humidity:"..humi)
    elseif status == dht.ERROR_CHECKSUM then
        print( "DHT Checksum error." );
    elseif( status == dht.ERROR_TIMEOUT ) then
        print( "DHT Time out." );
    end
end

function read_data()
    get_sensor_data()
    node.dsleep(sleep_time_microseconds, 2)
end

read_data()

I'm using the float version of the NodeMCU firmware, so the results come as floats. If I had the int version, I would have to massage the results a little bit:

print(
    string.format(
      "DHT Temperature:%d.%03d;Humidity:%d.%03d\r\n",
      math.floor(temp),
      temp_decimial,
      math.floor(humi),
      humi_decimial
    )
  )

If we are using WiFi in deep-sleep, is recommended to configure the connection to use a static IP which will save time- less DHCP back and forth- and battery. In my totally informal testing, using static IP show a 1-2 second delay and 4 or more for DHCP.

Another configuration option to take into account when optimizing for battery life is the wifi signal mode:

-- wifi.PHYMODE_B 802.11b: More range, low transfer rate, more current draw.
-- wifi.PHYMODE_G 802.11g: Medium range, medium transfer rate, medium current draw.
-- wifi.PHYMODE_N 802.11n: Least range, fast transfer rate, least current draw.
wifi.setphymode(wifi.PHYMODE_N)

Also, we can save some battery live by passing an option to dsleep. If we read the docs, we see that passing the value 2 means no RF_CAL.

option number (integer) or nil. If nil, it will use last alive setting as default option.

0, init data byte 108 is valuable

0, init data byte 108 is valueless 0, RF_CAL or not after deep-sleep wake up, depends on init data byte 108 1, RF_CAL after deep-sleep wake up, there will belarge current 2, no RF_CAL after deep-sleep wake up, there will only be small current 4, disable RF after deep-sleep wake up, just like modem sleep, there will be the smallest current

wiring-diagram

consumption related to WiFi mode:

power consumption http://bbs.espressif.com/viewtopic.php?f=6&t=133&p=485&hilit=sleep+modem power modes http://russ.russmathis.com/esp8266-power-modes/