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

power consumption increases 1.1mA after first ADC sample

Hello,

I am experiencing a power issue after the first ADC sample is triggered. Sampling 2 ADC channels using PPI and TIMER as the triggering mechanism. Here is a capture using PPK2.

It is alright to have a spike in power but in this case, once the power increases it never decreases.

Is there a way to fix this?

TIA

  • Hi, 

    The increase in current comes from the EasyDMA being enabled and drawing current once the SAADC START task is triggered.

    In order to reduce the current, you can only have a buffer size equal to the number of active channels enabled, and not use the double-buffering feature.

    There is a low-power mode in the SAADC driver that you can try to enable, but we have previously seen some issues with this together with enabling multiple channels. If you are using LP mode, it is important that you use the function nrf_drv_saadc_sample_task_get() when setting up the PPI channels, is this will trigger the START task over PPI and not the SAMPLE task. The SAMPLE task will be triggered in the IRQ handler when the STARTED event is generated.

    The post provides another approach where the SAADC driver is uninit and re-initialized between each sampling, which should work with multiple channels.

    Best regards,
    Jørgen

  • Jorgen,

    The sample rate of the ADC is very slow so I modified the code to init/sample/unit using an app_timer.

    I don't understand why EasyDMA does not seem to be a problem with other peripherals. The SPI manager uses EasyDMA and there isn't a power issue with that...?

    Thanks

  • The SPIM peripheral will consume the same amount of current when it is transferring data, but this is normally limited to a shorter period of time, as you start a transfer that finishes when all data have been transferred. The difference to the SAADC peripheral is that the SAADC is started when you configure the buffers, but the sampling/actual transfer of data to RAM happens when you trigger the SAMPLE task. Since the SAADC peripheral does not know when the sampling will happen, it is ready to transfer data to RAM at any time. Ideally, the EasyDMA access should only have been enabled after sample task has happened and result is transferred to RAM, but this is not how the design works.

    You will see similar current draw if you enable UARTE in RX mode, as this needs to be ready to transfer received data to RAM at any given time.

  • Hello,

    I know this was marked at verified, but I still have a problem. Init is called at the beginning of the program. When the ADC channel is init'ed, The power goes up about .5mA. After the first sample is taken, the current goes up another 1.5mA. The code below should not use DMA. I can not find an option to disable EASY_DMA for the ADC. The lowest power consumption is when the ADC is only enabled long enough to take a sample. Would SAADC_API_V2 help address this issue? 3.5mA is too high for our battery powered application. Enabling and disabling the ADC with each sample is causing other electrical issues.

    #define SAADC_CONFIG_RESOLUTION 3
    
    #define SAADC_CONFIG_LP_MODE 1
    


    static void saadc_sample_init() { ENABLE_TEMP_OUTPUT(); // Setup for double buffer, continuous sampling nrf_drv_saadc_config_t cfg = NRF_DRV_SAADC_DEFAULT_CONFIG; ret_code_t err_code = NRF_SUCCESS; err_code = nrf_drv_saadc_init(&cfg, saadc_callback); APP_ERROR_CHECK(err_code); // battery_init() - configure the SAADC interface nrf_saadc_channel_config_t vbatt_channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(ADC_VBATT_AIN); err_code = nrf_drv_saadc_channel_init(BATTERY_ADC_CHANNEL, &vbatt_channel_config); APP_ERROR_CHECK(err_code); // lmt70_init() - configure temperature ADC channel nrf_saadc_channel_config_t temp_channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(ADC_TEMPOUT_AIN); err_code = nrf_drv_saadc_channel_init(TEMPERATURE_ADC_CHANNEL, &temp_channel_config); APP_ERROR_CHECK(err_code);

        ret_code_t err_code = app_timer_start(sample_timer_id, ADC_SAMPLE_TIMEOUT, NULL);
        APP_ERROR_CHECK(err_code);
    
    } 
    static void sample_timer_handler(void * p_context)
    {
        app_sched_event_put(NULL, 0, sample_timer_task);
    }
    
    static void sample_timer_task(void * data, uint16_t len)
    {
        UNUSED_PARAMETER(data);
        UNUSED_PARAMETER(len);
    
        // Sample all channels
        nrf_drv_saadc_buffer_convert(m_buffer_pool[m_samples], NUM_ADC_CHANNELS);
        nrf_drv_saadc_sample(); // trigger sample
    
    }
    


  • Hi,

    It is not possible to disable EasyDMA in the SAADC peripheral. Even with the buffer size set to a single sample, EasyDMA will be used to store the sample directly in RAM. ~0.5mA sounds like the current from the HFCLK running, while 1.5mA could be the EasyDMA current.

    Have you defined NUM_ADC_CHANNELS to 2?

    Your base current looks very high, even with the SAADC running. Are you running at 3.0V supply? Are you using the DCDC regulator, or just LDO?

    Could you share the full project for us to reproduce and debug the current consumption?

    Best regards,
    Jørgen

Related