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

Sleep current is high after using SAADC

Hi,

There is a similar case:

High power consumption in sleep mode after using SAADC

But I am using the SAADC driver version 2.0 because the oversampling feature is only supported in new driver, low power mode is not supported.

My environments:

nRF52840, the sdk version is 17.02, s140 version 7.2.0. Because we need the oversample feature in SAADC, so we are using SAADC driver version 2.0. When there are two channels sampled, the sleep power current is very high, more than 600uA, but if only one channel is sampled ,the sleep current is low, only 4uA. UART is also disabled.

Please help on this. Thanks

Regards

Roy Huang

Parents
  • Here is my code to reproduce this issue and I changed it from ble_peripheral ble_app_blinky example in SDK 17.02

    #define NUM_ADC_CHANNELS 1
    // #define NUM_ADC_CHANNELS 2
    
    static nrf_saadc_value_t samples[NUM_ADC_CHANNELS];
    APP_TIMER_DEF(m_sample_timer);
    
    static uint8_t m_event_type;
    
    static void UninitAdc(void * event_data, uint16_t event_size)
    {
    
        ASSERT(*(uint8_t*)event_data == 0x1);
        NRF_LOG_DEBUG("Uninit ADC");
    
        nrfx_saadc_uninit();
        NRF_SAADC->INTENCLR = (SAADC_INTENCLR_END_Clear << SAADC_INTENCLR_END_Pos);
        NVIC_ClearPendingIRQ(SAADC_IRQn);
    }
    
    
    static void SaadcHandler(nrfx_saadc_evt_t const * p_event)
    {
        if (p_event->type == NRFX_SAADC_EVT_DONE)
        {
            ASSERT(p_event->data.done.size == NUM_ADC_CHANNELS);
    
            NRF_LOG_INFO("%d %d", *(uint16_t *)p_event->data.done.p_buffer, *(uint16_t *)(p_event->data.done.p_buffer + 2));
    
            m_event_type = 0x1;
            ret_code_t err_code = app_sched_event_put(&m_event_type, sizeof(m_event_type), UninitAdc);
            APP_ERROR_CHECK(err_code);
        }
    }
    
    static void SampleHandler(void * p_context)
    {
        uint8_t adc_channel_mask;
        ret_code_t err_code;
    
    #if (NUM_ADC_CHANNELS == 1)
        nrfx_saadc_channel_t channels[NUM_ADC_CHANNELS] = {NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN3, 0)};
    #else
        nrfx_saadc_channel_t channels[NUM_ADC_CHANNELS] = {NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN3, 0),
                                                           NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN2, 1)};
    #endif
    
        /* Use gain 1/4 for all conversions */
        for (uint8_t i = 0; i < NUM_ADC_CHANNELS; ++i)
        {
            channels[i].channel_config.gain = NRF_SAADC_GAIN1_4;
        }
    
        err_code = nrfx_saadc_init(NRFX_SAADC_CONFIG_IRQ_PRIORITY);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrfx_saadc_channels_config(channels, NUM_ADC_CHANNELS);
        APP_ERROR_CHECK(err_code);
    
        for (uint8_t i = 0; i < NUM_ADC_CHANNELS; ++i)
        {
            adc_channel_mask |= 1 << i;
        }
    
        err_code = nrfx_saadc_simple_mode_set(adc_channel_mask,
                                              NRF_SAADC_RESOLUTION_12BIT,
                                              NRF_SAADC_OVERSAMPLE_16X,
                                              SaadcHandler);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrfx_saadc_buffer_set(samples, NUM_ADC_CHANNELS);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrfx_saadc_mode_trigger();
        APP_ERROR_CHECK(err_code);
        
        NRF_LOG_INFO("Sample started");
    }
    
    void SampleInit(void)
    {
        ret_code_t err_code;
    
        app_timer_create(&m_sample_timer,
                            APP_TIMER_MODE_REPEATED,
                            SampleHandler);
    
        err_code = app_timer_start(
            m_sample_timer,
            APP_TIMER_TICKS(2000), NULL);
    }
    
    /**@brief Function for application main entry.
     */
    int main(void)
    {
        // Initialize.
        log_init();
        // leds_init();
        timers_init();
        // buttons_init();
        power_management_init();
        APP_SCHED_INIT(1, 10);
        ble_stack_init();
        gap_params_init();
        gatt_init();
        services_init();
        advertising_init();
        conn_params_init();
    
        // Start execution.
        NRF_LOG_INFO("Blinky example started.");
        advertising_start();
    
        SampleInit();
    
        // Enter main loop.
        for (;;)
        {
            idle_state_handle();
            app_sched_execute();
        }
    }
    

    Below is the current curve from PPK2 when only one channel is sampled, advertising interval is about 800ms. Every 2 seconds, SAADC is enabled, after sampling, SAADC is disabled. It works fine.

    Current curve from PPK2 when two channels are sampled.

    I attached the code which is modified from the ble_app_blinky example and can reproduce this phenomenon.

    Unzip it to directory examples\ble_peripheral.

    There is an macro NUM_ADC_CHANNELS at line 564 in file main.c. When it is defined as 1, only one channel is sampled; when defined as 2, two channel are sampled.

    ble_app_saadc_sample.7z

