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

[nRF52] Best practise for ultra low power SAADC 4 channel conversion

What is the best practise for multichannel SAADC conversion in ultra low power devices? For example I have to measured 4 channel in interval 250ms. Below what I try:

  1. I'm set RTC for interupt 250ms. In RTC handler I initialized SAADC channel 0 and start conversion. In SAADC end of conversion handler i uintialized SAADC, get result from channel 0 and initialized for channel 1 and start conversion. Same for channels 3 and 4 but in channel 4 I'm not start new conversion but Im set RTC for 333ms Handler. I try it and I get strange result.

If I have only one channel I've get current consuption: image description

avarage current is around 10uA ( it's ok for my aplication ). but if I enabled conversion for 4 channel, one by one ( as I descripted above ) I've got something like that: image description

Current is 2 times higher! I don't know why density of the current spikes is in that level.

Mayby I should use PPI? i read this topic: devzone.nordicsemi.com/.../

or maybe different method?

Parents Reply Children
  • I'm not sure which issue you are referring. I have tested my above example with SDK 15.3.0, and I'm seeing ~3.6 µA average current with 4 Hz sample rate. With 256 Hz, current increase to ~63 µA average, both on PCA10056 (nRF52840 DK) with 4 channels enabled.

    I have attached the project: saadc_low_power_multichannel_sdk15_3_0.zip

  • Hello Jorgen,

    Let me elaborate a little, the code you provided me meets the specs i need but I am trying to not init and un-init the SAADC every time I have to take a sample.

    I believe that once the channels are configured the Easy-DMA never goes to sleep even in low power mode giving a much larger current average than I would like. I wanted to use the non blocking call to store like 1000 values at a stretch with the SAADC connected to the RTC TICK via PPI but the higher current read makes that impossible.

    I could not find anything related to this in the errata, could you please tell me if there is any way of doing that?

  • The DMA current will be present whenever the SAADC is in STARTED state. The driver triggers the START task when the buffer is setup, in order to be ready to sample. There is a low power mode in the driver, that will delay triggering the start task until the sample task is triggered, to reduce the current when no samples are taking place.

    This is not mentioned in the errata, as this is the base current for all DMA operations. It is not considered a bug.

    If you do not want any CPU operations, and you have two RTCs and 4 PPI channels to spare, you can start and sample the SAADC as shown in this diagram:

    If you configure the buffer to take 1000 samples, and make sure you do not start the SAADC when setting up the buffer, this should give you low current consumption. You should configure the second RTC to give you a compare event after each sample interval, to reduce the time between samples as much as possible. With this solution you can take 1000 samples quickly at a regular interval.

  • I have attached the project: saadc_low_power_multichannel_sdk15_3_0.zip

    In that Project, in main.c line 68, I see:

    #define SAADC_SAMPLES_IN_BUFFER 4                 //Number of SAADC samples in RAM before returning a SAADC event. For low power SAADC set this constant to 1. Otherwise the EasyDMA will be enabled for an extended time which consumes high current.
    

    The comment says,

    "For low power SAADC set this constant to 1"

    So, as this is supposed to be specifically a low-power example, why is it set to 4 ?!

  • Another question on that Project:

    In the saadc_callback, nrf_drv_saadc_buffer_convert() is called, and immediately followed by  nrf_drv_saadc_uninit():

            err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAADC_SAMPLES_IN_BUFFER);  //Set buffer so the SAADC can write to it again. This is either "buffer 1" or "buffer 2"
            APP_ERROR_CHECK(err_code);
            
            :
            : // UART logging stuff
            :
    
            nrf_drv_saadc_uninit();                                                                   //Unintialize SAADC to disable EasyDMA and save power
            NRF_SAADC->INTENCLR = (SAADC_INTENCLR_END_Clear << SAADC_INTENCLR_END_Pos);               //Disable the SAADC interrupt
            NVIC_ClearPendingIRQ(SAADC_IRQn);                                                         //Clear the SAADC interrupt if set
            m_saadc_initialized = false;  
    doesn't the nrf_drv_saadc_uninit() render the nrf_drv_saadc_buffer_convert() pointless?

Related