RAK 11300 ADC shows incorrect battery voltage

Hi! I’ve started doing my first projects with my brand new RAK11300 module. To be able to monitor the battery, I’ve implemented a battery check using the onboard ADC and the voltage divider that is present on the RAKWireless Base Board v2.

According to my calculation, the ADC should present a value of about 3037 at 12 Bit accuracy and 4,1 V battery voltage:

Source

The voltage across GND and ADC_VBAT is 2,46 V at VBat=4,1V:

(4,1 V / 2,5) * 1,5 = 2,46 V

Now given the ADC is set to a resolution of 12 Bit, there are 2¹² values, which is 4096 values. If the max voltage the ADC can take is 3300 mV each ADC step is:

3300 / 4096 = 0,81 mV.

The ADC value should be:

2460 mV / 0,81 mV = 3037

Unfortunately this is now what the actual ADC value shows. It’s more in the region of about 2800 - 2900, which makes my battery level measuring inaccurate. Is this in the normal range of inaccuracy or am I missing something?

I noticed that the example program for battery measurement has the same ADC readings, but the voltage is calculated differently and then matches the end result in volts better than my calculation. But I can’t find the reason why. There are magic numbers that I don’t understand, such as “VBAT_DIVIDER_COMP”. Where do they come from?

For the RAK11300 I use

/** Millivolts per LSB 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096 */
#define VBAT_MV_PER_LSB (0.806F)
/** Compensation factor for the VBAT divider */
#define VBAT_DIVIDER_COMP (1.846F)

/** Real milli Volts per LSB including compensation */
#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)

void init_batt(void)
	// Set the resolution to 12-bit (0..4095)
	analogReadResolution(12); // Can be 8, 10, 12 or 14
}

float read_batt(void)
{
	float raw;

	// Get the raw 12-bit, 0..3000mV ADC value
	raw = analogRead(vbat_pin);

	// Convert the raw value to compensated mv, taking the resistor-
	// divider into account (providing the actual LIPO voltage)
	// ADC range is 0..3000mV and resolution is 12-bit (0..4095)
	return raw * REAL_VBAT_MV_PER_LSB;
}


The VBAT_DIVIDER_COMP is kind of measured correction factor.

And the ADC voltage is 3V, not 3.3V

Hi! Thanks for clarifying. I’m curious about the 3V: In the RP2040 datasheet, usually 3,3 V is mentioned. With one exception:

For much improved ADC performance, an external 3.0V shunt reference, such as LM4040, can be connected from the
ADC_VREF pin to ground. Note that if doing this the ADC range is limited to 0-3.0V signals (rather than 0-3.3V), and the
shunt reference will draw continuous current through the 200Ω filter resistor (3.3V-3.0V)/200 = ~1.5mA.

… so I guess this applies to the RAK11300 module?