Deep Sleep and OTAA (m328p / LMIC)


For a node I’m developing at the moment, I using a power-gating MOSFET from a nano current timer (tpl5111)to switch my entire node off. This is an extremely elegant solution as it allows me to run ultra low current (35nA). But I just recently came across OTAA best practice and saw that the join method should be done once in the device life-time. Well … in my current situation I’m doing a join every 2h when my device wakes-up to do a measurement.

I have read the various discussions around this issue with deepsleep and the need to store the join details in non-volatile memory. My question is the following: I wanted to know if anyone has managed to successfully adapt the LMIC library to write all the OTAA key into EEPROM (or external FLASH) and did managed to send payload without a new join session after deepsleep (or power off). If this is not currently possible, it would mean I have to re-think our node solution, as I understand joining every 2h after power off does violate the LoRaWAN standard.

Thank you for your answers.

Actually this is not…

The Atmega 328p has itself an extremely low power sleep current, you should be able to get sleep current under 1μA…

Shutting down the node completely should be seen as last resort for OTAA as storing the keys is not enough, you need to store the session state (Frequencies, counters, …), basically almost the whole LMIC structure, and you don’t want to write to EEPROM after each message.

If you absolutely want to to that, use FRAM to store session data, but using the Atmega deep sleep is much more easy…

There are a several showcases of Ultra Low Power nodes in this forum :wink:


Well, it might not violate the standard, but you will run into issues because each join requires a unique 16 bit random value (LoRaWAN 1.0.2). After some time your node will have more and more difficulty to join because the random values will match one previously used which will be rejected by TTN.
Storing the stack state (including channel list, ADR settings, counters etc) is by far the best solution.


Thank you kersing for your answer;

And yes indeed; I understand that saving the stack state is the the best solution. However I don’t really know where to start using LMIC(RF96) + m328p MCU.

  • Does the MCU EEPROM will suffice for this task or should I consider external non-volatile memory?
  • Where and how in the LMIC library one would implement this ? First perform an OTAA join, if successful store the stack. During the next power off/on cycle, verify of OTAA has been previously done, if yes restore the state and send payload via OTAA without join (or ABP).

Thank you.


Yes I know about the low power solution for ATmega328p, I have implemented this in previous devices however it makes a huge difference between 1uA and 35nA when running on a CR2023 coin cell for target lifetime of 1+ year.

But I hear you, if you use ultra low power on m328p, can you then still power cycle the RF95 and only have the MCU running on ultra low sleep?

Once you are under 1µA, the real factor in power consumption is the awake time, not the sleep time…

If you draw 1µA in sleep time, it will require a capacity of 10 mAh over a year, which is nothing compared to the wake-up current draw.

To give an idea I measure 0.84µA on my nodes, with RFM95 and BME280 connected, and I do nothing on the RFM95 to save power (I don’t think you will go under 0.40µA for the 328p alone – but again this is not the challenge, the challenge is to minimize your awake time/consumption)

1 Like

It might seem that way, but in practice, perhaps not.

It depends on the exact circuit of course, but an ATMega328 and LoRa device is capable of a deep sleep current of circa 1.5uA.

A sleep current of 1.5uA, is really of no consequency, a set of AAA Alkalines would keep the node going for 76 years, if the batteries could have that long a shelf life.

Using the TPL5110 to power off the node, my well be actually using more power than the deep sleep option, due to the time take to cold start the node every time.

The TPL5010 is in my view a much better option. It can provide an accurate interrupt to wake up from deep sleep.

And with the deep sleep approach you dont have the issues with rejoin etc.

Thank you for your answer;

I am indeed re-considering the power gating option. Initially I was using ABP, therefore the issue never surfaced with the JOIN. But yes, I think using the TPL5010 on a hardware interrupt to wake up the MCU seems the best case scenario.

What method would you recommend for deepsleep?

  • External interrupt from RTC or nano timer
  • LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); looped as many time as it’s need to reach 2h.

There are some notes on power down versus deep sleep in the section entitled;

“Reducing Tracker node sleep current - a wasteful race to the bottom ?”

In this report;

Its about GPSs and trackers, but the principles are the same.

1 Like

I do external interrupt from TPL 5110.

I use Mini-Lora nodes as described in:

This Arduino stack allows you to save the session keys (and network id, upload counter):

I’m basing a node on this library for use with an ESP32 TTGO LoRa board where the session keys and some counters are stored in (simulated) EEPROM here. In the EV_JOINED callback, I’m saving them:

Upon startup, I check my EEPROM structure for a previously saved session, and restore it using either LMIC_SetSession(…), or do a JOIN using LMIC_StartJoining():


How to get dev_EUI from RFM95 with arduino nano? I have problems

Thanks in advance.

@am1lcarcaceres just let TTN generate you a unique one when you register a device

The RFM95 does not have an EUI so you will not be able to get it.
Use a TTN generated one like @Paul_Stewart suggests.

Which library are you using to drive the RFM95?

I’m just entering the world of LoRa, thanks for solving the doubt

I am using the LMIC library, thank you for solving my doubts

Hi im also using a ATMEGA328p with an RFM in deepsleep mode.

But my uC wakes only 3 oder 4 times up after that it newer sends data again.

Somebody has a clue?

that’s not enough information :sunglasses:


I’m using IOT-MCU V1, soldered DIO1 D5 together and my sketch is from

Using the MCCI Library.

It works only one time, (see the data in the console) then die Atmega sleeps and never wakes up again.