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

nRF51: IoT-SDK and current consumption / sleep modes

Hello again,

fortunately I made some progress using the IoT-SDK v0.8.0 on nRF51. I extended the MQTT-example to my needs, but there are still some questions. The final device is battery-powered and should transmit some sensor values periodically, so power management is very important.

The program flow would be:

  • Wake up
  • Read sensors
  • Start advertising
  • Connect to MQTT broker after connection is established
  • Publish values
  • Disconnect
  • Go to sleep for x minutes and wake up again

To optimize current consumtion, I intend to power off all unnecessary peripherals:

  • As far as I can tell, the Timer0 is needed by the Softdevice itself, so there is no optimization possible here.
  • Disable app_trace (UART)
  • Disable LEDs and buttons

Which other peripherals are used by the Softdevice itself and the other components in the MQTT-example?

I found some app_timers, but I don't understand the difference between app_timer and nrf_drv_timer. I can only assume, that nrf_drv_timer is using the hardware timer peripheral and app_timer is creating a timer instance in the Softdevice itself, so any app_timer is derived from Timer0. Is this correct? If so, how do I set a timer interval (interval between two app_timer-Interrupts)? Is there any further documentation explaining the background? I did not find anything about this in the S130-Documentation of the underlying SDK v8.1.0.

Next questions are about ble_stack_init(). Where is the transmission power of the radio part set?

Does the initalization

SOFTDEVICE_HANDLER_APPSH_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, true);

mean, the Softdevice is running on Low-Frequency-Oscillator? Can I save energy by running "my" application also on LF only or do some parts (IP-Stack) need the HSE-Oscillator?

Next question: what is the influence of calling sd_app_evt_wait() on power consumption?

Last question: What is the best way to implement the long sleeping time with max. power saving? Would it be possible to wakeup the device from "System off"-Mode with a RTC-interrupt which is linked to an GPIO (in order to create an external interrupt event)?

Thank you very much for your support!

Parents
  • app_timer is using RTC1, and the softdevice is using RTC0. The softdevice uses TIMER only for radio activity, and turns this on only during the BLE event.

    TIMER => HF clock => high current consumption

    RTC => LF clock => low current consumption

    So, you don't want the TIMER to be running all the time because it uses a lot of current, that's why both the softdevice and app_timer uses the RTC peripherals. TIMER is only active when you need a very high accuracy (like the radio link).

    When you call ble_stack_init() you set which source you want for the RTC0. In the code you pasted above you tell the SD that your LF clock source is an external crystal with a minimum accuracy of 20ppm.

    nrf_drv_timer is the driver for the TIMER peripheral and has nothing to do with app_timer.

    Creating an app timer is pretty simple. It is documented here. You can do something like this:

    #define APP_TIMER_OP_QUEUE_SIZE 3                                  // Increase this by one
    #define MYTIMER_INTERVAL APP_TIMER_TICKS(100, APP_TIMER_PRESCALER) // Set the interval of your timer
    static app_timer_id_t m_mytimer_id;                                // Your timer id
    
    //Create a timeout handler:
    static void mytimer_timeout_handler(void * p_context){
        NRF_POWER->SYSTEMOFF = 1;
    }
    
    // Register your timer in the main() function:
    app_timer_create(&m_mytimer_id, APP_TIMER_MODE_REPEATED, mytimer_timeout_handler);
    app_timer_start(m_mytimer_id, MYTIMER_INTERVAL, NULL);
    

    The transmission power of the radio is set using this SD call: sd_ble_gap_tx_power_set(). Call this after ble_stack_init()

    sd_app_evt_wait() should be called in the main loop to ensure that the chip is in the lowest possible power consumption state. This is the System ON IDLE state which means that the CPU is sleeping, but other peripherals like the RTC is running so that it can wake up the CPU on f.ex. an app_timer event.

    The only mode that uses less power than System ON IDLE is System OFF mode. But then no RTCs are running, which means that the only way to wake up the chip is through an external event on a GPIO pin, LPCOMP, NFC or a reset. On other words, the chip cannot wake up itself from SysOFF.

Reply
  • app_timer is using RTC1, and the softdevice is using RTC0. The softdevice uses TIMER only for radio activity, and turns this on only during the BLE event.

    TIMER => HF clock => high current consumption

    RTC => LF clock => low current consumption

    So, you don't want the TIMER to be running all the time because it uses a lot of current, that's why both the softdevice and app_timer uses the RTC peripherals. TIMER is only active when you need a very high accuracy (like the radio link).

    When you call ble_stack_init() you set which source you want for the RTC0. In the code you pasted above you tell the SD that your LF clock source is an external crystal with a minimum accuracy of 20ppm.

    nrf_drv_timer is the driver for the TIMER peripheral and has nothing to do with app_timer.

    Creating an app timer is pretty simple. It is documented here. You can do something like this:

    #define APP_TIMER_OP_QUEUE_SIZE 3                                  // Increase this by one
    #define MYTIMER_INTERVAL APP_TIMER_TICKS(100, APP_TIMER_PRESCALER) // Set the interval of your timer
    static app_timer_id_t m_mytimer_id;                                // Your timer id
    
    //Create a timeout handler:
    static void mytimer_timeout_handler(void * p_context){
        NRF_POWER->SYSTEMOFF = 1;
    }
    
    // Register your timer in the main() function:
    app_timer_create(&m_mytimer_id, APP_TIMER_MODE_REPEATED, mytimer_timeout_handler);
    app_timer_start(m_mytimer_id, MYTIMER_INTERVAL, NULL);
    

    The transmission power of the radio is set using this SD call: sd_ble_gap_tx_power_set(). Call this after ble_stack_init()

    sd_app_evt_wait() should be called in the main loop to ensure that the chip is in the lowest possible power consumption state. This is the System ON IDLE state which means that the CPU is sleeping, but other peripherals like the RTC is running so that it can wake up the CPU on f.ex. an app_timer event.

    The only mode that uses less power than System ON IDLE is System OFF mode. But then no RTCs are running, which means that the only way to wake up the chip is through an external event on a GPIO pin, LPCOMP, NFC or a reset. On other words, the chip cannot wake up itself from SysOFF.

Children
No Data
Related