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

How to increase SAADC sample rate and how to correctly use SAADC conversion results when oversampling (nRF52840)?

Hi after a long time,

we have developed a custom board with nRF52840 and there is a part of the project, which is focused on sensing sound and evaluating sound pressure level.(SPL)

We have a A-weighted analog filter connected to the AIN2 input on nRF52840, this filter also serves as an anti-aliasing filter. The measured value of SPL is then sent over BLE to the outside world.

However, we run into trouble with sample rate limitations of SAADC module. We have been using SAADC example provided in SDK as the starting point. 

void saadc_sampling_event_init(void)
{
  ret_code_t err_code;
  err_code = nrf_drv_ppi_init();
  APP_ERROR_CHECK(err_code);
  nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
  timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
  err_code = nrf_drv_timer_init(&saadc_timer, &timer_cfg, saadc_timer_handler);
  APP_ERROR_CHECK(err_code);
  /* setup saadc_timer for compare event every 40us */
  uint32_t ticks = nrf_drv_timer_us_to_ticks(&saadc_timer, 40);
  nrf_drv_timer_extended_compare(&saadc_timer,
  NRF_TIMER_CC_CHANNEL0,
  ticks,
  NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
  false);
  nrf_drv_timer_enable(&saadc_timer);
  uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&saadc_timer,
  NRF_TIMER_CC_CHANNEL0);
  uint32_t saadc_sample_task_addr = nrf_drv_saadc_sample_task_get();
  /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
  err_code = nrf_drv_ppi_channel_alloc(&saadc_ppi_channel);
  APP_ERROR_CHECK(err_code);
  err_code = nrf_drv_ppi_channel_assign(saadc_ppi_channel,
  timer_compare_event_addr,
  saadc_sample_task_addr);
  APP_ERROR_CHECK(err_code);
}

With timer set to minimum of 25us, everything works fine, setting shorter time leads to BLE stack failling to init. We need shorter sampling time in order to avoid aliasing. Code for reading ADC value is

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 output data to be assigned to x_in variable
   float32_t x_in = p_event->data.done.p_buffer[0]; //ADC
   saadc_evt_counter++;

 

We\ve been unable to find the cause for BLE init failure with SAADC sampling rates >40kSa/s so the question would be, whether the code provided in the SDK SAADC example is capable of delivering ADC samples at such high sample rates (there is some stuff which in my opinion makes things a bit slower, i.e. APP_ERROR_CHECK() function calls).

We have tried OVERSAMPLE functionality as well, however it delivered not plausible data. So, the second question is whether ve understand the OVERSAMPLE correctly. After searching this DevZone, I concluded that the oversampling on SAADC cannot be used to increase sample rate (i.e. setting timer to 40us and oversample to 8x would not result in actual 5us sampling time). Is this assumption correct?

Thanks a lot!

Cheers,

Petr

Parents
  • Hi Petr

    Are you able to provide some more input on how the BLE stack fails to init when you increase the sample rate?

    Have you tried to enable and initialize the BLE stack before starting the ADC sampling to see if this fixes the issue?

    What is the SAMPLES_IN_BUFFER define set to?
    If you are sampling at a rapid rate it is recommended to increase the size of the buffer, to reduce the overhead of handling the ADC callback, and increase the time between interrupts. 

    The OVERSAMPLE feature is designed for situations where you want to oversample a low frequency signal in order to increase the ADC resolution, and will not help you achieve higher sampling rate. 

    Best regards
    Torbjørn

Reply
  • Hi Petr

    Are you able to provide some more input on how the BLE stack fails to init when you increase the sample rate?

    Have you tried to enable and initialize the BLE stack before starting the ADC sampling to see if this fixes the issue?

    What is the SAMPLES_IN_BUFFER define set to?
    If you are sampling at a rapid rate it is recommended to increase the size of the buffer, to reduce the overhead of handling the ADC callback, and increase the time between interrupts. 

    The OVERSAMPLE feature is designed for situations where you want to oversample a low frequency signal in order to increase the ADC resolution, and will not help you achieve higher sampling rate. 

    Best regards
    Torbjørn

Children
Related