BM833 energy saving

Dear forum,

I want to achive low energy consumption for a BM833 (with crystal).

From the following thread, I could deduct, that running the softdevice, an average of 300+ uA is required:

https://devzone.nordicsemi.com/f/nordic-q-a/10425/possible-to-shutdown-soft-device-or-ble-after-init-to-achieve-low-power

Now I could follow the instructions to shutdown the HF-Clock, as suggested, but I could read:

"The SoftDevice does not stop the LFCLK when it disables because other modules may use it (like app_timer)."

This, in reverse, could mean that stopping LFCLK might render the app_timer unusable?

I need to be able to "relaunch" the softdevice (S132) periodically to achieve periodic transmissions (send and/or receive) and currently, I'm using also timers to read from peripherals.

How would I have to proceed to achieve that goal when, at the same time, switching off the LFCLK to achieve 2uA consumption?

Can anyone give a code example?

Best regards,

Richard

Parents Reply Children
  • Hello Vidar,

    thank you for the initial answere.

    Let's assume I have a 32k crystal, then what should I do:

    known places for settings:

    ~\components\softdevice\common\nrf_sdh.c
    
    //without crystal
    nrf_clock_lf_cfg_t const clock_lf_cfg =
        {
            .source       = 0,
            .rc_ctiv      = 16,
            .rc_temp_ctiv = 2,
            .accuracy     = 7
        }
    
    
    //setting with soldered crystal, e.g. nRF52833 DK
    nrf_clock_lf_cfg_t const clock_lf_cfg =
        {
            .source       = NRF_SDH_CLOCK_LF_SRC,
            .rc_ctiv      = NRF_SDH_CLOCK_LF_RC_CTIV,
            .rc_temp_ctiv = NRF_SDH_CLOCK_LF_RC_TEMP_CTIV,
            .accuracy     = NRF_SDH_CLOCK_LF_ACCURACY
        }
    


    And in my main.c code (dependent on crystal availability), I have:

        #if CRYSTAL_ENABLED == 1
        NRF_CLOCK->LFCLKSRC            = (CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos);
        #else
        NRF_CLOCK->LFCLKSRC            = (CLOCK_LFCLKSRC_SRC_Synth << CLOCK_LFCLKSRC_SRC_Pos);
        #endif

    Is that code OK to get LFCLK to use the crystal as source?

    What do I need to do to switch off HFCLK and get the low-power mode?

    Best regards,

    Richard

  • Hello Richard,

    For LFXO you can use the following configuration:

    / </h> 
    //==========================================================
    
    // <h> Clock - SoftDevice clock configuration
    
    //==========================================================
    // <o> NRF_SDH_CLOCK_LF_SRC  - SoftDevice clock source.
     
    // <0=> NRF_CLOCK_LF_SRC_RC 
    // <1=> NRF_CLOCK_LF_SRC_XTAL 
    // <2=> NRF_CLOCK_LF_SRC_SYNTH 
    
    #ifndef NRF_SDH_CLOCK_LF_SRC
    #define NRF_SDH_CLOCK_LF_SRC 1
    #endif
    
    // <o> NRF_SDH_CLOCK_LF_RC_CTIV - SoftDevice calibration timer interval. 
    #ifndef NRF_SDH_CLOCK_LF_RC_CTIV
    #define NRF_SDH_CLOCK_LF_RC_CTIV 0
    #endif
    
    // <o> NRF_SDH_CLOCK_LF_RC_TEMP_CTIV - SoftDevice calibration timer interval under constant temperature. 
    // <i> How often (in number of calibration intervals) the RC oscillator shall be calibrated
    // <i>  if the temperature has not changed.
    
    #ifndef NRF_SDH_CLOCK_LF_RC_TEMP_CTIV
    #define NRF_SDH_CLOCK_LF_RC_TEMP_CTIV 0
    #endif
    
    // <o> NRF_SDH_CLOCK_LF_ACCURACY  - External clock accuracy used in the LL to compute timing.
     
    // <0=> NRF_CLOCK_LF_ACCURACY_250_PPM 
    // <1=> NRF_CLOCK_LF_ACCURACY_500_PPM 
    // <2=> NRF_CLOCK_LF_ACCURACY_150_PPM 
    // <3=> NRF_CLOCK_LF_ACCURACY_100_PPM 
    // <4=> NRF_CLOCK_LF_ACCURACY_75_PPM 
    // <5=> NRF_CLOCK_LF_ACCURACY_50_PPM 
    // <6=> NRF_CLOCK_LF_ACCURACY_30_PPM 
    // <7=> NRF_CLOCK_LF_ACCURACY_20_PPM 
    // <8=> NRF_CLOCK_LF_ACCURACY_10_PPM 
    // <9=> NRF_CLOCK_LF_ACCURACY_5_PPM 
    // <10=> NRF_CLOCK_LF_ACCURACY_2_PPM 
    // <11=> NRF_CLOCK_LF_ACCURACY_1_PPM 
    
    #ifndef NRF_SDH_CLOCK_LF_ACCURACY
    #define NRF_SDH_CLOCK_LF_ACCURACY 7
    #endif
    

    And for LFRC you can use this one (notice that the accuracy is changed to 500 ppm. This is required when using the LFRC):

    // </h> 
    //==========================================================
    
    // <h> Clock - SoftDevice clock configuration
    
    //==========================================================
    // <o> NRF_SDH_CLOCK_LF_SRC  - SoftDevice clock source.
     
    // <0=> NRF_CLOCK_LF_SRC_RC 
    // <1=> NRF_CLOCK_LF_SRC_XTAL 
    // <2=> NRF_CLOCK_LF_SRC_SYNTH 
    
    #ifndef NRF_SDH_CLOCK_LF_SRC
    #define NRF_SDH_CLOCK_LF_SRC 0
    #endif
    
    // <o> NRF_SDH_CLOCK_LF_RC_CTIV - SoftDevice calibration timer interval. 
    #ifndef NRF_SDH_CLOCK_LF_RC_CTIV
    #define NRF_SDH_CLOCK_LF_RC_CTIV 16
    #endif
    
    // <o> NRF_SDH_CLOCK_LF_RC_TEMP_CTIV - SoftDevice calibration timer interval under constant temperature. 
    // <i> How often (in number of calibration intervals) the RC oscillator shall be calibrated
    // <i>  if the temperature has not changed.
    
    #ifndef NRF_SDH_CLOCK_LF_RC_TEMP_CTIV
    #define NRF_SDH_CLOCK_LF_RC_TEMP_CTIV 2
    #endif
    
    // <o> NRF_SDH_CLOCK_LF_ACCURACY  - External clock accuracy used in the LL to compute timing.
     
    // <0=> NRF_CLOCK_LF_ACCURACY_250_PPM 
    // <1=> NRF_CLOCK_LF_ACCURACY_500_PPM 
    // <2=> NRF_CLOCK_LF_ACCURACY_150_PPM 
    // <3=> NRF_CLOCK_LF_ACCURACY_100_PPM 
    // <4=> NRF_CLOCK_LF_ACCURACY_75_PPM 
    // <5=> NRF_CLOCK_LF_ACCURACY_50_PPM 
    // <6=> NRF_CLOCK_LF_ACCURACY_30_PPM 
    // <7=> NRF_CLOCK_LF_ACCURACY_20_PPM 
    // <8=> NRF_CLOCK_LF_ACCURACY_10_PPM 
    // <9=> NRF_CLOCK_LF_ACCURACY_5_PPM 
    // <10=> NRF_CLOCK_LF_ACCURACY_2_PPM 
    // <11=> NRF_CLOCK_LF_ACCURACY_1_PPM 
    
    #ifndef NRF_SDH_CLOCK_LF_ACCURACY
    #define NRF_SDH_CLOCK_LF_ACCURACY 1
    #endif

    RichardHdrd said:
    What do I need to do to switch off HFCLK and get the low-power mode?

    You don't need to do anything. The Softdevice turns off the HFXO after every RADIO event.

    RichardHdrd said:
    And in my main.c code (dependent on crystal availability), I have:

    The Softdevice enables the clock with the configuration given in sdk_config.h so you usually don't have to start the clock yourself in main.

    Best regards,

    Vidar

  • Hello Vidar,

    Thank you for your advice. I adjusted the sdk_config.h as suggested by you, but I keep measuring the same current average of 300+ uA.

    I then tried to modify:

    //old energy idle
    static void idle_state_handle(void)
    {
        if (NRF_LOG_PROCESS() == false)
        {
            nrf_pwr_mgmt_run();
        }
    }
    
    //new energy idle
    static void idle_state_handle(void)
    {
        if (NRF_LOG_PROCESS() == false)
        {
            if (nrf_sdh_is_enabled())
            {
                nrf_sdh_suspend();
                nrf_sdh_disable_request();
                //NRF_CLOCK->TASKS_HFCLKSTOP = 1;
            }
            __WFE();
            if (!nrf_sdh_is_enabled())
            {
                //NRF_CLOCK->TASKS_HFCLKSTART = 1;
                nrf_sdh_enable_request();
                nrf_sdh_evts_poll();
            }
        }
    }

    But this did not only increase the required current, but also rendered all my timers inactive.

    BTW timers, this is the way I implemented them:

    main.c:
    
    APP_TIMER_DEF(m_bsp_tmr1);
    
    int main(void)
    {
        (...)
        uint32_t timeout_ticks1 = APP_TIMER_TICKS(2000);
        err_code = app_timer_create(&m_bsp_tmr1, APP_TIMER_MODE_REPEATED, m_timer_handler1);
        APP_ERROR_CHECK(err_code);
        app_timer_start(m_bsp_tmr1, timeout_ticks1, NULL);
        (...)
        for (;;)
        {
            idle_state_handle();
            NRF_LOG_INFO("Active");
            NRF_LOG_FLUSH();
        }
    }

    So maybe there is something additional that needs to be set, cleared or considered to get to a low current consumption while keeping timers active?

    Best regards,

    Richard

  • Hi Richard,

    There is no benefit to enabling and disabling the Softdevice as shown in your code snippet if you are going to keep the LF clock active anyway. I suggest you enable the Softdevice and use the idle_state_handle() as in our other SDK BLE examples.

    Best regards,

    Vidar

  • Hello Vidar,

    Sorry to continue the thread from here, but the forum doesn't allow me to respond from your last suggestion ("enable the Softdevice and use the idle_state_handle().").

    If I do, as you suggest, with all LFRC clock-configuration as suggested, I see an average current of 300+ uA (the same 300+ uA that were observed, before I changed the clock settings in sdk_config.h for LFRC, as you suggested below).

    So, the question still is, how to get the current down to the famous 2.2uA (or at least significantly below 300+ uA)?

    Best regards,

    Richard

Related