Skip to content

Battery Voltage

Monitoring Power Before It Fails

Your robot runs on a Li-Ion battery (3.0V - 4.2V range). The ADC only handles up to 3.3V. You can't connect the battery directly.

Solution: A voltage divider scales the battery voltage down to ADC range.

Battery voltage divider circuit

Scaling ratio: 5.1k / (10k + 5.1k) ≈ 1/3

The discharge curve challenge: Li-Ion batteries have a flat voltage curve through most of their capacity. From 80% to 20% charge, voltage barely changes. Then it drops rapidly.

Voltage vs Charge:
  4.2V ──┐
         └────────────────────┐
  3.7V                        │   ← 80% of usage here
  3.0V ───────────────────────┴── ← Sudden drop at end

Li-Ion Battery Discharge Curve Li-Ion discharge curve showing the flat usable region and critical voltage zones

Voltage alone gives poor state-of-charge estimation. But it's sufficient for detecting the critical "low battery" threshold before shutdown.


In embedded systems, monitoring power supply voltage, such as a battery's charge level, is a common task. Although it is not a sensor in the traditional sense, it utilizes analog inputs, so we will cover it here.

Understanding Battery Voltage Measurement

The robot's battery is a single-cell Li-Ion battery with the following characteristics:

  • Fully charged voltage: 4.2V
  • Discharge limit: ~3V (discharging beyond this level can cause damage)
  • Nominal voltage: 3.6V (typical operating range between 80% and 20% charge)

Since the battery voltage can exceed 3.3V (the ADC reference voltage), a voltage divider is used to scale down the battery voltage before feeding it to the ADC.

Voltage Divider Circuit

A resistor divider (10kΩ and 5.1kΩ) is used to reduce the battery voltage before measurement:

\[ V_{\text{ADC}} = V_{\text{battery}} \times \frac{5.1kΩ}{(10kΩ + 5.1kΩ)} \]

The voltage scaling ratio is approximately 1:3, meaning the ADC measures a third of the actual battery voltage.

Battery voltage calculation formula:

\[ V_{\text{battery}} = V_{\text{ADC}} \times 3 \]

The scaled-down voltage is connected to GP28 (ADC2).

Monitoring battery voltage is essential in embedded systems to prevent deep discharge and estimate battery life. However, estimating the State of Charge (SoC) from voltage alone is challenging, especially for Li-Ion batteries.

Why Voltage-Based SoC Estimation is Limited?
  • Li-Ion batteries have a flat voltage curve in the middle of their discharge cycle.
  • This means that between ~80% and ~20% charge, the voltage does not change significantly, making it difficult to determine the exact SoC from voltage alone.
  • More accurate SoC estimation often requires Coulomb counting, which tracks charge and discharge current over time instead of relying solely on voltage.

⚡Hands-on tasks

✅ Task 1 - Reading battery voltage as analog values

Building on the previous example where we used the ADC to read the temperature sensor value, we will now read battery voltage using the ADC.

Example: Reading Battery Voltage

from machine import ADC, Pin
import time

# --- Configuration ---
VREF = 3.3  # ADC reference voltage (V)
VOLTAGE_DIVIDER_RATIO = 3  # Scaling factor due to voltage divider

# Initialize ADC on GP28 (ADC2)
adc_battery = ADC(Pin(28))

def read_battery_voltage():
    """ Reads the battery voltage from the ADC and converts it to real voltage. """
    raw_value = adc_battery.read_u16()  # Read raw 16-bit ADC value (0-65535)

    v_adc = (raw_value / 65535) * VREF  # Convert to actual ADC voltage
    v_battery = v_adc * VOLTAGE_DIVIDER_RATIO  # Convert to actual battery voltage

    return round(v_battery, 2)  # Round to 2 decimal places

while True:
    battery_voltage = read_battery_voltage()

    # Display voltage on the console
    print(f"Battery Voltage: {battery_voltage}V")

    time.sleep(0.1)  # Update every 100ms

🔦 Try This:

  • Observe voltage changes when turn on and off the main switch
  • Compare voltage readings at full charge (4.2V) and near depletion (~3.0V).
Key Takeaways
  • Voltage measurement provides a rough SoC estimate, but accuracy is limited.
  • The middle voltage range (80%-20% SoC) is nearly flat, making it hard to differentiate charge levels.
  • For precise battery monitoring, Coulomb counting (current-based measurement) is preferred, tracking energy in and out over time.

✅ Task 2 - Displaying Battery State of Charge (SoC) as a Percentage

Since a Li-Ion battery does not have a linear voltage-to-charge relationship, direct voltage measurement can only provide an approximate State of Charge (SoC). In this task, we will map the battery voltage to a percentage scale between minimum and maximum voltage values to estimate the SoC.

Objective:

  • Measure the battery voltage using the ADC.
  • Define minimum and maximum voltage levels for the battery.
  • Convert the voltage reading into a SoC percentage (0-100%).
  • Display the battery percentage in the terminal.
How SoC Calculation Works

Since the battery’s minimum voltage is not 0V, we need to scale the ADC reading between the discharge limit (~3.0V) and fully charged level (~4.2V):

$\(\text{SoC (\%)} = \frac{V_{\text{battery}} - V_{\text{min}}}{V_{\text{max}} - V_{\text{min}}} \times 100\)$

Where:

  • \(V_{\text{battery}}\) = Measured battery voltage
  • \(V_{\text{max}}\) = 4.2V (fully charged)
  • \(V_{\text{min}}\) = 3.0V (minimum safe voltage)

➡ Next Steps