If you could only learn one circuit in electronics, it should be the voltage divider. Two resistors. That is it. Yet this deceptively simple arrangement appears in battery monitors, sensor interfaces, audio circuits, biasing networks, and almost every schematic you will ever read.
In this deep dive, we will go from first principles through the math, build five practical circuits, write real ESP32 code, and cover the pitfalls that catch even experienced engineers.
What Is a Voltage Divider?
A voltage divider is a pair of resistors connected in series between a voltage source and ground. The junction between the two resistors produces an output voltage that is a fraction of the input voltage.
Vin
|
[R1]
|
+---- Vout
|
[R2]
|
GND
The output voltage depends entirely on the ratio of R1 and R2. No active components, no ICs, no magic — just Ohm's law at work.
The Formula
Deriving It from Ohm's Law
Since R1 and R2 are in series, the same current flows through both:
I = Vin / (R1 + R2)
The voltage across R2 (which is our output) is:
Vout = I × R2
Vout = Vin × R2 / (R1 + R2)
That is the voltage divider equation:
Vout = Vin x (R2 / (R1 + R2))
Notice that Vout is always less than or equal to Vin. When R2 is much larger than R1, Vout approaches Vin. When R2 is much smaller, Vout approaches zero.
The Division Ratio
The term R2 / (R1 + R2) is called the division ratio (often written as k). It ranges from 0 to 1 and tells you what fraction of the input voltage appears at the output.
| R1 | R2 | Ratio (k) | If Vin = 12V, Vout = |
|---|---|---|---|
| 10k | 10k | 0.500 | 6.00V |
| 10k | 3.3k | 0.248 | 2.98V |
| 27k | 10k | 0.270 | 3.24V |
| 100k | 33k | 0.248 | 2.98V |
| 1k | 2k | 0.667 | 8.00V |
| 47k | 10k | 0.175 | 2.11V |
Worked Example
Problem: You need 3.3V from a 5V source. What resistor values work?
We need k = 3.3 / 5 = 0.66, so:
R2 / (R1 + R2) = 0.66
Rearranging: R1 = R2 x (1 - k) / k = R2 x (0.34 / 0.66) = R2 x 0.515
If R2 = 10k, then R1 = 5.15k. The nearest standard value is 5.1k. Let us verify:
Vout = 5V × 10k / (5.1k + 10k) = 5 × 10000 / 15100 = 3.31V
Close enough for most applications.
Practical Application 1: Battery Voltage Monitoring
The Problem
You want to monitor a 12V lead-acid battery with an ESP32, but the ESP32 ADC only accepts 0-3.3V. Feeding 12V directly into a GPIO pin will destroy the chip instantly.
The Solution
Use a voltage divider to scale 12V down to the 0-3.3V range.
We need: Vout(max) = 3.3V when Vin = 14.4V (fully charged battery with charger)
k = 3.3 / 14.4 = 0.229
Using R1 = 100k and R2 = 30k (close enough at k = 0.231):
Vout = 14.4V × 30k / (100k + 30k) = 14.4 × 0.2308 = 3.32V
At 12V nominal: Vout = 12 × 0.2308 = 2.77V
At 10.5V (discharged): Vout = 10.5 × 0.2308 = 2.42V
The ESP32 ADC sees a safe voltage range of 2.42V to 3.32V, which it can read accurately.
Why 100k/30k instead of 1k/300 ohm? Power dissipation. With 100k + 30k = 130k total resistance, the divider draws only 12V / 130k = 0.09mA from the battery. With 1k + 300 ohm = 1.3k, it would draw 9.2mA — wasteful for a battery-powered system.
Practical Application 2: Logic Level Shifting (5V to 3.3V)
The Problem
A 5V sensor outputs a digital or analog signal, but your ESP32 GPIO is not 5V tolerant (despite what some forum posts claim).
The Solution
A quick voltage divider brings 5V logic down to 3.3V:
k = 3.3 / 5.0 = 0.66
Use R1 = 1k and R2 = 2k:
Vout = 5V × 2k / (1k + 2k) = 5 × 0.667 = 3.33V
Important: This only works for unidirectional, low-frequency signals. For bidirectional signals (like I2C), use a proper level shifter IC. For signals above a few hundred kHz, the parasitic capacitance of resistors will round off your edges — use a dedicated buffer instead.
Practical Application 3: Light Sensor with an LDR
An LDR (Light Dependent Resistor) is a variable resistor whose resistance drops as light increases — typically from 1M ohm in darkness to a few hundred ohms in bright light. Pair it with a fixed resistor in a voltage divider, and you get a light-sensitive analog voltage.
Circuit
3.3V
|
[LDR] (R1 — variable, light-dependent)
|
+---- Vout (to ESP32 ADC)
|
[10k] (R2 — fixed)
|
GND
- Bright light: LDR resistance drops to ~500 ohm. Vout = 3.3 x 10k / (500 + 10k) = 3.14V (high reading)
- Dim light: LDR resistance rises to ~50k. Vout = 3.3 x 10k / (50k + 10k) = 0.55V (low reading)
- Darkness: LDR resistance hits 500k+. Vout = 3.3 x 10k / (500k + 10k) = 0.065V (near zero)
The 10k fixed resistor is chosen as a middle-ground value that gives good sensitivity across the LDR's useful range. If your application is mostly outdoors in bright conditions, a smaller fixed resistor (1k-4.7k) gives better resolution in the bright range.
Practical Application 4: Audio Signal Attenuation
In audio circuits, voltage dividers are used to reduce signal levels — for example, attenuating a line-level signal (~1V peak-to-peak) down to microphone level (~10mV) for an ADC input, or building a passive volume control.
For a 10:1 attenuation (20dB):
k = 0.1
R1 = 9k, R2 = 1k
A potentiometer is the classic implementation here — it is literally an adjustable voltage divider. A 10k audio-taper pot between your signal source and amplifier input gives you a smooth volume control.
Tip: For audio dividers, keep total impedance between 1k and 100k. Too low and you load the source. Too high and you pick up noise.
Practical Application 5: Setting Reference Voltages
Many ICs need a precise reference voltage. An adjustable voltage regulator like the LM317 uses a voltage divider to set its output:
Vout = 1.25V × (1 + R2/R1)
For a 5V output: R1 = 240 ohm, R2 = 720 ohm (or a 1k trimmer pot).
Op-amp circuits frequently use voltage dividers to set bias points, threshold voltages, and reference levels. A divider feeding the non-inverting input of a comparator sets the trip point for your circuit.
ESP32 Code: Reading a Voltage Divider
Basic ADC Reading with Calibration
// Battery voltage monitor via voltage divider
// R1 = 100k, R2 = 30k
// Vin(max) = 14.4V -> Vout(max) = 3.32V
const int ADC_PIN = 34; // ADC1 channel (GPIO 34)
const float R1 = 100000.0; // 100k ohm
const float R2 = 30000.0; // 30k ohm
const float ADC_REF = 3.3; // ADC reference voltage
const int ADC_RESOLUTION = 4095; // 12-bit ADC
const int NUM_SAMPLES = 64; // Averaging for noise reduction
// Calibration factor — measure actual Vin with a multimeter
// and adjust this until the reading matches.
const float CALIBRATION = 1.015;
float readBatteryVoltage() {
long total = 0;
for (int i = 0; i < NUM_SAMPLES; i++) {
total += analogRead(ADC_PIN);
delayMicroseconds(100);
}
float adcAverage = (float)total / NUM_SAMPLES;
// Convert ADC reading to voltage at the divider output
float vOut = (adcAverage / ADC_RESOLUTION) * ADC_REF;
// Reverse the divider equation to get actual battery voltage
// Vout = Vin * R2/(R1+R2), so Vin = Vout * (R1+R2)/R2
float vIn = vOut * (R1 + R2) / R2;
return vIn * CALIBRATION;
}
void setup() {
Serial.begin(115200);
analogReadResolution(12);
// Use 11dB attenuation for full 0-3.3V range
analogSetAttenuation(ADC_11db);
}
void loop() {
float voltage = readBatteryVoltage();
Serial.printf("Battery: %.2fV\n", voltage);
delay(1000);
}
Why 64 samples? The ESP32 ADC is notoriously noisy. Averaging 64 readings gives roughly 3 extra bits of effective resolution and smooths out jitter.
Battery Percentage Estimation
// Lead-acid battery percentage lookup
// Based on 12V nominal (6-cell) battery at rest
struct VoltagePoint {
float voltage;
int percentage;
};
const VoltagePoint DISCHARGE_CURVE[] = {
{12.70, 100},
{12.50, 90},
{12.42, 80},
{12.32, 70},
{12.20, 60},
{12.06, 50},
{11.90, 40},
{11.75, 30},
{11.58, 20},
{11.31, 10},
{10.50, 0}
};
const int CURVE_POINTS = sizeof(DISCHARGE_CURVE) / sizeof(VoltagePoint);
int estimateBatteryPercent(float voltage) {
if (voltage >= DISCHARGE_CURVE[0].voltage) return 100;
if (voltage <= DISCHARGE_CURVE[CURVE_POINTS - 1].voltage) return 0;
// Linear interpolation between known points
for (int i = 0; i < CURVE_POINTS - 1; i++) {
if (voltage >= DISCHARGE_CURVE[i + 1].voltage) {
float range = DISCHARGE_CURVE[i].voltage
- DISCHARGE_CURVE[i + 1].voltage;
float delta = voltage - DISCHARGE_CURVE[i + 1].voltage;
int pctRange = DISCHARGE_CURVE[i].percentage
- DISCHARGE_CURVE[i + 1].percentage;
return DISCHARGE_CURVE[i + 1].percentage
+ (int)(delta / range * pctRange);
}
}
return 0;
}
void loop() {
float voltage = readBatteryVoltage();
int percent = estimateBatteryPercent(voltage);
Serial.printf("Battery: %.2fV (%d%%)\n", voltage, percent);
delay(5000);
}
The Loading Effect: Why Voltage Dividers Sag
Here is where beginners get burned. The voltage divider equation assumes no current flows out of the output node. In reality, whatever you connect to Vout draws current, and that changes everything.
What Happens Under Load
When you connect a load resistance (R_load) in parallel with R2, the effective lower resistance becomes:
R2_eff = (R2 × R_load) / (R2 + R_load)
This is always less than R2, so the division ratio drops and Vout sags below what you calculated.
Worked Example
Your divider: R1 = 10k, R2 = 10k, Vin = 5V. Expected Vout = 2.5V.
Now connect a 10k load:
R2_eff = (10k × 10k) / (10k + 10k) = 5k
Vout = 5V × 5k / (10k + 5k) = 5 × 0.333 = 1.67V
Instead of 2.5V, you get 1.67V — a 33% error. The load has completely changed the operating point.
The Rule of Thumb
For less than 1% error from loading, the load resistance should be at least 100 times greater than R2:
R_load > 100 × R2
The ESP32 ADC input impedance is roughly 1M ohm or more when using appropriate attenuation settings, so a divider with R2 = 10k (where 100 x R2 = 1M) will be minimally affected. But if you are feeding a circuit with lower input impedance, you must account for the loading effect.
Thevenin Equivalent: Output Impedance of a Divider
Every voltage divider can be modelled as a Thevenin equivalent circuit: an ideal voltage source (Vth) in series with an output resistance (Rth).
Vth = Vin × R2 / (R1 + R2) (the open-circuit voltage)
Rth = R1 × R2 / (R1 + R2) (R1 parallel with R2)
This Rth is the output impedance of the divider. It tells you how "stiff" the output is — lower Rth means less voltage sag under load.
For R1 = R2 = 10k: Rth = 5k. Not great for driving anything. For R1 = R2 = 100 ohm: Rth = 50 ohm. Much stiffer, but draws 25mA from a 5V source.
This is the fundamental trade-off: lower resistance = stiffer output but higher quiescent current.
When NOT to Use a Voltage Divider
Never Use It as a Power Supply
This is the single most common beginner mistake. You cannot power a device through a voltage divider.
Consider: you want to power an ESP32 (which draws 100-240mA during Wi-Fi transmission) from 5V through a divider to get 3.3V. With R1 = 5.1k, R2 = 10k:
Rth = 5.1k × 10k / (5.1k + 10k) = 3.38k
At 240mA load: voltage drop across Rth = 0.24A x 3380 ohm = 811V (obviously impossible — the divider simply collapses to near-zero output).
Even at 10mA: drop = 33.8V. The divider cannot deliver this current.
Use a voltage regulator instead (AMS1117-3.3, LM7805, or a buck converter for higher efficiency). Voltage dividers are for signal conditioning, not power delivery.
Other Cases to Avoid
- High-current loads: Anything drawing more than a few microamps relative to the divider's bias current.
- Rapidly switching signals at high frequency: Parasitic capacitance creates an RC filter that rounds edges. Use a resistive divider only for DC or low-frequency signals.
- Bidirectional level shifting: A voltage divider only works in one direction. For I2C or SPI, use a MOSFET-based level shifter or a dedicated IC like the TXS0108E.
- High-precision voltage references: Even 1% resistors give you at best 2% accuracy in the output. Use a dedicated voltage reference IC for precision work.
Resistor Selection: The Trade-offs
High Values (100k-1M)
Advantages: Very low power consumption. A 200k total resistance divider from 12V draws only 60uA.
Disadvantages: Higher thermal noise (Johnson-Nyquist noise scales with resistance), more susceptible to electromagnetic interference, and more sensitive to the loading effect. Leakage currents on PCB surfaces (especially in humid conditions) can introduce errors when resistances exceed a few hundred kilohms.
Low Values (100 ohm - 1k)
Advantages: Low noise, stiff output, less sensitive to loading and PCB leakage.
Disadvantages: High power consumption. A 200 ohm divider from 12V draws 60mA and dissipates 720mW — significant heat and wasted energy.
The Sweet Spot
For most signal-conditioning applications with microcontrollers: 10k to 100k total resistance. This balances power consumption, noise, and loading effect.
For battery monitoring where every microamp counts: 100k to 500k, but add a 100nF capacitor across R2 to filter noise.
Precision: Using 1% Resistors
Standard resistors have 5% tolerance (gold band). This means your carefully calculated 3.30V output could actually be anywhere from 3.12V to 3.49V.
Worst-Case Error Analysis
With R1 = 100k (5%) and R2 = 30k (5%), from 12V:
- Best case (R1 low, R2 high): Vout = 12 x 31.5k / (95k + 31.5k) = 2.99V
- Nominal: Vout = 12 x 30k / (100k + 30k) = 2.77V
- Worst case (R1 high, R2 low): Vout = 12 x 28.5k / (105k + 28.5k) = 2.56V
That is a spread of 0.43V — enormous if you are trying to measure battery voltage accurately.
With 1% resistors, the spread narrows to about 0.09V. For ADC work, always use 1% (or better) metal film resistors. They cost only a few paise more per piece and are well worth it.
Calibration in Software
Even with 1% resistors, calibrate in software. Measure the actual battery voltage with a multimeter, read the ADC value, and compute a correction factor. Store it in EEPROM/NVS so it persists across reboots. The code example earlier includes a CALIBRATION constant for exactly this purpose.
The Potentiometer: An Adjustable Voltage Divider
A potentiometer (pot) is mechanically a voltage divider with a sliding contact (wiper). The three terminals correspond to Vin, Vout, and GND of our divider circuit.
Common uses:
- Volume control in audio circuits (10k audio-taper pot)
- Threshold adjustment for comparator circuits
- Calibration trim during manufacturing (multi-turn trimpot)
- User input — reading a knob position with an ADC
Potentiometer with ESP32
const int POT_PIN = 35; // Connect pot wiper to GPIO 35
void setup() {
Serial.begin(115200);
analogReadResolution(12);
}
void loop() {
int raw = analogRead(POT_PIN);
float voltage = raw * 3.3 / 4095.0;
int position = map(raw, 0, 4095, 0, 100);
Serial.printf("Position: %d%% Voltage: %.2fV\n", position, voltage);
delay(100);
}
Connect the pot's outer terminals to 3.3V and GND, and the wiper to the ADC pin. Turning the knob sweeps the output from 0V to 3.3V.
Capacitive Voltage Dividers
For AC signals, capacitors can replace resistors. The impedance of a capacitor is:
Xc = 1 / (2 * pi * f * C)
A capacitive divider with C1 and C2:
Vout = Vin × Xc2 / (Xc1 + Xc2) = Vin × C1 / (C1 + C2)
Note the inversion: the smaller capacitor has the higher impedance, so it drops more voltage. This is opposite to the resistive case.
Capacitive dividers are used in:
- AC mains voltage sensing (safely stepping down 230V AC for measurement)
- RF signal attenuation
- Oscillator feedback networks
- Touch sensing circuits
Warning: Capacitive dividers connected to mains voltage are dangerous. They do not provide galvanic isolation. Never use them in projects unless you fully understand the safety implications. For mains voltage sensing, a proper isolation transformer or an optocoupled sensor module is strongly recommended.
Common Mistakes
Mistake 1: Using a Divider as a Power Supply
We covered this above, but it bears repeating because it is so common. A divider with 10k resistors cannot deliver milliamps. Use a regulator.
Mistake 2: Ignoring Load Impedance
If your load resistance is comparable to R2, the output voltage will be significantly lower than calculated. Always check R_load >> R2.
Mistake 3: Wrong Resistor Ratio (R1 and R2 Swapped)
If you swap R1 and R2, you get Vout = Vin - (what you wanted). Double-check which resistor connects to the input and which connects to ground. R2 is always the one connected to ground.
Mistake 4: Exceeding ADC Input Voltage
If your input voltage can spike above the expected maximum, your divider output might exceed the ADC's maximum input voltage. Add a 3.3V Zener diode from Vout to GND as overvoltage protection:
Vin
|
[R1]
|
+---- Vout --- to ESP32 ADC
|
[R2] [3.3V Zener] (Zener in parallel with R2)
| |
GND GND
Mistake 5: Forgetting About Temperature
Resistor values drift with temperature. Carbon film resistors have a temperature coefficient of around 200-500 ppm/degC, while metal film resistors are much better at 25-50 ppm/degC. For outdoor battery monitoring in Indian conditions (where temperatures can swing from 5 to 50 degC), use metal film resistors.
Mistake 6: Not Accounting for ESP32 ADC Non-Linearity
The ESP32 ADC is known for poor linearity at the extremes (below 0.1V and above 3.1V). Design your divider so the output stays in the 0.15V to 2.9V range for best accuracy. The ESP-IDF includes ADC calibration functions — use them.
Quick Reference: Common Resistor Pairs for 3.3V Output
| Input Voltage | R1 | R2 | Actual Vout | Divider Current |
|---|---|---|---|---|
| 5V | 5.1k | 10k | 3.31V | 0.33mA |
| 9V | 56k | 33k | 3.34V | 0.10mA |
| 12V | 100k | 39k | 3.37V | 0.09mA |
| 14.4V | 100k | 30k | 3.32V | 0.11mA |
| 24V | 100k | 15k | 3.13V | 0.21mA |
| 36V | 100k | 10k | 3.27V | 0.33mA |
| 48V | 150k | 10k | 3.00V | 0.30mA |
All values use standard E24 series resistors. Use 1% tolerance for ADC applications.
Summary
The voltage divider is the Swiss Army knife of electronics. With just two resistors, you can:
- Scale down voltages for safe ADC reading
- Shift logic levels between 5V and 3.3V systems
- Build sensor interfaces with variable resistors like LDRs and thermistors
- Attenuate audio signals
- Set reference and bias voltages
The key things to remember:
- Vout = Vin x R2 / (R1 + R2) — commit this to memory
- Never use a divider as a power supply — it cannot deliver current
- R_load must be much greater than R2 to avoid voltage sag
- Use 1% metal film resistors for any measurement application
- Calibrate in software for the best accuracy
- Add overvoltage protection (Zener diode) when monitoring unpredictable sources
Build one on a breadboard today. Grab a couple of resistors from the parts bin, wire them up, and measure the output with a multimeter. The best way to internalize this circuit is to see it working with your own hands.



