Skip to content

Deep Sleep and Power Off

Manuel Bl edited this page Sep 29, 2021 · 1 revision

LoRaWAN and TTN are often used by battery powered devices. Thus, saving energy to extend the time until the battery is recharged is paramount. With the ESP32, there are two main options:

  • Put the ESP32 into deep sleep and wake up again after a certain time or if an external event is triggered.
  • Power off the ESP32. This requires additional circuitry to control power.

Both options are supported by this library.

Challenge

When a TTN device is initially powered on, it sends a join request to become activated in the network. The activation establishes a session and assigns session keys to the device. This is known as OTAA – an abbreviation for over the air activation.

TTN will send MAC commands to the device to configure timings, channels etc. The device has to use increasing sequence numbers for messages. Furthermore, TTN devices are supposed to hop between channels for communication. Thus, there is information to be remembered throughout a session.

So the challenge with deep sleep and power off is to retain the information associated with the current TTN session.

If the state were not retained, the device would need to rejoin every time it wakes up from deep sleep or power off. This does not only take a lot of time and power. It also undermines many mechanisms for the efficient use of the LoRa spectrum. This is why TTN v3 implements restrictive limits on the number of joins.

This library (or rather the underlying LMIC library) also enforces the link budget, i.e. it makes sure the devices does not send messages more frequently than allowed by TTN. It does so by delaying a message until there is sufficient available budget. This mechanism depends on a working clock. So as an additional challenge, the clock needs to be retained or restored.

Usage Pattern

The basic usage pattern is that the device does some measurement, transmit the result as a TTN message and then goes to sleep until the next measurement is due or an external event occurs. Transmitting a message will typically take 7 seconds as the device has to be listening for downlink messages during two RX windows that are currently scheduled after 1 and 5 seconds after the uplink message (the effective values are transmitted in the join accept message). It might take slightly longer if the device has received MAC commands and needs to confirm them. In that case, an additional message is sent.

So a typical cycle is that the ESP32 will be awake and working for about 10 seconds and then go to sleep for 5 minutes, 1 hour or whatever your use case requires. The library does not support going to sleep for just 2 or 3 seconds.

Deep Sleep

In deep sleep mode, the ESP32 turns off everything except the RTC memory, RTC clock and – if configured so – the ULP processor and/or selected RTC GPIOs. It can be awoken from deep sleep by a timer, by external inputs or by the ULP processor. When the ESP32 wakes up, the program restarts and everything is re-initialized except for the RTC memory, RTC clock and ULP.

Before going to deep sleep, the TTN session state is saved in RTC memory. After deep sleep, the session state is restored. Furthermore, the LMIC clock is updated based on the RTC clock.

Two example programs demonstrate the use of deep sleep:

The typical code checks whether there is valid session state in RTC memory. If so, the state is restored. If not, the device will start joining and thus establish a new session.

If the state is restored from RTC memory, it is invalidated in RTC memory to ensure it not reused again. This would fail as the same sequence number cannot be reused.

Approximately 360 bytes of data are occupied in RTC memory if this feature is used.

Power Off

Even more energy can be saved by completely powering off the ESP32. This requires additional hardware that powers on the ESP32 in the first place and lets the ESP32 control when it should be powered off. Such circuitry goes by the name power latch, power trigger or trigger board.

During power off, the session state has to be stored in non-volatile storage (NVS), which is flash storage as the ESP32 has no EEPROM.

For the managing the clock, there are two options:

  • On power up, specify the duration that device was powered off. Usually, this is not known. So an estimate of the minimum duration can be used. Let's say the ESP32 is powered up whenever the garage door is opened. Except for rare cases, there will be at least 30 minutes between to consecutive openings. So 30 minutes is used as the duration.

  • If the real world time is known, e.g. because an external RTC clock is connected, then the ESP32's system time should be set accordingly. This must happen before the session state is restored. Use settimeofday() to set the time. Also see ESP32 System Time.

Two example programs demonstrate the use of power off:

Before powering off, the TTN session state is saved in NVS. After power up, the code checks if there is valid state data in NVS. If so, the state is restored and the clock adjusted according to the specified duration. If not, the device will normally join the network and establish a new session.

Whenever the state is restored from NVS, it is invalidated to ensure it is not reused. Reuse does not work as it would reuse a message sequence number and the message would be rejected.

In order to reset the device and force it to rejoin, it can be started and shut off after 3 seconds. 3 seconds is after the state has been restored but before a new state has been saved.

Flash Memory Wear

Flash memory can only be written to a limited number of time. After that, it has worn out so much that it can stop to work. Today's flash memory can typically handle between 10,000 and 100,00 write cycles.

To save the state, approximately 360 bytes of payload data are written to non-volatile storage into the default partition nvs. Additional space will be needed for the management of the key/value pairs and their validity. So the total will be approximately 400 bytes. Every time the session state is saved, this amount of data is appended to NVS. Once the entire nvs partition has been filled, flash pages are erased and reused. At this time, the entire partition has been written once and a new write cycle starts. This is a simplified view but it is sufficient to derive a calculation of how long the flash memory will last:

Life time = max. write cycle × size of NVS partitions ÷ 400 ÷ power-on frequency

Example:

Assuming the flash memory can only sustain 10,000 write cycles, the default nvs size of 24 kBytes is used and the device is powered on 10 times a day, the life time until the flash memory could start to fail is:

10,000 cycles × 24 kBytes ÷ 400 bytes ÷ 10 p.d. = 60,000 days (more than 160 years)

So with just 10 power ups per day and no other NVS use, the flash memory wear is no issue.