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
  • Sounds to me that you are measuring a very high impedance source (e.g. >1Mohm), which each time the pin is sampled need to be "charged" before it return to the same level. Can you connect a small capacitor (e.g. >1nF) on the analog input to see if this affect your results?

    Kenneth

  • That could be right. Here's the voltage divider I am using to measure the battery level.

    It is a 4MOhm by 10MOhm voltage divider with a 10nF cap. I remember I could do this with my sampling frequency from this post

    From the post

    However, if you see the notes it should have been 2 100KOhm resistors. Anyways, I'm surprised it would be this slow to charge. I'm assuming a fix would be to replace the resistors for something smaller. Same for the capacitor (say 1 nF)?

    Thanks,

    George

Reply
  • That could be right. Here's the voltage divider I am using to measure the battery level.

    It is a 4MOhm by 10MOhm voltage divider with a 10nF cap. I remember I could do this with my sampling frequency from this post

    From the post

    However, if you see the notes it should have been 2 100KOhm resistors. Anyways, I'm surprised it would be this slow to charge. I'm assuming a fix would be to replace the resistors for something smaller. Same for the capacitor (say 1 nF)?

    Thanks,

    George

Children
Related