Skip to content

Lesson11: Reading Battery Voltage and Charging Status

1. Objectives

In this lesson, the ADC is used to read the voltage after it passes through the battery voltage divider. The battery voltage is then calculated based on the voltage-divider resistors shown in the schematic. The raw logic level of the charging status pin is also read to observe the status of the charging IC.

2. Prerequisites

  • Complete the ESP32-S3 environment setup in Lesson01.
  • This lesson uses the ADC and GPIO APIs built into Arduino-ESP32. No additional third-party libraries are required.

How to add the library files:

  • No additional third-party libraries are required for this lesson. Use the ADC/GPIO APIs included with the ESP32 3.3.3 board package.

3. Arduino IDE Instructions

  1. Open Lesson11_Battery_Monitor.ino in Arduino IDE. lesson_1

  2. Confirm that the board settings match those in Lesson01. lesson_2

  3. Click Verify to compile the sketch. lesson_3

  4. Click Upload to flash the sketch. Open Serial Monitor and set the baud rate to 115200. lesson_4

4. Hardware Instructions

  1. Connect the development board to the computer using a USB data cable, and then open Serial Monitor.

lesson_5

  1. Observe the battery ADC value in millivolts, the calculated battery voltage, and the raw CHRG logic level.

  2. Connect or disconnect the charging cable and observe whether the raw CHRG logic level changes.

  3. If the voltage is clearly abnormal, first verify that the battery connection, power supply status, and ADC voltage-divider circuit are working properly.

5. Key Code Explained

constexpr float kUpperResistorKiloOhms = 100.0f;
constexpr float kLowerResistorKiloOhms = 137.0f;
constexpr float kDividerRatio =
    kLowerResistorKiloOhms / (kUpperResistorKiloOhms + kLowerResistorKiloOhms);

The battery voltage cannot be applied directly to the ADC and must first pass through a resistor voltage divider. kDividerRatio represents the proportion of the battery voltage that the ADC actually receives. After measuring the voltage at the ADC input, the battery voltage can be calculated by dividing the measured voltage by this ratio.

uint32_t millivoltSum = 0;
for (uint8_t sample = 0; sample < kSampleCount; ++sample) {
  millivoltSum += analogReadMilliVolts(kBatteryAdcPin);
  delay(kSampleDelayMs);
}
adcMillivolts = static_cast<float>(millivoltSum) / kSampleCount;

ADC readings fluctuate slightly, so the program takes 20 consecutive readings and calculates their average. analogReadMilliVolts() returns a millivolt value calibrated by Arduino-ESP32, making it more suitable than the standard analogRead() for directly explaining voltage measurements.

analogReadResolution(12);
analogSetAttenuation(ADC_11db);
const int chargeStatusRaw = digitalRead(kChargeStatusPin);

analogReadResolution(12) sets the ADC resolution to 12 bits, while ADC_11db increases the measurable voltage range, making it suitable for reading the divided battery voltage. digitalRead() reads the raw logic level of the charging status pin. This lesson does not attempt to interpret the status of the charging IC; it simply allows students to observe the hardware signal first.

Download the Lesson 11 code