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

What is the SAADC Maximum sampling rate for nRF52810?

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.

Parents Reply Children
Related