Power management issue (LoRa E4-mini + LoRaWAN stack + UART)

I am trying to complete an apparently very simple application where a LoRa E4-Mini should power a sensor, read the sentences on UART, send over LoRaWAN, and go to sleep in low power mode. My initial development was using stdio over uart and functions such as stdio_write() and stdio_read(). The software was functional but would not allow to reach a low power mode, since apparently with RIOT-OS the developer is not allowed to set the LPM bits but must hope the scheduler understands that all threads have completed their tasks to automagically set a low power mode. This feature does not seem functional with stdio over uart if I understand pm: is the overall power management flawed? · Issue #8428 · RIOT-OS/RIOT · GitHub correctly.

So I rewrote the program without relying on stdio but only with the uart example and a callback function going to sleep with the ztimer (see RIOT_NyAlesund/lora_snowdepth/main.c at main · jmfriedt/RIOT_NyAlesund · GitHub ). The new example is functional as well (i.e. I get the UART collected sentences on the LoRaWAN network server) but again power consumption remains at 9 mA, so the microcontroller is not going to sleep I believe. Am I missing a low-power mode capability when writing RIOT_NyAlesund/lora_snowdepth/main.c at main · jmfriedt/RIOT_NyAlesund · GitHub ?


I am unable to update the title which should read “LoRa E5-mini” of course, misspelled board name. I just ran the tests/periph/pm example and the current consumption also remains at 10 mA.


this is basically correct. The scheduler will reliably detect when no task is runnable (e.g. because all threads are blocked) and will cause the MCU to enter the deepest possible power state to enter.

The deepest possible power state is limited be a number of factors.

  1. Lower power states need to be implemented to work (for STM32, this is fully implemented)
  2. Lower power states involve disabling clock domains. But if those clock domains are still needed, they cannot be disabled.
    • A high frequency timer (as e.g. set with xtimer or ZTIMER_USEC) will typically prevent low power states other than sleep. Try using ZTIMER_MSEC and the ztimer_msec module instead. You can use ZTIMER_USEC when using the ztimer_ondemand module for short timeouts (during which lots of power is consumed), but the system will go back to sleep afters
    • Other peripherals also disable low power states. UART peripherals often use a lot of power while active. If the sensor you interface with will only send data as a reply to a request send on UART, try uart_poweron() before sending the request and uart_poweroff() when the reply was fully received. That should unblock the power state
    • The pm shell command can list you the number of “blockers” (where blockers is roughly synonymous to reference counting). If a power state has only one blocker, you only need to figure out which specific driver is preventing the system from entering a low power state.

My bet is that the UART driver is the culprit. If you cannot just power it off most of the time, try using UART_DEV(2) (PC1 = RXD, PC0 = TXD) of the lora-e5-dev board and add FEATURES_REQUIRED += periph_lpuart to the Makefile. That will use the low power UART instead of the USART peripheral, which should allow entering low power states without disabling the UART interface. But even that peripheral will use some energy while active, so uart_poweroff() is still you friend when you want to optimize energy consumption.

I hope I could answer your question.