This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

nRF52840 SDK16 - SAADC + RTC + PPI (power optimized solution)

Hi everyone,

There is an open ticket that I need support with because the responsible engineer will be out of the office until the new year.

In a nutshell:

I design a low-power application and I want to sample 8 pressure sensors that are connected to a MUX. I want to sample with a rate of 100Hz the group of eight sensors. That means every 10ms I need to sample all of the 8 sensors as fast as possible (given of course the hardware delays such as the MUX's switching speed and ADC conversion and acquisition time). So far, the optimized approach is to use:

RTC because uses the low-frequency clock

PPI because sampling does not require CPU intervention. However, PPI channels require that the HFCLK is always kept running (so I still thinking about it)

My purpose to go through the MUX's truth table using PPI as well (but in a future step)

Now let's say that I set an RTC CC to 10ms to trigger the SAMPLE task using the COMPARE event. Then, I have to keep sapling until the 8th sensor. I came across with two possible solutions using PPI:

1. To set up a second RTC CC let's say to 50us, to trigger the sample task using the compare event until to sample all the sensors

2. To enable the DONE interrupt, to set up a second PPI channel and trigger the SAMPLE task with the DONE event (I tried to do this but still it hasn't work) until the 8th sensor

Here Karl says that I can achieve the same functionality with just one PPI channel. I do not understand how can I do it with one channel or I didn't explain correctly to Karl what I want to achieve.

Given the aforementioned, what is the most power-optimized approach?

Thanks

Nick

  • Thank you for your answer but I cannot modify the hardware at the moment. However I do not understand why I cannot sampling in a loop like this

    for(uint_8 i=0; i<no_of_sensors; i++){
    nrf_drv_saadc_sample();
    }

  • Hi,

    That will not work. Calling nrfx_saadc_sample() in the end calls nrfx_saadc_sample(), which looks like this:

    nrfx_err_t nrfx_saadc_sample()
    {
        NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
    
        nrfx_err_t err_code = NRFX_SUCCESS;
        if (m_cb.adc_state != NRF_SAADC_STATE_BUSY)
        {
            err_code = NRFX_ERROR_INVALID_STATE;
        }
        else if (m_cb.low_power_mode)
        {
            nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
        }
        else
        {
            nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
        }
    
        NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
        return err_code;
    }

    So you need to have set everything up for sampling, and not for instance, be in the middle of another sampling. If you want to do thing like this where you juts call a function and everything is done for you and you are ready again once it returns you need to use the blocking API instead, which is nrfx_saadc_sample_convert() in this case.

Related