I am developing a NIR (Near-Infrared) product using nRF52810.
I use 15.3 for SDK and S112 for Softdevice.
I implemented ADC (saadc) function based on ble_app_uart.
I have to read 2 ADC channels at 62.5KHz (16usec) for NIR measurement.
I made a test code and tried it out.
However, if nrf_drv_saadc_sample () is called 100 times in 62.5KHz (16usec), saadc_callback (nrf_drv_saadc_evt_t const * p_event) is rarely performed.
If nrf_drv_saadc_sample () is called 100 times in approximately 1KHz (1,000 usec) units, saadc_callback (nrf_drv_saadc_evt_t const * p_event) is performed 100 times.
As a result of my measurement test, the maximum sampling rate for ADC 2 channels is 1KHz (1,000usec).
That is, the maximum sampling rate is too slow for NIR measurement.
Looking at the nRF52810 datasheet, the SAADC Maximum sampling rate is 200KHz.
How can I read ADC 2channel in 62.5KHz (16usec) unit?
My test code is here.
#include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <string.h> #include "nrf.h" #include "nrf_drv_saadc.h" #include "nrf_drv_ppi.h" #include "nrf_drv_timer.h" #include "boards.h" #include "app_error.h" #include "nrf_delay.h" #include "app_util_platform.h" #include "nrf_pwr_mgmt.h" #include "nrf_log.h" #include "nrf_log_ctrl.h" #include "nrf_log_default_backends.h" #include "nir_meas.h" #define SAMPLES_IN_BUFFER 2 volatile uint8_t state = 1; static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(1); static nrf_saadc_value_t m_buffer_pool[2][SAMPLES_IN_BUFFER]; #define TEST_NUM 100 static uint16_t data_mv[TEST_NUM][2] = {0,}; static uint8_t count_num = 0; static uint8_t cnt_cnt = 0; void timer_handler(nrf_timer_event_t event_type, void * p_context) { if(count_num < TEST_NUM) { APP_ERROR_CHECK(nrf_drv_saadc_sample()); count_num ++; } else if(count_num >= TEST_NUM) { nrf_drv_timer_disable(&m_timer); } } void saadc_sampling_event_init(void) { ret_code_t 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(&m_timer, &timer_cfg, timer_handler); APP_ERROR_CHECK(err_code); /* setup m_timer for compare event every xxxms */ uint32_t ticks = nrf_drv_timer_us_to_ticks(&m_timer, 1000); nrf_drv_timer_extended_compare(&m_timer, NRF_TIMER_CC_CHANNEL0, ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true); nrf_drv_timer_enable(&m_timer); } void saadc_callback(nrf_drv_saadc_evt_t const * p_event) { cnt_cnt++; 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); data_mv[count_num][0] = p_event->data.done.p_buffer[0] * 3600 / 1024; data_mv[count_num][1] = p_event->data.done.p_buffer[1] * 3600 / 1024; printf("<%d> %d mV\r\n", count_num, data_mv[count_num][0]); printf("<%d> %d mV\r\n", count_num, data_mv[count_num][1]); } printf("-<%d>- \r\n", cnt_cnt); } void saadc_init(void) { ret_code_t err_code; nrf_saadc_channel_config_t channel_0_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0); nrf_saadc_channel_config_t channel_1_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN1); err_code = nrf_drv_saadc_init(NULL, saadc_callback); APP_ERROR_CHECK(err_code); err_code = nrf_drv_saadc_channel_init(0, &channel_0_config); APP_ERROR_CHECK(err_code); err_code = nrf_drv_saadc_channel_init(1, &channel_1_config); APP_ERROR_CHECK(err_code); err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER); APP_ERROR_CHECK(err_code); err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_IN_BUFFER); APP_ERROR_CHECK(err_code); }
In the code above, I set TIMER to 1,000usec.
When timer_handler is called 100 times (count_num = 100), saadc_callback (cnt_cnt = 100). It is OK.
So, as a result of my testing, the maximum sampling rate is 1KHz.
Set TIMER to 1000usec or less,
If timer_handler is called 100 times (count_num = 100), saadc_callback is executed 80-90 times.
(cnt_cnt <100).
Additional comments:
Ultimately, I want to use a method to call nrf_drv_saadc_sample () through an external interrupt input pin in 62.5KHz.
So the timer routine in the current code is also using the method to call nrf_drv_saadc_sample ().
Thank you.