OLED Animation Maker OLED Maker

Arduino Battery Voltage on OLED — A Meter You Can Build Today

Arduino style OLED UI showing numeric readout suitable for a voltage meter

Animations are fun. A voltage readout on a tiny OLED is useful. I use this pattern on robot packs and portable lab boxes so students can see the battery sag under load instead of guessing from a “full” LED that lies.

Warning up front: never put a raw Li-ion pack above 5V straight into an Arduino analog pin. You need a voltage divider (and preferably a fuse / proper battery protection). This guide assumes a simple two-resistor divider into A0.

Parts

  • Arduino Uno or Nano
  • 0.96" I2C SSD1306 OLED
  • Two resistors for the divider — e.g. 100k + 100k (÷2) for up to ~10V packs on a 5V Arduino
  • Battery pack with a safe measurement point (protected pack recommended)

Divider math (keep it honest)

For resistors R1 (from battery+ to A0) and R2 (from A0 to GND):

V_pin = V_battery × R2 / (R1 + R2)
V_battery = V_pin × (R1 + R2) / R2

Example: R1 = R2 = 100k → divide by 2. A 8.4V 2S pack becomes 4.2V at A0 — safe for a 5V Uno. A 12V lead-acid needs a bigger ratio (for example 100k / 47k) so the pin stays under 5V.

Resistor tolerance is ±1% or ±5%. Your reading will be wrong until you calibrate with a multimeter. That is normal — build calibration into the sketch.

Wiring

  • OLED: VCC→5V, GND→GND, SDA→A4, SCL→A5 (Uno)
  • Battery+ → R1 → node → R2 → GND
  • Node → Arduino A0
  • Battery− → Arduino GND (common ground required)

Double-check polarity before connecting a pack. Reverse polarity into the divider can still hurt the pin if you also short something — take a breath, wire once.

Sketch: OLED voltmeter with calibration

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Adafruit_SSD1306 display(128, 64, &Wire, -1);

// Divider: R1 (top) and R2 (bottom). Change to match your resistors.
const float R1 = 100000.0;
const float R2 = 100000.0;
const float DIV = (R1 + R2) / R2;   // 2.0 for equal resistors

// Measure Arduino 5V rail with a meter if you can; USB is often ~4.9–5.1V
const float VREF = 5.0;

// Tweak after comparing OLED vs multimeter (e.g. 1.02 if you read 2% low)
const float CAL = 1.00;

const int PIN = A0;

float readBatteryVolts() {
  // Average a few samples to reduce noise
  long sum = 0;
  for (int i = 0; i < 16; i++) {
    sum += analogRead(PIN);
    delay(2);
  }
  float adc = sum / 16.0;
  float vPin = adc * (VREF / 1023.0);
  return vPin * DIV * CAL;
}

void setup() {
  analogReference(DEFAULT);
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    for (;;);
  }
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
}

void loop() {
  float v = readBatteryVolts();

  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.println(F("Pack voltage"));

  display.setTextSize(3);
  display.setCursor(0, 22);
  display.print(v, 2);
  display.setTextSize(2);
  display.print(F(" V"));

  // Simple bar (0–12V scale — change maxV for your pack)
  const float maxV = 9.0;
  int bar = (int)constrain(v / maxV * 120, 0, 120);
  display.drawRect(0, 54, 124, 8, SSD1306_WHITE);
  display.fillRect(2, 56, bar, 4, SSD1306_WHITE);

  display.display();
  delay(300);
}

Calibrate in five minutes

  1. Measure the pack with a decent multimeter.
  2. Note what the OLED shows.
  3. Set CAL = multimeter / oled (example: 8.20 / 8.00 = 1.025).
  4. Re-upload. Check again under a small load — some packs droop; that is real, not a bug.

Also measure the Uno’s 5V pin while powered from USB. If it is 4.85V, put VREF = 4.85. USB power is rarely a perfect 5.000V.

What this project teaches (beyond the number)

  • Analog input limits and why dividers exist
  • Noise averaging (analogRead is jittery on USB-powered boards)
  • Updating an OLED without flashing the whole UI every microsecond
  • Why “percentage battery” from voltage alone is rough — chemistry curves are not linear

Safety notes I tell students

  • Use protected Li-ion packs. Bare cells + hobby wiring is how benches get scars.
  • Do not power motors from the same weak USB port you use for measurement and expect stable readings.
  • If you monitor a car battery, remember load dumps and spikes — add protection or use a proper module.

Ideas to extend

  • Add a low-voltage warning icon (flash a bitmap when V < threshold).
  • Log min/max since boot.
  • Show mV and a bigger bar for classroom demos.

For icons and bars without hand-packing bitmaps, draw shapes in the shape exporter or drop a small warning glyph from the animation maker.

Related

Add a battery icon animation later

Design a charging/empty glyph, export drawBitmap code, drop it into this meter.

Open the free tool →