Skip to content

Battery Level Sensor

Miguel Tomas Silva edited this page Nov 15, 2023 · 12 revisions

Change Language
Last update: 15-11-2023

Simple Battery Level sensor

The positive battery terminal is connected to an ADC IO on the microcontroller. The code below allows the calculation of the battery level, in percentage %, in a simplistic manner.

In my devices I use two 100k resistors:

#define R2 100 #define R3 100

The output voltage of the resistor divider is calculated as Vout = (Vin * R3) / (R2 + R3).

#define VOLTAGE_OUT(Vin) (((Vin) * R3) / (R2 + R3))

As a very rough estimation, one can assume a battery voltage of 4.2V as 100% and a voltage of 3.3V as 0%. Converted to millivolts to avoid floating-point calculations.

#define VOLTAGE_MAX 4200 #define VOLTAGE_MIN 3300

The reference voltage of the ESP32 microprocessor is 1100mV:

#define ADC_REFERENCE 1100

A value returned from ADC in 12-bit mode will be in the range of 0 to 4095. To determine the voltage on the ADC IO one can use the following formula:

#define VOLTAGE_TO_ADC(in) ((ADC_REFERENCE * (in)) / 4096)

The minimum and maximum values of battery voltage using a resistor divider are:

#define BATTERY_MAX_ADC VOLTAGE_TO_ADC(VOLTAGE_OUT(VOLTAGE_MAX)) #define BATTERY_MIN_ADC VOLTAGE_TO_ADC(VOLTAGE_OUT(VOLTAGE_MIN))

Retrieving value from ADC is pretty straightforward and well described in the official Espressif documentation. Assume the measured value from ADC IO in the variable called adc, then the battery level calculation is done as follows:

int calc_battery_percentage(int adc)
{
    int battery_percentage = 100 * (adc - BATTERY_MIN_ADC) / (BATTERY_MAX_ADC - BATTERY_MIN_ADC);

    if (battery_percentage < 0)
        battery_percentage = 0;
    if (battery_percentage > 100)
        battery_percentage = 100;
    return battery_percentage;
}

A more accurate Battery Level sensor [1]

A more accurate Battery level sensor can be implemented on the same electronics using Alberto Iriberri Andrés (PangoDream) Library.

First, is needed to get the value of ADC pin. This value may vary from 0 to 4096 depending on the voltage applied to it from 0V to 3.3V. So it can be established a constant to calculate the voltage applied to the pin based on its value. This constant, theoretically, will be 3300 / 4096 = 0.8056.

Since the measurement electronics is based on a voltage divider and the voltage applied to the pin is half the voltage of the battery, the constant value should be 0.8056 x 2 = 1.6113. This means, for each unit in ADC pin, represents 1.6113 mVolts applied to it. For instance, if one reads the value of the ADC pin of 2,543, then the voltage applied to the pin should be 2,453 x 1.6113 = 3,952V = 3.95V

ADC pins are not that precise, so the value of the constant should be adjusted to a level considered to be valid for the onboard components. In Alberto Iriberri Andrés case, after doing some tests concluded that the best value for the conversion factor is 1.7.

As mentioned before, calculating the charge level is a direct translation from the voltage we obtained to a charge level by using a table.

All the code to make these calculations is contained in a library Alberto Iriberri Andrés created for that purpose.



References & sources

[1] https://www.pangodream.es/esp32-getting-battery-charging-level

Clone this wiki locally