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 variablefloat32_t x_in = p_event->data.done.p_buffer[0]; //ADCsaadc_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