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.

Reply
  • 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.

Children
  • 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?

  • Hi,

    The EasyDMA is directly controlled by the peripherals and isn't something you would have directly control over. I agree that based on your results it seems to be a bug either in the driver, the peripheral itself or the documentation. Stopping the SAADC by sending the STOP signal is ok and does not introduce any downsides.

    best regards

    Jared

Related