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

Proximity Example - Power profiling sits at baseline 2.7mA and does not sleep between advertisements

Hi,

My stack is

  • s112
  • SDK 15.3
  • Segger
  • nrfConnect
  • nrf52832 DK
  • Power profiler kit connected via USB to my MAC to get the traces to run.
  • CR2032 batter removed
  • SB9 solder jumper cut

I have my code effectively running on the uP as I need it, and I now have  the Power Profiling Kit so I can start to power optimise.  I have modified the ble_app_proximity example but when running it, it sits at a baseline of 2.7mA while in advertising mode and when connected to the central.

To analyse my first step was to flash the board with the unmodified ble_app_proximity to see if it was my code.

The unmodified code gives a trace below which also sits at 2.7mA average also

The mystery deepens however. In my code I have PIN 16 wired to ground and when it goes high (switch open) I send the chip into sd_power_system_off();

This works elegantly and I can see that we drop to 6uA or thereabouts when the switch os opened. Just as it should.

So it leads me to wonder why the 2.3mA is the baseline when advertising and when connected. So I am a little stumped and perhaps I am missing something simple but the 2.3mA is going to drain my CR2032 very fast so any tips on how I get the uP to sleep between advertisements? Also I am looking to power optimise by extending the advertising interval and raising the slave latency. But the 2.7mA baseline dwarfs any advantages chosen here. 

I've found this thread leading me to think it is my technique which is highly likely, but there is no answer on the thread. It just ends with no resolution. I've power cycled the board multiple times after flashing it.

I've found this thread leading me to understand (incorrectly?)  that the softdevice prevents the low power state from ever firing?

Looking at the code it appears that nrf_pwr_mgmt_run() never goes to sleep as the "else" statement is never run, as I am running a softdevice. 

void nrf_pwr_mgmt_run(void)
{
    PWR_MGMT_FPU_SLEEP_PREPARE();
    PWR_MGMT_SLEEP_LOCK_ACQUIRE();
    PWR_MGMT_CPU_USAGE_MONITOR_SECTION_ENTER();
    PWR_MGMT_DEBUG_PIN_SET();

    // Wait for an event.
#ifdef SOFTDEVICE_PRESENT
    if (nrf_sdh_is_enabled())
    {
        ret_code_t ret_code = sd_app_evt_wait();
        ASSERT((ret_code == NRF_SUCCESS) || (ret_code == NRF_ERROR_SOFTDEVICE_NOT_ENABLED));
        UNUSED_VARIABLE(ret_code);
    }
    else
#endif // SOFTDEVICE_PRESENT
    {
        // Wait for an event.
        NRF_LOG_INFO("Got to here");
        NRF_LOG_FINAL_FLUSH();
        __WFE();
        // Clear the internal event register.
        __SEV();
        __WFE();
    }

    PWR_MGMT_DEBUG_PIN_CLEAR();
    PWR_MGMT_CPU_USAGE_MONITOR_SECTION_EXIT();
    PWR_MGMT_SLEEP_LOCK_RELEASE();
}

My setup. I connect the USB, fire teh mrfConnect power profiler on the laptop, power cycle the DK board. The yellow wire is my "switch" tying pin 16 to ground. On open the board goes to sleep effectively

Any help appreciated.

Best,

DW

