I'm having issue where after booting I can immediately do three SAADC samples as follows:
for (uint8_t i = 0; i < SAMPLES_IN_BUFFER; i++)
{
nrfx_saadc_sample();
nrf_delay_ms(SAADC_SAMPLE_DELAY);
}
This works as expected where I get the callback immediately after the third call to nrfx_saadc_sample(). I needed to put in a 1ms delay, otherwise the first sample is 0; However, when I do the same thing in a timer handler, I cannot do three samples in a row. The timer needs to timeout three times in order to get the three samples. I doesn't matter how long the delay time is (I've put in up to 1 second), the only way to get three samples is for the handler to trigger three times. I'm using an app_timer. Here is the handler code:
static void advertise_timeout_handler(void * p_context)
{
for (uint8_t i = 0; i < SAMPLES_IN_BUFFER; i++)
{
nrfx_saadc_sample();
nrf_delay_ms(SAADC_SAMPLE_DELAY);
}
}
Here is the SAADC initialization code:
static void saadc_init(void)
{
ret_code_t err_code;
nrf_drv_saadc_config_t saadc_config;
saadc_config.low_power_mode = NRFX_SAADC_CONFIG_LP_MODE;
saadc_config.resolution = NRF_SAADC_RESOLUTION_10BIT; //Set SAADC resolution to 10-bit. This will make the SAADC output values from 0 (when input voltage is 0V) to 2^10=1024 (when input voltage is 3.6V for channel gain setting of 1/6).
saadc_config.oversample = NRF_SAADC_OVERSAMPLE_DISABLED; //Disable oversample. Can't oversample with more than one channel active.
saadc_config.interrupt_priority = NRFX_SAADC_CONFIG_IRQ_PRIORITY;
nrf_saadc_channel_config_t channel_config =
NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_VDD);
err_code = nrf_drv_saadc_init(NULL, saadc_callback);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_saadc_channel_init(0, &channel_config);
APP_ERROR_CHECK(err_code);
err_code = nrfx_saadc_buffer_convert(m_buffer_pool, SAMPLES_IN_BUFFER);
APP_ERROR_CHECK(err_code);
}
Here is the callback code:
static void saadc_callback(nrf_drv_saadc_evt_t const *p_event)
{
static uint32_t m_adc_evt_counter;
if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
{
ret_code_t err_code;
uint32_t voltage;
uint16_t average_sample = 0;
err_code = nrfx_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
APP_ERROR_CHECK(err_code);
SEGGER_RTT_printf(0, "\nADC event number: %d\n", m_adc_evt_counter);
for (uint8_t i = 0; i < SAMPLES_IN_BUFFER; i++)
{
voltage = p_event->data.done.p_buffer[i] * 3600 / 1024;
SEGGER_RTT_printf(0, "%d\n", voltage);
average_sample += voltage;
}
if((++m_adc_evt_counter % SAADC_CALIBRATION_INTERVAL) == 0)
m_saadc_calibrate = true;
battery_voltage = average_sample / SAMPLES_IN_BUFFER;
change_manuf_specific_data();
}
}
Why does the timer handler have to trigger three times in order to get three samples when outside of the hander after booting, I can do three samples in row and get a valid result?