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

expected current for saadc low power mode

Dear Nordic support,

I need to clarify a few points using SAADC for battery measurement - running the ble_app_proximity application without modification. I measured the power using PPK on 52840 DK and get around 1mA back ground current. After some googling, it says using Low power of SAADC should help. 

However,  after I change the config.h file to enable low power mode of SAADC, the current measured is still close to 1mA. Is this expected?

The following post (2 years old):

https://devzone.nordicsemi.com/f/nordic-q-a/27070/saadc-battery-measurement-current-consumption

suggest that the following has to be done for each read to reduce current, is it still relevant in SDK 15.2 or 15.3? What's the SAADC low power mode is for if it cannot reduce power consumption? What's the expected current using LP (low power) SAADC mode? 

Thanks,

Lichang

Parents Reply Children
  • Thanks Vidar, yes I've disabled all the logging. Please see the attached config.h file.

    Can you please adapt  the ble_app_proximity project to make it achieve a few uA and send me the whole project (config.h and other files) ? I've tried my own project and the ble_app_proximity (based on which my own project is created), neither can get current below 800uA if not using the above snippet containing nrf_drv_saadc_uninit();

    While using nrf_drv_saadc_uninit() I can achieve current below 20uA (advertising) current.

  • Not sure why I cannot attach files but here is the related section:


    // <e> NRF_LOG_ENABLED - nrf_log - Logger
    //==========================================================
    #ifndef NRF_LOG_ENABLED
    #if DEBUG
    #define NRF_LOG_ENABLED 1
    #warning "debug version got log"
    #else
    #define NRF_LOG_ENABLED 0
    #endif
    #endif

    I specifically checked if LOG is enabled or not for non-debug build, if enabled, compiler will report that. 

  • Thanks for confirming. I will try to adapt the ble_app_proximity example for you as soon as I get time. Hopefully tomorrow. Friday if not. 

  • Hi, 

    I think I found the problem; when we set up the DMA buffer with nrf_drv_saadc_buffer_convert() the SAADC gets enabled and starts drawing 1-2 mA (¨~2 without DCDC). This isn't obvious, and we have not accounted for this in the proximity example. A solution is to set up the buffer just before sampling. Double buffering isn't needed in this case. 

    I disabled advertising and set up the timer instance to trigger one sampling per second. Here's a diff showing the changes I made (SDK 15.3.0):

    diff --git a/examples/ble_peripheral/ble_app_proximity/main.c b/examples/ble_peripheral/ble_app_proximity/main.c
    index c8ae96b..b4977f4 100644
    --- a/examples/ble_peripheral/ble_app_proximity/main.c
    +++ b/examples/ble_peripheral/ble_app_proximity/main.c
    @@ -98,7 +98,7 @@
     #define APP_BLE_OBSERVER_PRIO           3                                       /**< Application's BLE observer priority. You shouldn't need to modify this value. */
     #define APP_BLE_CONN_CFG_TAG            1                                       /**< A tag identifying the SoftDevice BLE configuration. */
     
    -#define BATTERY_LEVEL_MEAS_INTERVAL     APP_TIMER_TICKS(120000)                 /**< Battery level measurement interval (ticks). This value corresponds to 120 seconds. */
    +#define BATTERY_LEVEL_MEAS_INTERVAL     APP_TIMER_TICKS(1000)                 /**< Battery level measurement interval (ticks). This value corresponds to 120 seconds. */
     
     #define MIN_CONN_INTERVAL               MSEC_TO_UNITS(500, UNIT_1_25_MS)        /**< Minimum acceptable connection interval (0.5 seconds).  */
     #define MAX_CONN_INTERVAL               MSEC_TO_UNITS(1000, UNIT_1_25_MS)       /**< Maximum acceptable connection interval (1 second). */
    @@ -157,7 +157,7 @@ BLE_DB_DISCOVERY_DEF(m_ble_db_discovery);               /**< DB discovery module
     static volatile bool m_is_high_alert_signalled;         /**< Variable to indicate whether a high alert has been signalled to the peer. */
     static volatile bool m_is_ias_present = false;          /**< Variable to indicate whether the immediate alert service has been discovered at the connected peer. */
     
    -static nrf_saadc_value_t adc_buf[2];
    +static nrf_saadc_value_t adc_buf;
     
     static ble_uuid_t m_adv_uuids[] =                       /**< Universally unique service identifiers. */
     {
    @@ -243,23 +243,11 @@ void saadc_event_handler(nrf_drv_saadc_evt_t const * p_event)
     
             adc_result = p_event->data.done.p_buffer[0];
     
    -        err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, 1);
    -        APP_ERROR_CHECK(err_code);
    -
             batt_lvl_in_milli_volts = ADC_RESULT_IN_MILLI_VOLTS(adc_result) +
                                       DIODE_FWD_VOLT_DROP_MILLIVOLTS;
             percentage_batt_lvl = battery_level_in_percent(batt_lvl_in_milli_volts);
     
    -        err_code = ble_bas_battery_level_update(&m_bas, percentage_batt_lvl, BLE_CONN_HANDLE_ALL);
    -        if ((err_code != NRF_SUCCESS) &&
    -            (err_code != NRF_ERROR_INVALID_STATE) &&
    -            (err_code != NRF_ERROR_RESOURCES) &&
    -            (err_code != NRF_ERROR_BUSY) &&
    -            (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
    -           )
    -        {
    -            APP_ERROR_HANDLER(err_code);
    -        }
    +        NRF_LOG_INFO("Battery voltage %d", batt_lvl_in_milli_volts);
         }
     }
     
    @@ -289,12 +277,6 @@ static void adc_configure(void)
             NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_VDD);
         err_code = nrf_drv_saadc_channel_init(0, &config);
         APP_ERROR_CHECK(err_code);
    -
    -    err_code = nrf_drv_saadc_buffer_convert(&adc_buf[0], 1);
    -    APP_ERROR_CHECK(err_code);
    -
    -    err_code = nrf_drv_saadc_buffer_convert(&adc_buf[1], 1);
    -    APP_ERROR_CHECK(err_code);
     }
     
     
    @@ -311,6 +293,8 @@ static void battery_level_meas_timeout_handler(void * p_context)
         UNUSED_PARAMETER(p_context);
     
         ret_code_t err_code;
    +    err_code = nrf_drv_saadc_buffer_convert(&adc_buf, 1);
    +    APP_ERROR_CHECK(err_code);
         err_code = nrf_drv_saadc_sample();
         APP_ERROR_CHECK(err_code);
     }
    @@ -1100,9 +1084,12 @@ int main(void)
         conn_params_init();
         peer_manager_init();
     
    +    uint32_t err_code = app_timer_start(m_battery_timer_id, BATTERY_LEVEL_MEAS_INTERVAL, NULL);
    +    APP_ERROR_CHECK(err_code);
    +
         // Start execution.
         NRF_LOG_INFO("Proximity example started.");
    -    advertising_start(erase_bonds);
    +    //advertising_start(erase_bonds);
         tx_power_set();
     
         // Enter main loop.
    diff --git a/examples/ble_peripheral/ble_app_proximity/pca10040/s132/config/sdk_config.h b/examples/ble_peripheral/ble_app_proximity/pca10040/s132/config/sdk_config.h
    index 4f0bb86..42bd9f8 100644
    --- a/examples/ble_peripheral/ble_app_proximity/pca10040/s132/config/sdk_config.h
    +++ b/examples/ble_peripheral/ble_app_proximity/pca10040/s132/config/sdk_config.h
    @@ -7472,7 +7472,7 @@
     // <e> NRF_LOG_BACKEND_UART_ENABLED - nrf_log_backend_uart - Log UART backend
     //==========================================================
     #ifndef NRF_LOG_BACKEND_UART_ENABLED
    -#define NRF_LOG_BACKEND_UART_ENABLED 1
    +#define NRF_LOG_BACKEND_UART_ENABLED 0
     #endif
     // <o> NRF_LOG_BACKEND_UART_TX_PIN - UART TX pin 
     #ifndef NRF_LOG_BACKEND_UART_TX_PIN
    @@ -7517,7 +7517,7 @@
     // <e> NRF_LOG_ENABLED - nrf_log - Logger
     //==========================================================
     #ifndef NRF_LOG_ENABLED
    -#define NRF_LOG_ENABLED 1
    +#define NRF_LOG_ENABLED 0
     #endif
     // <h> Log message pool - Configuration of log message pool
     
    

    And the resulting power trace (captured with the power profiler kit):

       

  • A solution is to set up the buffer just before sampling. Double buffering isn't needed in this case.

    Hi, 

    How should I do, when I want use PPI to trigger the SAADC sample.

    1. In function "adc_configure", you comment out the "nrf_drv_saadc_buffer_convert", and move it into the ISR function.
    2. In PPI mode, the sample-task will be auto triggered by timeout-event, instead of ISR;
    3. But "nrf_drv_saadc_buffer_convert" should be call before start sample.
    4. How should I do it, in PPI mode;

    My platform:

    • nRF5_SDK_17.0.2
    • DK 52833

    I want reduce the current consumption in PPI mode.

    Thanks.

Related