Step by Step: Sizing a Voltage Divider for a Sensor Input
There's a moment every embedded developer hits where they stare at a datasheet and realize: the sensor spits out 12V logic, and the microcontroller tolerates exactly 3.3V on its GPIO. Connecting them directly would fry the pin instantly. The fix — a voltage divider — sounds trivial until you actually sit down to pick the resistors. Get the ratio wrong and you're off target. Ignore the load the MCU input presents and your reading drifts. Let's walk through the whole thing properly, with numbers.
What We're Actually Solving
We have a sensor that outputs a signal swinging between 0V and 12V. We need to scale that down to a maximum of 3.3V so it can be read safely by an analog or digital input pin on a 3.3V microcontroller — let's say a Raspberry Pi Pico or an STM32.
The basic voltage divider is two resistors in series, with the output taken from the midpoint:
Vin ──┬── R1 ──┬── Vout
│ │
GND R2
│
GND
The formula is straightforward:
Vout = Vin × (R2 / (R1 + R2))
We want Vout = 3.3V when Vin = 12V, so:
3.3 / 12 = R2 / (R1 + R2) → ratio = 0.275
That means R2 must be 27.5% of the total resistance. Simple so far. But which actual values do you pick?
Step 1 — Choose a Total Resistance Range
This is where most tutorials skip ahead too fast. You can't just pick any pair that satisfies the ratio. Two competing concerns pull in opposite directions:
- Too high (MΩ range): The divider becomes sensitive to the MCU's input impedance. The input pin acts like a resistor in parallel with R2, pulling Vout down from your target. It also makes the circuit noisy and slow to respond.
- Too low (sub-100Ω range): You waste current unnecessarily. At 12V across 100Ω total, you're drawing 120mA — absurd for a passive scaling network.
A practical sweet spot for microcontroller work is usually 10kΩ to 100kΩ total resistance. For a clean mid-range choice, let's target a total resistance of about 47kΩ.
With ratio = 0.275 and Rtotal = 47kΩ:
- R2 = 0.275 × 47,000 = 12,925Ω → nearest standard value: 13kΩ
- R1 = 47,000 − 12,925 = 34,075Ω → nearest standard value: 33kΩ
Let's verify with real standard values:
Vout = 12 × (13,000 / (33,000 + 13,000)) = 12 × (13,000 / 46,000) = 12 × 0.2826 = 3.391V
That's 2.7% over 3.3V — within tolerance for most sensors, but tight. If your MCU datasheet says the absolute maximum on GPIO is 3.6V, you're fine. If it's strict 3.3V, you might want to go slightly lower. We'll come back to this once we account for the loading effect.
Step 2 — Model the Loading Effect
Here's what textbooks often gloss over: the MCU's analog input is not infinitely high impedance. Typical ADC input impedance on a mid-range STM32 or RP2040 is in the range of 50kΩ to several MΩ, depending on sampling mode and whether there's an internal sample-and-hold capacitor.
Let's use a realistic worst-case figure: 50kΩ input impedance on the MCU pin (call it R_load).
When R_load is connected, it appears in parallel with R2. The effective lower resistance becomes:
R2_eff = (R2 × R_load) / (R2 + R_load)
With R2 = 13kΩ and R_load = 50kΩ:
R2_eff = (13,000 × 50,000) / (13,000 + 50,000) = 650,000,000 / 63,000 = 10,317Ω ≈ 10.3kΩ
Now recalculate Vout with the load present:
Vout = 12 × (10,317 / (33,000 + 10,317)) = 12 × (10,317 / 43,317) = 12 × 0.2382 = 2.858V
That's a meaningful shift — from 3.39V to 2.86V. If you were expecting 3.3V and getting 2.86V, your ADC readings would be off by about 13%. In a battery monitoring circuit, that could be the difference between "charge now" and "safe to continue."
Step 3 — Compensate for the Load
Now that we know the loading effect, we can design around it. The approach is to solve for R1 and R2 such that, with R_load in parallel with R2, the output hits exactly 3.3V at 12V input.
Let's define:
- R2_eff = (R2 × R_load) / (R2 + R_load) — this is the effective lower leg
- Target: Vout / Vin = 3.3 / 12 = 0.275
So: R2_eff / (R1 + R2_eff) = 0.275
Rearranging: R1 = R2_eff × (1/0.275 − 1) = R2_eff × 2.636
If we keep R2 = 13kΩ and R_load = 50kΩ, then R2_eff = 10.317kΩ (calculated above).
R1 = 10,317 × 2.636 = 27,194Ω → nearest standard: 27kΩ
Verify with loaded circuit:
Vout = 12 × (10,317 / (27,000 + 10,317)) = 12 × (10,317 / 37,317) = 12 × 0.2765 = 3.318V
That's within 0.5% of our 3.3V target — excellent for a passive network. So our final values are:
- R1 = 27kΩ
- R2 = 13kΩ
Step 4 — Check Power Dissipation
Don't skip this. With 12V across (27k + 13k) = 40kΩ:
I = 12V / 40,000Ω = 0.3mA
Power in R1: P = I² × R = (0.0003)² × 27,000 = 0.00243W = 2.43mW
Power in R2: P = (0.0003)² × 13,000 = 1.17mW
Standard 1/4W (250mW) resistors handle this comfortably. Even 1/8W parts would be fine with enormous margin. No thermal concerns here.
Step 5 — Add a Decoupling Capacitor (Optional but Smart)
If the sensor signal has noise riding on it — which is common in automotive or industrial environments — a small capacitor across R2 creates a low-pass filter. The cutoff frequency is:
f_c = 1 / (2π × R_parallel × C)
Where R_parallel = R1 in parallel with R2 (since from the capacitor's perspective, the source and load are at AC ground). For R1=27kΩ and R2=13kΩ:
R_parallel = (27,000 × 13,000) / (27,000 + 13,000) = 351,000,000 / 40,000 = 8,775Ω
If you want to filter out noise above 1kHz, choose C such that:
C = 1 / (2π × 8,775 × 1,000) = 1 / 55,132,000 = 18nF → use 22nF (standard value)
Solder a 22nF ceramic cap directly across R2 and you'll noticeably clean up noisy readings. Don't use this if you need to track fast-changing signals — the filter will round off the edges.
Final Circuit Summary
Here's the complete design:
- R1: 27kΩ, 1/4W, 1% tolerance (between sensor output and divider midpoint)
- R2: 13kΩ, 1/4W, 1% tolerance (from midpoint to GND)
- C1: 22nF ceramic capacitor across R2 (optional, for noise filtering)
- Output voltage at 12V input (with 50kΩ MCU load): ~3.32V
- Current draw: ~0.3mA continuous
A Few Practical Gotchas
Check your MCU's actual input impedance. The 50kΩ figure used here is a conservative estimate. Some MCUs have much higher impedance in high-speed sampling mode, others lower in low-power modes. Pull the datasheet and look for "input impedance" or "ADC source impedance" — it directly affects how much loading correction you need.
Use 1% tolerance resistors. Standard 5% parts can introduce enough error to push you outside safe voltage limits. 1% metal film resistors cost almost nothing more and significantly tighten the output.
Keep leads short near the MCU pin. A voltage divider with long PCB traces or flying leads acts as an antenna. If you're seeing unexplained ADC jitter, the layout is often the culprit. Route the divider as close to the MCU pin as possible.
The sensor's output impedance matters too. If the sensor has a high output impedance (some older analog sensors do), it adds to R1 effectively, shifting your ratio. In that case, you'd either need to characterize the sensor's output impedance and factor it into your R1 value, or buffer the sensor output with a unity-gain op-amp before the divider.
Wrapping Up
A voltage divider is one of the most elementary circuits in electronics, but sizing it correctly for a real MCU interface involves more than just solving the ratio equation. You need to pick a total resistance that balances noise immunity against power waste, account for the load that the MCU input presents, and verify that your standard resistor values still land within safe voltage limits after all those corrections. The 27kΩ/13kΩ combination derived here gives you a reliable, accurate 12V-to-3.3V scaling network that you can drop into a schematic with confidence.