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

Measuring execution time of saadc sampling

Hi everyone,

I want to measure the total execution time of saadc_sample() & saadc_callback() functions. I am using the application timer and I have inserted the app_timer_cnt_get() before and after the functions I want to measure as well as the app_timer_cnt_diff_compute() to calculate the ticks.

After the functions executed the app_timer_cnt_diff_compute()  returns 0 ticks. My questions are:

1. Does this mean that the execution time is less than the resolution of app_timer which is ~30 us?

2. Does it make sense that the execution time of those functions is less than 30us?

There are the functions

void saadc_sample() {
  ret_code_t err_code;
  begin = app_timer_cnt_get();       // na - get the current ticks
  NRF_LOG_INFO("ticks_start = %d \n",begin);
  err_code = nrf_drv_saadc_sample(); // na - trigger sampling
  APP_ERROR_CHECK(err_code);
}

void saadc_callback(nrf_drv_saadc_evt_t const *p_event) {

  if (p_event->type == NRF_DRV_SAADC_EVT_DONE) { 
    ret_code_t err_code;

    err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);

    ADC_RawData[callback_counter] = p_event->data.done.p_buffer[0]; 
    

    if (callback_counter == NO_SENSORS - 1) {

      end = app_timer_cnt_get(); // na - get the current ticks after saadc sampling
      NRF_LOG_INFO("ticks_end = %d \n",end);
      NRF_LOG_INFO("result time in ticks = %d \n", app_timer_cnt_diff_compute(end, begin));

    }

Thanks in advance

Nick

Parents
  • Hello Nick,

    What is your defined Acquisition time?
    If you are initializing your SAADC channel with the NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE then the default acquisition time is 10 us.

    #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_10US,           \
        .mode       = NRF_SAADC_MODE_SINGLE_ENDED,      \
        .burst      = NRF_SAADC_BURST_DISABLED,         \
        .pin_p      = (nrf_saadc_input_t)(PIN_P),       \
        .pin_n      = NRF_SAADC_INPUT_DISABLED          \
    }

    1. Does this mean that the execution time is less than the resolution of app_timer which is ~30 us?

    2. Does it make sense that the execution time of those functions is less than 30us?

    Yes to both. If the timer has not had any ticks since last time, the difference will be 0. This makes sense unless you are using the 40 us SAADC channel acquisition time. You could print out(using deferred logging for minimal impact) the values of begin and end to verify this.

    From your code, I am assuming your SAMPLES_IN_BUFFER = 1?

    Best regards,
    Karl 

  • Hi Karl,

    Yes I am using the NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE  to initialize my channel and I am just changing the gain and reference voltage

    void saadc_init(void) {
      ret_code_t err_code;
    
      //na configure adc resolution
      nrfx_saadc_config_t adc_config = NRFX_SAADC_DEFAULT_CONFIG;
      adc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;
    
      nrf_saadc_channel_config_t channel_config =
          NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN1); //na AIN0 is the pin P0.03 - https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Fpin.html
    
      //na configure adc channel gain and vref
      channel_config.gain = NRF_SAADC_GAIN1_4;
      channel_config.reference = NRF_SAADC_REFERENCE_VDD4;
    
      //pd adc initialize with custom configuratiom
      err_code = nrf_drv_saadc_init(&adc_config, saadc_callback);
      APP_ERROR_CHECK(err_code);
    
      err_code = nrf_drv_saadc_channel_init(0, &channel_config);
      APP_ERROR_CHECK(err_code);
    
      err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER); // na - designating the buffer in which to fill the samples produces by nrf_drv_saadc_sample or NRF_SAADC_TASK_SAMPLE.
      APP_ERROR_CHECK(err_code);
    
      err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_IN_BUFFER);
      APP_ERROR_CHECK(err_code);
    }

    I didn't notice the acq_time parameter, so it makes sense that I cannot the execution time. I printed out the values of begin and end and indeed they have the same value. Also, I've noticed that I can further reduce the acquisition time down to 3us

    /** @brief Analog-to-digital converter acquisition time. */
    typedef enum
    {
        NRF_SAADC_ACQTIME_3US  = SAADC_CH_CONFIG_TACQ_3us,  ///< 3 us.
        NRF_SAADC_ACQTIME_5US  = SAADC_CH_CONFIG_TACQ_5us,  ///< 5 us.
        NRF_SAADC_ACQTIME_10US = SAADC_CH_CONFIG_TACQ_10us, ///< 10 us.
        NRF_SAADC_ACQTIME_15US = SAADC_CH_CONFIG_TACQ_15us, ///< 15 us.
        NRF_SAADC_ACQTIME_20US = SAADC_CH_CONFIG_TACQ_20us, ///< 20 us.
        NRF_SAADC_ACQTIME_40US = SAADC_CH_CONFIG_TACQ_40us  ///< 40 us.
    } nrf_saadc_acqtime_t;

    What is the purpose of all these acquisition times and how do I know which one fits better my application?

    From your code, I am assuming your SAMPLES_IN_BUFFER = 1?

    Yes, SAMPLES_IN_BUFFER = 1, is this somehow related?

    Thanks

    Nick

  • Hello again Nick,

    Great, I am happy that my answer made things more clear.

    Nikosant03 said:
    What is the purpose of all these acquisition times and how do I know which one fits better my application?

    The Acquisition time indicates how long the capacitor is connected, when gathering the sample.
    The SAADC Documentations section on Acquisition time reads:

    The acquisition time indicates how long the capacitor is connected, see TACQ field in CH[n].CONFIG register. The required acquisition time depends on the source resistance (Rsource). For high source resistance the acquisition time should be increased.

    In essence; if the resistance is larger(such that current is low) then the capacitor will reach the steady state voltage slower. In the case of a massive resistance, you would want to have the capacitor connected longer to ensure that you are getting correct measurements.

    Nikosant03 said:
    Yes, SAMPLES_IN_BUFFER = 1, is this somehow related?

    Not directly, I was just confirming that your intent was to measure the time it took to do and process exactly 1 sample(since the "end" variable was being captured at the end of the SAADC DONE EVT). The sample buffer size is not in any way related to the acquisition time parameter, sorry if this was confusing.

    Best regards,
    Karl

Reply
  • Hello again Nick,

    Great, I am happy that my answer made things more clear.

    Nikosant03 said:
    What is the purpose of all these acquisition times and how do I know which one fits better my application?

    The Acquisition time indicates how long the capacitor is connected, when gathering the sample.
    The SAADC Documentations section on Acquisition time reads:

    The acquisition time indicates how long the capacitor is connected, see TACQ field in CH[n].CONFIG register. The required acquisition time depends on the source resistance (Rsource). For high source resistance the acquisition time should be increased.

    In essence; if the resistance is larger(such that current is low) then the capacitor will reach the steady state voltage slower. In the case of a massive resistance, you would want to have the capacitor connected longer to ensure that you are getting correct measurements.

    Nikosant03 said:
    Yes, SAMPLES_IN_BUFFER = 1, is this somehow related?

    Not directly, I was just confirming that your intent was to measure the time it took to do and process exactly 1 sample(since the "end" variable was being captured at the end of the SAADC DONE EVT). The sample buffer size is not in any way related to the acquisition time parameter, sorry if this was confusing.

    Best regards,
    Karl

Children
Related