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

Inconsistent ADC values - ADC conversion taking a long time

Hello,

I am using multiple ADC pins and realized that repeated calls to the ADC give inconsistent data, suggesting that the conversions are not completing before the next call. I am using the blocking function nrf_drv_saadc_sample_convert(pin, &value), so I assumed it would complete before allowing me to call again but that seems to be false. To check, I artificially call nrf_drv_saadc_sample_convert multiple times and print to UART; however, I need to wait a whole 1000 msec before the next call is consistent to the previous one!

Here's my saadc_init() initialization code

void saadc_init(void)
{
	ret_code_t err_code;
	nrf_saadc_channel_config_t channel_config0 = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
	nrf_saadc_channel_config_t channel_config1 = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN1);
	nrf_saadc_channel_config_t channel_config2 = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
	nrf_saadc_channel_config_t channel_config3 = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN3);
	nrf_saadc_channel_config_t channel_config4 = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN4); 
	nrf_saadc_channel_config_t channel_config5 = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN5);
	nrf_saadc_channel_config_t channel_config6 = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN6);
	nrf_saadc_channel_config_t channel_config7 = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN7);

	err_code = nrf_drv_saadc_init(NULL, saadc_callback);
	APP_ERROR_CHECK(err_code);

	err_code = nrf_drv_saadc_channel_init(0, &channel_config0);
	APP_ERROR_CHECK(err_code);
	err_code = nrf_drv_saadc_channel_init(1, &channel_config1);
	APP_ERROR_CHECK(err_code);
	err_code = nrf_drv_saadc_channel_init(2, &channel_config2);
	APP_ERROR_CHECK(err_code);
	err_code = nrf_drv_saadc_channel_init(3, &channel_config3);
	APP_ERROR_CHECK(err_code);
	err_code = nrf_drv_saadc_channel_init(4, &channel_config4);
	APP_ERROR_CHECK(err_code);
	err_code = nrf_drv_saadc_channel_init(5, &channel_config5);
	APP_ERROR_CHECK(err_code);
	err_code = nrf_drv_saadc_channel_init(6, &channel_config6);
	APP_ERROR_CHECK(err_code);
	err_code = nrf_drv_saadc_channel_init(7, &channel_config7);
	APP_ERROR_CHECK(err_code);
}

// this block of code doesn't run as I am running blocking conversion nrf_drv_saadc_sample_convert()
void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
    NRF_LOG_INFO("SAADC CALLBACK HAPPENING");

    nrfx_saadc_evt_type_t type = p_event->type;
    switch(type)
    {
        case NRF_DRV_SAADC_EVT_DONE:
            SAADC_CONVERT_COMPLETE = true;
            NRF_LOG_INFO("ADC DONE");
            break;
        case NRFX_SAADC_EVT_LIMIT:
            // do something
            break;
        case NRFX_SAADC_EVT_CALIBRATEDONE:
            // do something
            break;
    }
}

For testing purposes, I have a single ADC pin read 3 times in my battery_read() function, which iterates every 10 seconds.

static void battery_read(void)
{
    nrf_saadc_value_t adc_result;
    uint32_t battery_level_millivolts;
    NRF_LOG_INFO("READING ADC VALUES===============");

    nrf_drv_saadc_sample_convert(NRF_SAADC_INPUT_AIN7, &adc_result);
    NRF_LOG_INFO("BATTERY ADC LEVEL 1: %d", adc_result);
    nrf_delay_ms(10); // artificial delay

    nrf_drv_saadc_sample_convert(NRF_SAADC_INPUT_AIN7, &adc_result);
    NRF_LOG_INFO("BATTERY ADC LEVEL 2: %d", adc_result);
    nrf_delay_ms(10); // artificial delay

    nrf_drv_saadc_sample_convert(NRF_SAADC_INPUT_AIN7, &adc_result);
    NRF_LOG_INFO("BATTERY ADC LEVEL 3: %d", adc_result);
    nrf_delay_ms(10); // artificial delay
}

Even at 10 msec delay between nrf_drv_saadc_sample_convert() calls, the UART output gives decreasing ADC values. I have to make the delay closer to 1000 msec to get consistent data (which is way too slow)

Can anyone point out what could be wrong in my SAADC configuration, or how I am retrieving my ADC values?

Thank you,

George

Parents
  • Hi Kenneth,

    I believe I corrected my confusion on configuring ADC pins and assigning them to channels. However, I had to search online to find the correct gain factor, and now I read that there are ADC offsets and other nuances that I need to add/subtract to get the actual voltage reading. Can you point me to any docs or datasheets that outline these computational parameters, and if changing the ADC configurations such as NRF_SAADC_GAIN1_6, or NRF_SAADC_ACQTIME_10US modify these values?

    To confirm I am doing this correctly, here's the minimum set of code to configure and read an ADC pin (in blocking mode)

    // this is where the physical pin is defined. Say AINO on the board
    nrf_saadc_channel_config_t channel_config0 = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
    
    // in blocking mode, this callback isn't used but needs to be initialized.
    // callback is not written here for brevity
    err_code = nrf_drv_saadc_init(NULL, saadc_callback);
    APP_ERROR_CHECK(err_code);
    
    // this is where that pin is assigned to a ADC channel. Channels go from 0-7
    ret_code_t err_code;
    err_code = nrf_drv_saadc_channel_init(0, &channel_config0);
    APP_ERROR_CHECK(err_code);
    
    // this is where the ADC value is read.
    // NOTE - using the same channel defined above, which is 0
    nrf_saadc_value_t adc_result;
    err_code = nrf_drv_saadc_sample_convert(0, &adc_result);
    
    // math to get the equivalent voltage (mV) reading
    // NOTE - gain is 3.6 for default settings and bit resolution defined in sdk_config is 12 bits.
    float val = ((adc_result * 3.6 * 1000) / 4096) ;

    Thank you, and hope this helps others involved.

    George

  • If you are only measuring remaining battery capacity, I don't expect a few % errors is any problem, but you can find the electrical parameters here:
    https://infocenter.nordicsemi.com/topic/ps_nrf52840/saadc.html#unique_699150403

    Kenneth

Reply Children
No Data
Related