Measure Battery Voltage with Arduino and Display It on an LED Bar

Engineering illustration: Measure Battery Voltage with Arduino and Display It on an LED Bar

An Arduino analog input can measure battery voltage and display it on a ten-segment LED bar, but the voltage must first be reduced to a safe input range. This build measures up to about 15V through a 5:1 divider and averages multiple samples for a more stable result.

Important: Never connect a battery above the Arduino ADC reference directly to A0. This indicator is not a charger or a protection circuit, especially for lithium batteries.

Edition note: This English edition was technically revised and published in August 2026. The original Arabic article was published on July 28, 2021.

Measurement principle

The 10-bit ADC in an Arduino Uno converts the range from ground to its reference voltage into codes from 0 to 1023. A 30kΩ resistor from battery positive to the measurement node and a 7.5kΩ resistor from that node to ground form a divider ratio of about 5:1. A 15V battery therefore produces about 3V at A0.

The general equation is Vbattery = ADC × (Vref / 1023) × ((R1 + R2) / R2). Measure the board's actual 5V rail with a multimeter and use that value as Vref when better accuracy is required.

Parts and wiring

  • Arduino Uno and a ten-segment LED bar or ten individual LEDs.
  • Ten 220Ω or 330Ω current-limiting resistors, one per LED.
  • 30kΩ and 7.5kΩ divider resistors, preferably 1% tolerance.
  • Optional 100nF capacitor from A0 to GND to reduce high-frequency noise.
ConnectionRoute
Battery positiveThrough R1=30kΩ to the A0 node
A0 nodeThrough R2=7.5kΩ to GND
Battery negativeArduino GND
LED segmentsD2 through D11, each through its own resistor

Arduino sketch

const byte VOLTAGE_PIN = A0;
const byte ledPins[10] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11};

const float VREF = 5.00;       // Replace with the measured 5V rail
const float R1 = 30000.0;
const float R2 = 7500.0;
const float DIVIDER_RATIO = (R1 + R2) / R2;
const float DISPLAY_MAX_VOLTAGE = 15.0;

float readBatteryVoltage() {
  unsigned long sum = 0;
  const byte samples = 16;
  for (byte i = 0; i < samples; i++) {
    sum += analogRead(VOLTAGE_PIN);
    delay(3);
  }
  float raw = sum / float(samples);
  float pinVoltage = raw * (VREF / 1023.0);
  return pinVoltage * DIVIDER_RATIO;
}

void showLevel(float voltage) {
  int lit = int((voltage / DISPLAY_MAX_VOLTAGE) * 10.0 + 0.5);
  lit = constrain(lit, 0, 10);
  for (byte i = 0; i < 10; i++) {
    digitalWrite(ledPins[i], i < lit ? HIGH : LOW);
  }
}

void setup() {
  Serial.begin(9600);
  for (byte i = 0; i < 10; i++) pinMode(ledPins[i], OUTPUT);
}

void loop() {
  float voltage = readBatteryVoltage();
  showLevel(voltage);
  Serial.print("Battery voltage: ");
  Serial.print(voltage, 2);
  Serial.println(" V");
  delay(500);
}

Calibration and limitations

Compare the result with a trusted multimeter at several voltages, then adjust Vref or the divider ratio if the error is consistent. Recalculate resistor power for higher voltages and add a fuse and reverse-polarity protection in permanent installations.

The ten LEDs represent a fraction of the configured 0–15V measurement span; they do not provide an accurate state-of-charge percentage. Voltage-to-charge relationships vary with battery chemistry, load, temperature, and rest time. A true fuel gauge requires a method designed for the specific battery system.

Leave your comment

*
*
Only registered users can leave comments.