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

nrfx_saadc_sample_convert causes static 800 uA current

Hi,

I have an application that uses the nrfx_saadc driver to measure voltages. One init-function that sets up the saadc and two channels, and one sample-function that calls 

nrfx_saadc_sample_convert to perform the actual sampling. After the call the idle consumption rises by about 800 uA.
This is my current code to get rid of the problem:
void adc_init(void)
{
    nrf_saadc_channel_config_t bat_ch_config = NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
    nrf_saadc_channel_config_t temp_ch_config = NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
    nrfx_saadc_config_t saadc_config = NRFX_SAADC_DEFAULT_CONFIG;
    nrfx_err_t err_code;

    /* Battery divider is 147k, needs longer acquisition time */
    bat_ch_config.acq_time = NRF_SAADC_ACQTIME_3US;

    err_code = nrfx_saadc_init(&saadc_config, on_saadc_evt);
    APP_ERROR_CHECK(err_code);

    err_code = nrfx_saadc_channel_init(ADC_CH_BAT_SENSE, &bat_ch_config);
    APP_ERROR_CHECK(err_code);

    err_code = nrfx_saadc_channel_init(ADC_CH_TEMP_SENSE, &temp_ch_config);
    APP_ERROR_CHECK(err_code);
}

uint32_t adc_single_conversion(adc_ch_t channel)
{
    nrf_saadc_value_t value = 0;
    uint32_t mV;

    nrfx_err_t err_code;

    err_code = nrfx_saadc_sample_convert(channel, &value);
    APP_ERROR_CHECK(err_code);

    // Without these four lines the base consumption rises by 800 uA
    nrfx_saadc_channel_uninit(ADC_CH_BAT_SENSE);
    nrfx_saadc_channel_uninit(ADC_CH_TEMP_SENSE);
    nrfx_saadc_uninit();
    adc_init();

    mV = value < 0 ? 0 : value;

    /* Convert to millivolt */
    mV *= 1200; // Bandgap reference
    mV *= 3;    // Voltage prescaler
    mV /= 1024; // 10-bit measurement

    NRF_LOG_INFO("ADC ch %d: %d mV (raw: %d)", channel, mV, value);

    return mV;
}
Can I do something else to restore the idle consumption? Re-configuring the ADC after each conversion feels like a bad hack.
Code runs on nRF52810 with SDK 15.3.0 and SD S112 v6.1.1.
Parents
  • I suggest that you try to turn off saadc peripherals before the device goes idle by using “nrf_drv_saadc_abort“ and ”nrf_drv_saadc_uninit”.

  • Abort will not do anything since it checks if the driver is in idle state. And normally peripherals keep their low power state even in initialized mode. It seems like a strange workaround. I get the feeling that it is a bug in the nrfx_saadc driver.

    I just tested calling:

    err_code = nrfx_saadc_sample_convert(channel, &value);
    APP_ERROR_CHECK(err_code);
    
    nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);
    nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP);
    while (!nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED));

    And that also solves the problem. So I think the driver should run the stop task when it is done with the sampling.

  • Hi,

    I'm suspecting that the reason for the high current consumption is due to the EasyDMA. The EasyDMA should have stopped consuming the current after nrfx_saadc_sample_convert has been called as it waits for the END event, I'm not sure from the code that you posted why you're seeing the high current consumption. Nevertheless, we have a low power SAADC example that is worth checking out here.

    regards

    Jared

  • How do I stop the EasyDMA? The sample you provided is using event/irq based sampling, the way the rest of my code is setup it makes more sense for me to do blocking sampling.

    I'm not sure about the EasyDMA-consumption. It matches the SAADC-consumption more. I also realized that I'm measuring current at 3.75 V before a buck regulator with the nRF running at 3V, so the 800 uA is likely closer to 1 mA.

    You also write that the EasyDMA should have stopped on the END-event. But the SAADC itself would still be running since the nrfx_saadc_sample_convert only calls START but not STOP. And in that case it makes sense that I would need to trigger the STOP task externally since the nrfx_saadc driver does not do it by itself.

    Do you think there is any downside to stopping the SAADC "manually" when the conversion is done?

Reply
  • How do I stop the EasyDMA? The sample you provided is using event/irq based sampling, the way the rest of my code is setup it makes more sense for me to do blocking sampling.

    I'm not sure about the EasyDMA-consumption. It matches the SAADC-consumption more. I also realized that I'm measuring current at 3.75 V before a buck regulator with the nRF running at 3V, so the 800 uA is likely closer to 1 mA.

    You also write that the EasyDMA should have stopped on the END-event. But the SAADC itself would still be running since the nrfx_saadc_sample_convert only calls START but not STOP. And in that case it makes sense that I would need to trigger the STOP task externally since the nrfx_saadc driver does not do it by itself.

    Do you think there is any downside to stopping the SAADC "manually" when the conversion is done?

Children
Related