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

SAADC oversample with burst configuration

Dear DevZone,

I am trying to configure the SAADC on my custom nRF52840 board.

I would like to use it in blocking mode together with oversample 16x and burst enabled.

I started from the example provided in the SDK, and I firstly removed all the parts related to non-blocking mode.

Then I modified the parameters to set oversample and burst mode. Here the steps I performed:

  • I modified the configuration struct to enable burst in this way:

#define NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE(PIN_P) \
{ \
.resistor_p = NRF_SAADC_RESISTOR_DISABLED, \
.resistor_n = NRF_SAADC_RESISTOR_DISABLED, \
.gain = NRF_SAADC_GAIN1_6, \
.reference = NRF_SAADC_REFERENCE_INTERNAL, \
.acq_time = NRF_SAADC_ACQTIME_3US, \
.mode = NRF_SAADC_MODE_SINGLE_ENDED, \
.burst = NRF_SAADC_BURST_ENABLED, \ //enabled burst mode to automatically acquire 2^oversample samples with one request
.pin_p = (nrf_saadc_input_t)(PIN_P), \
.pin_n = NRF_SAADC_INPUT_DISABLED \
}

  • I modified the following value in the sdk_config file:

// <0=> Disabled
// <1=> 2x
// <2=> 4x
// <3=> 8x
// <4=> 16x
// <5=> 32x
// <6=> 64x
// <7=> 128x
// <8=> 256x

#ifndef NRFX_SAADC_CONFIG_OVERSAMPLE
#define NRFX_SAADC_CONFIG_OVERSAMPLE 4
#endif

Is the procedure correct? Am I missing something? Do you think there could be any issues related to the buffer size if I use the blocking mode (nrfx_saadc_sample_convert function)?

Thank you very much in advance,

best regard,

Gianluca Milani

Parents
  • Hi,

    It seems correct for blocking mode. However, what is your intention of using blocking mode instead of non-blocking? Are you using PPI to connect the SAMPLE task with the COMPARE event as in the example? That could be a bit problematic as it could lead to the buffer swap issue.

    regards

    Jared 

  • In other words, what I understood from the documentation is that the relationship between the ADC modalities can be described as follows:

    1) Am I correct?

    In that case, I would use the one-shot - blocking since I need to leave free the timers.

    2) Do you think is a good idea or I should go with one of the others?

    3) To have the oversample with burst feature is it ok to use the blocking- one shot modality as I showed you in the code?

    Thanks, I hope I was clear enough,

    Best regards,

    Gianluca

  • Thanks Jared,

    I saw in this post https://devzone.nordicsemi.com/f/nordic-q-a/67552/what-is-the-eventdone-of-saadc-oversampling the differences between the EVENTS_DONE event of the oversample and the one for the buffer which is filled (SAADC_EVT_DONE).

    I cannot understand how to handle the generation of the event EVENTS_DONE in the callback function . can I do as the case with SAADC_EVT_DONE putting the address of the register? something like this?

    void saadc_callback_handler(nrf_drv_saadc_evt_t const * p_event)
    {
    //Empty
    static int a;
    if (p_event->type == 0x108)
    {
    
    
    a++;
    }
    }

    Thanks,

    Gianluca

  •  Hi,

    You're actually 100% correct, and I managed to mix up the SW and HW events myself. I'm so sorry for this. The driver doesn't really support monitoring the DONE event. You can use a PPI + a Timer in counter mode that increments every time the EVENTS_DONE event is produced. It's a bit more complex than just waiting for the DONE event to be produced by the driver. What's your intention of implementing this?

    regards

    Jared 

  • Dear Jared, 

    don't worry at all, thanks for the answer.

    My only intention was to check if I was actually performing the oversample correctly, but if you can confirm me that with the code I showed you before the oversampling is implemented, I can also avoid to perform this verification.

    P.S.: As you suggested here:

    I don't see any reason to use blocking in the first place as I don't see any benefit from it. It will just cause a higher power consumption.

    I tried to use the non-blocking one-shot mode. I did it following following the basic instruction from Infocenter:

    Here my code instructions for periodically triggering the reading:
        for(int n=1; n=1000; n++){
          
        err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool, SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
        err_code = nrfx_saadc_sample();
        APP_ERROR_CHECK(err_code);
        float bat_vol = m_buffer_pool[0]*2.8/2*6*0.6/4095;
    
        nrf_delay_ms(1000);
    
        }
    Do you thing I am doing it correctly?
    Thanks,
    Gianluca
  • Hi,

    My understanding is that you want to take the sample that has been oversampled 16 times and multiply/divide it with 2.8/2*6*0.6/4095? In that case you have to wait for the data to be ready after it has been oversampled and averaged. The data is ready when the callback handler is called with the NRF_DRV_SAADC_EVT_DONE, which is where this multiplication should take place.

    Don't hesitate to correct me if I misunderstood you on this point. 

    And you should not mix between the legacy nrfx and nrf API. Use nrf_drv_saadc_sample()

     
     Other than that, the code looks correct it will sample in non-blocking mode.
    On a second thought,
    An easier but less elegant way is to count the number of times you have to call the sample task before the NRF_DRV_SAADC_EVT_DONE is generated when burst mode is disabled. When burst mode is disabled, you have to call the sample task manually the number of times the oversample is set to, the callback handler will not generate the NRF_DRV_SAADC_EVT_DONE event before the sample task has been triggered the set amount of times. Which means that you can try to call the sample task in a loop until the NRF_DRV_SAADC_EVT_DONE is generated. If you count the number of times you have iterated the loop then you can ensure that sample has been oversampled. 
    best regards
    Jared 
  • Thank you very much Jared,

    you were correct in understanding my point.

    only one thing: what do you mean with:

    you should not mix between the legacy nrfx and nrf API. Use nrf_drv_saadc_sample()

    Do I have to avoid to use:

    nrf_drv_saadc_buffer_convert(m_buffer_pool, SAMPLES_IN_BUFFER);

    and use only nrf_drv_saadc_sample() ?

    In that case, how can I understand which is the buffer I filled? Where is the sample saved?

    Thanks,

    Gianluca

Reply Children
Related