This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Sleep Modes on the nrf9160 DK

Hi All,

I've just received an nrf9160dk, I'm starting to investigate the development of our application while the hardware guys produce a custom board.  

I'm just starting with the power management and sleep modes for the nrf9160. 
The form of the application is as follows:

Most of the time I want the radio off (no PSM or eDRX), I also want the MPU in its lowest power state, with only the RTC running (no other peripherals are needed in sleep) 
Every 5 minutes I want to power on the MPU and sample a couple of sensors and store the results in EEPROM. 
Every 8 hours I want to power on the radio and send the previously buffered results. 

Our previous-gen product used a ublox SARA tied with UART to an STM32 uC. I've come from an STM32 development background and I'm struggling to find the appropriate function calls in the NRF-SKD that puts the nrf9160 into this deep sleep with the RTC running. 

Any help/guidance/pointers are very much apricahated.  

 

Parents
  • Hi, Skipper!

    Zephyr handles power management quite well in the backround, requiring little effort in terms of dedicated function calls. Using the function k_sleep puts the thread from which it's called into sleep. If all threads in the application are sleeping the OS will put the device in low power operation, with the RTC running. For your case I suggest having main wakeup every 5 minutes to do sampling while you have a separate timer that fires every eight hours, setting a "upload" flag for example. 

    Note that serial operation should be deactivated for optimal power consumption. This can be done by setting CONFIG_SERIAL=n in prf.conf. If you are using other peripherals they may have to be deinitialized or turned off.  For information on that, as well as more details around power management in Zephyr I suggest reading up on the Zephyr Power Management API

    I hope this answers your question!

    Best regards,
    Carl Richard

Reply
  • Hi, Skipper!

    Zephyr handles power management quite well in the backround, requiring little effort in terms of dedicated function calls. Using the function k_sleep puts the thread from which it's called into sleep. If all threads in the application are sleeping the OS will put the device in low power operation, with the RTC running. For your case I suggest having main wakeup every 5 minutes to do sampling while you have a separate timer that fires every eight hours, setting a "upload" flag for example. 

    Note that serial operation should be deactivated for optimal power consumption. This can be done by setting CONFIG_SERIAL=n in prf.conf. If you are using other peripherals they may have to be deinitialized or turned off.  For information on that, as well as more details around power management in Zephyr I suggest reading up on the Zephyr Power Management API

    I hope this answers your question!

    Best regards,
    Carl Richard