Reply
  • Here is my code to reproduce this issue and I changed it from ble_peripheral ble_app_blinky example in SDK 17.02

    #define NUM_ADC_CHANNELS 1
    // #define NUM_ADC_CHANNELS 2
    
    static nrf_saadc_value_t samples[NUM_ADC_CHANNELS];
    APP_TIMER_DEF(m_sample_timer);
    
    static uint8_t m_event_type;
    
    static void UninitAdc(void * event_data, uint16_t event_size)
    {
    
        ASSERT(*(uint8_t*)event_data == 0x1);
        NRF_LOG_DEBUG("Uninit ADC");
    
        nrfx_saadc_uninit();
        NRF_SAADC->INTENCLR = (SAADC_INTENCLR_END_Clear << SAADC_INTENCLR_END_Pos);
        NVIC_ClearPendingIRQ(SAADC_IRQn);
    }
    
    
    static void SaadcHandler(nrfx_saadc_evt_t const * p_event)
    {
        if (p_event->type == NRFX_SAADC_EVT_DONE)
        {
            ASSERT(p_event->data.done.size == NUM_ADC_CHANNELS);
    
            NRF_LOG_INFO("%d %d", *(uint16_t *)p_event->data.done.p_buffer, *(uint16_t *)(p_event->data.done.p_buffer + 2));
    
            m_event_type = 0x1;
            ret_code_t err_code = app_sched_event_put(&m_event_type, sizeof(m_event_type), UninitAdc);
            APP_ERROR_CHECK(err_code);
        }
    }
    
    static void SampleHandler(void * p_context)
    {
        uint8_t adc_channel_mask;
        ret_code_t err_code;
    
    #if (NUM_ADC_CHANNELS == 1)
        nrfx_saadc_channel_t channels[NUM_ADC_CHANNELS] = {NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN3, 0)};
    #else
        nrfx_saadc_channel_t channels[NUM_ADC_CHANNELS] = {NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN3, 0),
                                                           NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN2, 1)};
    #endif
    
        /* Use gain 1/4 for all conversions */
        for (uint8_t i = 0; i < NUM_ADC_CHANNELS; ++i)
        {
            channels[i].channel_config.gain = NRF_SAADC_GAIN1_4;
        }
    
        err_code = nrfx_saadc_init(NRFX_SAADC_CONFIG_IRQ_PRIORITY);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrfx_saadc_channels_config(channels, NUM_ADC_CHANNELS);
        APP_ERROR_CHECK(err_code);
    
        for (uint8_t i = 0; i < NUM_ADC_CHANNELS; ++i)
        {
            adc_channel_mask |= 1 << i;
        }
    
        err_code = nrfx_saadc_simple_mode_set(adc_channel_mask,
                                              NRF_SAADC_RESOLUTION_12BIT,
                                              NRF_SAADC_OVERSAMPLE_16X,
                                              SaadcHandler);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrfx_saadc_buffer_set(samples, NUM_ADC_CHANNELS);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrfx_saadc_mode_trigger();
        APP_ERROR_CHECK(err_code);
        
        NRF_LOG_INFO("Sample started");
    }
    
    void SampleInit(void)
    {
        ret_code_t err_code;
    
        app_timer_create(&m_sample_timer,
                            APP_TIMER_MODE_REPEATED,
                            SampleHandler);
    
        err_code = app_timer_start(
            m_sample_timer,
            APP_TIMER_TICKS(2000), NULL);
    }
    
    /**@brief Function for application main entry.
     */
    int main(void)
    {
        // Initialize.
        log_init();
        // leds_init();
        timers_init();
        // buttons_init();
        power_management_init();
        APP_SCHED_INIT(1, 10);
        ble_stack_init();
        gap_params_init();
        gatt_init();
        services_init();
        advertising_init();
        conn_params_init();
    
        // Start execution.
        NRF_LOG_INFO("Blinky example started.");
        advertising_start();
    
        SampleInit();
    
        // Enter main loop.
        for (;;)
        {
            idle_state_handle();
            app_sched_execute();
        }
    }
    

    Below is the current curve from PPK2 when only one channel is sampled, advertising interval is about 800ms. Every 2 seconds, SAADC is enabled, after sampling, SAADC is disabled. It works fine.

    Current curve from PPK2 when two channels are sampled.

    I attached the code which is modified from the ble_app_blinky example and can reproduce this phenomenon.

    Unzip it to directory examples\ble_peripheral.

    There is an macro NUM_ADC_CHANNELS at line 564 in file main.c. When it is defined as 1, only one channel is sampled; when defined as 2, two channel are sampled.

    ble_app_saadc_sample.7z

Children
No Data
Related