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

Prescaling on ADC battery voltage measurement

I'm trying to measure a scaled down battery voltage level on an ADC pin. Given my resistor values the voltage on the pin should be about 0.279 times VBATT, to fit within 1.2V. It's a lithium ion battery that shouldn't go over about 4.1V or 4.2V.

Here's how my ADC pin is set up. Note the "NoPrescaling".

	NRF_ADC->CONFIG	= (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos) // We don't have any external reference pins.
		| (ADC_CONFIG_PSEL_AnalogInput2 << ADC_CONFIG_PSEL_Pos) // Use analog input 2.
		| (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) // Use internal 1.2V bandgap voltage as reference for conversion.
		| (ADC_CONFIG_INPSEL_AnalogInputNoPrescaling << ADC_CONFIG_INPSEL_Pos) // No prescaling.
		| (ADC_CONFIG_RES_8bit << ADC_CONFIG_RES_Pos); // 8 bit resolution.

There's some discussion of the arithmetic to be done on the NRF_ADC->RESULT in this thread:

devzone.nordicsemi.com/.../what-s-wrong-with-measuring-lithium-battery-voltage

My question is, why is the code in that thread using an ADC_PRE_SCALING_COMPENSATION value when the ADC is set to no prescaling?

Multiplying by 4 would get me a value pretty close to what I'm measuring with a multimeter, as it happens.

Parents
  • Here are my constants:

    #define BATTERY_ADC_FACTOR (0.279f)
    #define BATTERY_REFERENCE_VOLTAGE (1.2f)
    #define BATTERY_ADC_MAX (1024)
    

    And here's my arithmetic, with the values I'm seeing:

    	// This gets us a fractional number from 0 to 1, a proportion of the maximum.
    	float adc_result_proportion = ((float)NRF_ADC->RESULT/(float)BATTERY_ADC_MAX);
    	// eg. 234 / 1024 = 0.229
    
    	// This gets us the actual voltage on the ADC pin.
    	float pin_voltage = adc_result_proportion * BATTERY_REFERENCE_VOLTAGE;
    	// eg. 0.229 * 1.2V = 0.274V <-- Too low considering I measure 4.2V across the battery directly.
    
    	// This gets us the corresponding voltage across the battery terminals.
    	m_battery_voltage = pin_voltage / BATTERY_ADC_FACTOR;
    	// eg. 0.274V / 0.279 = 0.983
    

    Let me know if you need my resistor values, but they're not too far off those posted in the other thread. Same orders of magnitude, anyway.

Reply
  • Here are my constants:

    #define BATTERY_ADC_FACTOR (0.279f)
    #define BATTERY_REFERENCE_VOLTAGE (1.2f)
    #define BATTERY_ADC_MAX (1024)
    

    And here's my arithmetic, with the values I'm seeing:

    	// This gets us a fractional number from 0 to 1, a proportion of the maximum.
    	float adc_result_proportion = ((float)NRF_ADC->RESULT/(float)BATTERY_ADC_MAX);
    	// eg. 234 / 1024 = 0.229
    
    	// This gets us the actual voltage on the ADC pin.
    	float pin_voltage = adc_result_proportion * BATTERY_REFERENCE_VOLTAGE;
    	// eg. 0.229 * 1.2V = 0.274V <-- Too low considering I measure 4.2V across the battery directly.
    
    	// This gets us the corresponding voltage across the battery terminals.
    	m_battery_voltage = pin_voltage / BATTERY_ADC_FACTOR;
    	// eg. 0.274V / 0.279 = 0.983
    

    Let me know if you need my resistor values, but they're not too far off those posted in the other thread. Same orders of magnitude, anyway.

Children
No Data
Related