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

problem with nrf51822 ADC

Hi to all,

i am developing a device that in it i need to measure voltage of battery to report percentage of battery to user, but the voltage that i measure with ADC is different with voltage that i measured with multi-meter, for example multi-meter say that voltage battery is 2.25v and ADC say vltage is 1.962v, or multi-meter say that voltage battery is 2.983v and ADC say voltage is 2.880v. i use the following setting to config ADC:

adc_config.reference  = NRF_ADC_CONFIG_REF_VBG;
adc_config.resolution = NRF_ADC_CONFIG_RES_8BIT;
adc_config.scaling    = NRF_ADC_CONFIG_SCALING_SUPPLY_ONE_THIRD;
nrf_adc_configure(&adc_config);

// Enable ADC interrupt
nrf_adc_int_enable(ADC_INTENSET_END_Msk);
err_code = sd_nvic_ClearPendingIRQ(ADC_IRQn);
APP_ERROR_CHECK(err_code);

err_code = sd_nvic_SetPriority(ADC_IRQn, 3);
APP_ERROR_CHECK(err_code);

err_code = sd_nvic_EnableIRQ(ADC_IRQn);
APP_ERROR_CHECK(err_code);

and when program receive the interrupt, i use the following code to convert ADC value to mili volt:

#define ADC_PRE_SCALING_COMPENSATION    3                                            /**< The ADC is configured to use VDD with 1/3 prescaling as input. And hence the result of conversion is to be multiplied by 3 to get the actual value of the battery voltage.*/
#define ADC_REF_VOLTAGE_IN_MILLIVOLTS   1200                                         /**< Reference voltage (in milli volts) used by ADC while doing conversion. */
#define ADC_RESULT_IN_MILLI_VOLTS(ADC_VALUE) ((((ADC_VALUE) * ADC_REF_VOLTAGE_IN_MILLIVOLTS) / 255) * ADC_PRE_SCALING_COMPENSATION)


void ADC_IRQHandler(void)
{  
    if (nrf_adc_conversion_finished())
    {
    	uint8_t  adc_result;
    	uint16_t batt_lvl_in_milli_volts;
    	uint8_t  percentage_batt_lvl;
    
    	nrf_adc_conversion_event_clean();
    
    	adc_result = nrf_adc_result_get();
    	batt_lvl_in_milli_volts = ADC_RESULT_IN_MILLI_VOLTS(adc_result);
    	bl = batt_lvl_in_milli_volts;
    }
}
i can not understand that what is wrong, there is any one that can give me a advice to solve this problem??  there is any way better for measuring the battery level instead of using ADC??

thanks for your responses 

  • and also another question, is it possible to measure battery accurate voltage when we are using voltage of battery as reference voltage??

    document say that when we set NRF_ADC_CONFIG_REF_VBG in configuration adc will use 1.2v as voltage reference, is there any regulator or something in nrf51822 that convert 3.3v battery voltage to 1.2v and then use from it as reference voltage???

  • Measuring vbat is always troublesome. If you are measuring a coin cell it can be even harder since processor and radio activity heavily influence the instantaneous voltage.  This can give you discrepancies when measuring rest voltage with a multimeter.

    To ensure you are measuring at the correct time use radio notifications to let you measure Vbat before the radio goes active.  In this manner you will know the battery has rested for a few milliseconds (maybe more depending on your code) and you will get a value closer to the rest voltage.

    Second all ADCs have some amount of DC offset, on nRF52 there is a routine to calibrate this out on nRF51 there is no such routine that I know of.  so you just have to come up with a way in code to compensate for the nominal offset.  This offset is normally temp dependent so you may have to measure temp then factor offset into your Vbat measurement.  I encourage you to thumb through the devzone for solutions on this.

    Some people even go so far as to take several measurements and then average to get a better idea of the real voltage. Functionally your value will always be off by a few quanta just because of how ADCs work.  For this reason people normally throw away the bottom two bits or so as an easy way to get more accurate values.

    Yes, VBG is an internal 1.2v reference.  Since it will always be 1.2v for Vbat from 2.1 to 3.6v you can always assume it is accurate.

    On our own nRF52 product we use temp and an offset number to measure Vbat.  The temp is important for the coin cell which has a rather large correlation with temp and its rest voltage.  We measure Vbat hourly 5.5msec before the radio goes active then do a weighted average of the hourly measurements.  Thus far it has worked really well.

  • The ADC requires a constant reference voltage, so it would not make much sense to use a battery as the the reference voltage. In addition, this is unfortunately not possible.

    Yes, there is an internal regulator that converts the 3.3v battery voltage to 1.2 volts.

    Which Nordic SDK version are you currently using?

Related