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

  • Hi Kenneth,

    Did some more testing and now I am a confused on how these ADC pins work. I used an ADC on an arduino and found that the resistor and cap values should be okay. I'm wondering if I configured my pins correctly, especially the pin numbering as I've read that AIN7 (pin 7, or P0.31) is NOT NRF_SAADC_INPUT_AIN7.

    I am using pin 0.31, AIN7 as the voltage reading on the battery voltage divider. Is it appropriate to assign this pin as 7 and run configuration:

    nrf_saadc_channel_config_t channel_config7 = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(7);
    err_code = nrf_drv_saadc_channel_init(7, &channel_config7);
    APP_ERROR_CHECK(err_code);

    Then I simply read its value in blocking mode

    ret_code_t err_code;
    nrf_saadc_value_t adc_result;
    
    // convert ADC value
    err_code = nrf_drv_saadc_sample_convert(BATTERY_PIN, &adc_result);
    APP_ERROR_CHECK(err_code);
    
    // print
    NRF_LOG_INFO("%d", adc_result);

    Yet, these are giving me readings of 321 out of a 12 bit resolution (configured in sdk_config.h - #define SAADC_CONFIG_RESOLUTION 2), which means my battery is dead or not hooked up.

    Any insights?

    Best,

    George

  • I think you are mixing adc channels with analog pins, there is no dependency between the two. So if you need to sample one analog pin (e.g. AnalogInput7), then I suggest to configure adc channel 0 to sample whatever analog input you want to sample (e.g. AnalogInput7 = value 8). Also see:
    https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52832.ps.v1.1/saadc.html#register.CH-0.PSELP 

    Kenneth

Reply Children
No Data
Related