Children
  • Hi Carl, 


    Your answer has got us most of the way there, we've just got one problem with deep sleep. 
    prf.config

    SYS_POWER_DEEP_SLEEP_STATES=y
    SYS_PM_MIN_RESIDENCY_DEEP_SLEEP_1=1000

    main.c

    void main(void) {
       nrf_gpio_cfg_output(LED_0);
       while (1) {
          nrf_gpio_pin_toggle(LED_0);
          k_sleep(K_MSEC(500));
          nrf_gpio_pin_toggle(LED_0);
          k_sleep(K_MSEC(5000));
       }
    }


    This blinks the LED once goes into deep sleep and never wakes. 
    Attempt to use RTC:
    const nrfx_rtc_t rtc = NRFX_RTC_INSTANCE(0);
    static void rtc_handler(nrfx_rtc_int_type_t int_type) {
      if (int_type == NRFX_RTC_INT_COMPARE0) {
        nrf_gpio_pin_toggle(LED_0);
      }
    }
    static void rtc_config(void) {
      uint32_t err_code;
      nrfx_rtc_config_t config = NRFX_RTC_DEFAULT_CONFIG;
      config.prescaler = 4095;
      err_code = nrfx_rtc_init(&rtc, &config, rtc_handler);
      if (err_code != NRFX_SUCCESS) {
        printk("Failure in setup\n");
        return;
      }
      nrfx_rtc_cc_set(&rtc, 0, 10, true);
      nrfx_rtc_enable(&rtc);
    }
    void main(void) {
       nrf_gpio_cfg_output(LED_0);
       rtc_config();
       IRQ_DIRECT_CONNECT(RTC0_IRQn, 0, nrfx_rtc_0_irq_handler, 0);
       irq_enable(RTC0_IRQn);
       nrf_gpio_pin_toggle(LED_0);
       k_sleep(K_MSEC(500));
       nrf_gpio_pin_toggle(LED_0);
       sys_set_power_state(SYS_POWER_STATE_DEEP_SLEEP_1);
    }
    
    
    This blinks the LED once goes into deep sleep and never wakes. RTC seemingly gets unpowered?

    If I set SYS_POWER_DEEP_SLEEP_STATES=n then it works, LED blinks continuously but only enters sleep (not deep sleep). De-initing bsdlib and CONFIG_SERIAL=n made normal sleep current consumption much better (now in uA) but ideally want to get to deep sleep.

    Cheers, 
    Skipper
  • Hi!

    I've attached an application that achieves average sleep current of ~3.16 µA using only k_sleep(i.e the RTC), as well as the following prj.conf:

    CONFIG_SYS_POWER_MANAGEMENT=y
    CONFIG_SYS_POWER_DEEP_SLEEP_STATES=y
    CONFIG_SYS_PM_STATE_LOCK=y
    CONFIG_SERIAL=n
    CONFIG_DK_LIBRARY=y

    It seems like SYS_PM_MIN_RESIDENCY_DEEP_SLEEP_1 somehow forced the device to stay sleeping(or off, as the current consumed was far below our minimum specs), but I'm not sure why. Notice as well that I've added the CONFIG_SYS_PM_STATE_LOCK.

    In addition you should add CONFIG_SERIAL=n to the prj.conf of the SPM sample, located at <ncs_root>/nrf/samples/spm. Hope this helps you on your way, if not I'll take a look at your RTC handling as well.

    4578.sleep.zip

    Best regards,
    Carl Richard 

  • Hi Carl, 

    We were able to get the sleep current down to the around ~3 uA thanks for the help!

    We have external devices that we want to talk to via UART. Currently, I'm using zephyr's UART implementation which works well but when I disable serial (CONFIG_SERIAL=n) my code fails to compile:

    "uart.h:180: undefined reference to `z_impl_uart_irq_rx_enable'",

    Is there something I'm missing or is the NRF9160 unable to go into low power sleep if built with the serial flag enabled?

    We've got CONSOLE, RTT_CONSOLE and PRINTK enabled so we can use printk to debug through Segger RTT.

    Will we need to disable this before going to sleep?

    Cheers,

    Skipper

  • Hi again, Skipper!

    Good to hear!  The device is able to go to sleep with serial enabled, but it will consume quite a lot more current (~900uA). However, with version 1.4.0 of the nRF Connect SDK we released a Low Power UART driver that doesn't rely on the serial flag. I haven't tested the actual power consumption when using the driver yet, but you can have a look at the sample demonstrating how it's used.

    You should not need to disable the RTT logging before going to sleep from what I know, but I will double check that.

    Best regards,
    Carl Richard

  • We don't need the UART in sleep, is there any way to de-init the serial peripheral before sleep that has the same effect as setting the CONFIG_SERIAL=n?


    Aditionally the LPUART sample provided doesn't compile with the below errors:

    3> In file included from C:/Users/josh/ncs/v1.4.0/zephyr/include/arch/arm/aarch32/arch.h:20,
    3>                  from C:/Users/josh/ncs/v1.4.0/zephyr/include/arch/cpu.h:19,
    3>                  from C:/Users/josh/ncs/v1.4.0/zephyr/include/kernel_includes.h:38,
    3>                  from C:/Users/josh/ncs/v1.4.0/zephyr/include/kernel.h:17,
    3>                  from C:/Users/josh/ncs/v1.4.0/zephyr/include/init.h:11,
    3>                  from C:/Users/josh/ncs/v1.4.0/zephyr/include/device.h:22,
    3>                  from C:/Users/josh/ncs/v1.4.0/zephyr/include/drivers/uart.h:26,
    3>                  from C:/Users/josh/ncs/v1.4.0/nrf/drivers/serial/uart_nrf_sw_lpuart.c:7:
    3> C:/Users/josh/ncs/v1.4.0/zephyr/include/devicetree.h:297:40: error: 'DT_N_INST_0_nordic_nrf_sw_lpuart_BUS_P_label' undeclared here (not in a function)


Related