Parents
  • Hi,

    I believe this is caused by the SAADC that is used for battery voltage measurement in the example.

    Please try enabling low power mode by setting the following in your sdk_config.h file:

    // <q> SAADC_CONFIG_LP_MODE  - Enabling low power mode
     
    
    #ifndef SAADC_CONFIG_LP_MODE
    #define SAADC_CONFIG_LP_MODE 1
    #endif

    Best regards,
    Jørgen

  • Try to also disable the logger:

    // <e> NRF_LOG_ENABLED - nrf_log - Logger
    //==========================================================
    #ifndef NRF_LOG_ENABLED
    #define NRF_LOG_ENABLED 0
    #endif

  • Once again thank you. The power profile kit is now averaging 230uA. Can I disable other things I think I'm just not using scuh as the the UART, CRYPTO, CLOCK peripheral driver, Peripheral Resource Sharing module, FPRINTF module?

  • If it is not initialized in the code, those peripherals should not cause increased current consumption from being enabled in the sdk_config.h file.

    I would recommend that you check if your average current is in line with the expected currents from the Online Power Profiler.

    Enabling the DCDC converter would also reduce the average current quite a lot. 

  • Once again thank you Jørgen,

    I have implemented the 

        NRF_POWER->DCDCEN = 1;

    to select the lower power use of DCDC and understand that if it drops below 2.1v I should switch it off. I can see that the individual advertising spikes are lower, which is great. However I was still at 230uA. So for the past evening I thought I must, by process of elimination, work out what is doing it. So I started completely fresh, with the ble_app_template app and added my services one by one, testing the power profile as each service was added. The lls and bas services were added and power behaved beautifully. It is when I added my GPIOTE event, that the current runs high. 

    The specific lines of code that do it are in the gpio initialisation done in switch_int()

    static void switch_init(void)
    {
        ret_code_t err_code;
    
    	//Initialize gpiote module
        //NRF_LOG_INFO("Initialize gpiote module");
        if(!nrf_drv_gpiote_is_init())
            {
            err_code = nrf_drv_gpiote_init();
            APP_ERROR_CHECK(err_code);  
            }    
        //Configure sense input pin
        nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_LOTOHI(false);                                //Configure to generate interrupt and go to system_off on pin signal high. "false" means that gpiote will use the PORT event, which is low power, i.e. does not add any noticable current consumption (<<1uA). Setting this to "true" will make the gpiote module use GPIOTE->IN events which add ~8uA for nRF52 and ~1mA for nRF51.
        in_config.pull = NRF_GPIO_PIN_PULLUP;                                                                       //Configure pullup for input pin to prevent it from floating. Pin is pulled down when button is pressed on nRF5x-DK boards, see figure two in http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52/dita/nrf52/development/dev_kit_v1.1.0/hw_btns_leds.html?cp=2_0_0_1_4		
        err_code = nrf_drv_gpiote_in_init(SWITCH_PIN, &in_config, in_pin_debounce_handler);  				//Initialize the pin with interrupt handler in_pin_handler
    
        //NRF_LOG_INFO("Intiate the PIN to detect switch opening: Error code on gpiote_in_init is %d..", err_code);
        //APP_ERROR_CHECK(err_code);                                                          			//Check potential error
        //nrf_drv_gpiote_in_event_enable(SWITCH_PIN, true);                                                           //Enable event and interrupt for the wakeup pin
    }

    Note: I have not enabled the switch detection in the final line, as it is specifically the nrf_drv_gpiote_in_init command, configured as I have configured it above, that sends the current usage up.

    I understood that by setting GPIOTE_CONFIG_IN_SENSE_LOTOHI(false) to "false" I was using a low power PORT event. 

    I call this gpio initialisation from main

    /**@brief Function for application main entry.
     */
    int main(void)
    {
        bool erase_bonds;
    
        // Initialize.
        
        NRF_POWER->DCDCEN = 1;
        log_init();
        timers_init();
        //buttons_leds_init(&erase_bonds);
        power_management_init();
        ble_stack_init();
        gap_params_init();
        gatt_init();
        advertising_init();
        services_init();
        conn_params_init();
        peer_manager_init();
    
        // Start execution.
        NRF_LOG_INFO("Template example started.");
        application_timers_start();
        tx_power_set();
        advertising_start(erase_bonds);
        switch_init();
    
        // Enter main loop.
        for (;;)
        {
            idle_state_handle();
        }
    }

    Looking further tonight and analysing the Power Profiler Kit, by running switch_init() the 230uA level is I think caused by something  triggering every 25ms resulting in the jagged baseline?

    Have also used the online power profiler kindly provided by Nordic

    using the variables of 

    • voltage : 3
    • DCDC regulator now enabled
    • LF Clock on the development board is External crystal as set in the sdk_config.h
      • #define NRF_SDH_CLOCK_LF_SRC 1
      • #define NRFX_CLOCK_CONFIG_LF_SRC 1
      • #define CLOCK_CONFIG_LF_SRC 1
    • Advertising interval is 2.022 seconds
      • #define APP_ADV_INTERVAL                3236                                    /**< The advertising interval 2.022 seconds. */
    • TX Payload I have yet to calculate so I've maxed it out to 31

    The anticipated current should be 7.8uA. It's definitely this 25ms tick that my code has which is creating the unwanted 230uA. As I added the lls and bas the baseline was smooth

    Any advice gratefully received. 


    Best DW

  • The size of the current sounds like it could correspond to a current flowing through your pullup resistor (~13kOhm, which would give ~230 uA @ 3.0V).

    By default, the DK has BUTTON4 connected to P0.16. Have you connected anything else to the pin? The switch on the DK is active low.

  • Thank you Jørgen. Everything has fallen into place. I should be able to reduce that current draw on PIN 16 as per the discussion board here

    Testing tonight!

    Jørgen - Could I reach out to you with another question, privately?

Reply Children
Related