Potentiometer knob with a staircase waveform on dark background

ADC Resolution: What 10-Bit vs 12-Bit Actually Buys You

ADC resolution is the number of steps an analog-to-digital converter divides its voltage range into: a 10-bit ADC gives 1024 steps and a 12-bit ADC gives 4096, so 12-bit can distinguish voltage differences four times smaller than 10-bit over the same range. On a 5V Arduino Uno R3, each 10-bit step is about 4.9mV; on a 3.3V ESP32 with a 12-bit ADC, each step is about 0.8mV. More bits mean finer steps, not more accuracy. A noisy sensor, an unstable reference voltage, or a badly wired breadboard can make the extra bits meaningless, which is why understanding resolution is really about knowing when it helps and when it is wasted.

What an ADC actually does

Microcontrollers live in a world of numbers, but sensors speak in voltages. An ADC (analog-to-digital converter) bridges the two: it samples the voltage on a pin, compares it against a reference voltage, and reports the result as an integer. The reference defines the top of the scale. On the Uno, the default reference is the 5V supply, so analogRead maps 0V to 0 and 5V to 1023.

Resolution is how many distinct integers the ADC can output. Ten bits means 2¹⁰ = 1024 possible values (0 to 1023). Twelve bits means 4096 values. Sixteen bits, found on dedicated ADC chips like the ADS1115, means 65536. Each extra bit doubles the number of steps and halves the smallest voltage difference you can resolve.

The step-size arithmetic

Step size = reference voltage ÷ number of steps. Work it once and it sticks:

  • Uno, 10-bit, 5V reference: 5 ÷ 1024 ≈ 4.9mV per count
  • ESP32, 12-bit, 3.3V range: 3.3 ÷ 4096 ≈ 0.8mV per count
  • ADS1115, 16-bit, ±4.096V range: about 0.125mV per count

Read that in reverse to see what you can detect. If your temperature sensor outputs 10mV per °C, the Uno's 4.9mV step means you can resolve about half a degree. Wanting 0.1°C readings from that sensor on a 5V reference is arithmetic you cannot win; the ADC literally cannot represent the difference.

Resolution is not accuracy

This is the most important sentence in this article: more bits give you finer steps, not more truthful readings. Accuracy depends on the reference voltage being stable and known, on noise, and on the sensor itself. The Uno's default reference is whatever USB delivers, often 4.8V to 5.1V and moving. A 2% wobble in the reference is a 2% wobble in every reading, which swamps the 0.1% granularity of 10 bits. The ESP32's built-in ADC is famously non-linear at the extremes of its range despite its 12 bits. A 16-bit reading of a noisy signal is a very precise measurement of noise.

The practical hierarchy: first quieten the signal (short wires, decoupling capacitors, sensor grounded properly), then stabilise the reference (the Uno can use its internal 1.1V reference or an external one via the AREF pin), and only then do extra bits pay off.

Worked example: a potentiometer on an Arduino Uno R3

Push a 10kΩ potentiometer into a 400-point breadboard. Outer legs to 5V and GND with Dupont jumper wires, middle leg (the wiper) to A0. The pot forms an adjustable voltage divider spanning the full 0 to 5V range.

analogRead(A0) returns 0 at one end, 1023 at the other. Convert to volts with value * 5.0 / 1023.0. Now turn the shaft as gently as you can while printing values: you will see single-count changes, each representing 4.9mV of wiper movement. Then hold the pot perfectly still and watch the readings dance by a count or two anyway. That dance is noise, and it is your daily reminder that the last bit of any ADC is a suggestion. Averaging 10 readings in software steadies it nicely.

Where this bites you

The classic beginner mistake is chasing resolution while ignoring the reference. A battery-powered project reads a sensor via the 5V rail reference, and as the battery sags from 5V to 4.6V over an evening, every reading drifts upward by 8%, because the ADC reports a ratio of signal to reference, not an absolute voltage. The sensor did not drift; the yardstick shrank. Fixes: use the internal 1.1V reference for small signals (analogReference(INTERNAL) on the Uno), use a ratiometric sensor whose output scales with the same supply, or measure the actual rail voltage and correct in software.

A close second: comparing single readings instead of averages, then concluding the sensor is broken because consecutive values differ. Averaging is not cheating. Nearly every commercial instrument does it.

FAQ

Does the map() function give me more resolution?

No. map(value, 0, 1023, 0, 5000) just rescales the same 1024 steps into millivolt-flavoured numbers. The gaps between representable values scale up with them. No software transformation can recover information the ADC never captured.

When do I actually need an external 16-bit ADC?

When the signal changes you care about are smaller than a few millivolts and you have already controlled noise: load cells via amplifiers, thermocouples, precision battery monitoring. For potentiometers, LDRs, soil moisture probes, and most hobby sensors, 10 bits is genuinely enough, and cleaner wiring beats more bits every time.

Why does my ADC reading change when I touch the wire?

An analog input with a high-impedance source is easily disturbed, and your body couples in 50Hz hum from the 230V mains all around you. Keep sensor wires short, and if a reading must travel far, buffer it or send it digitally instead.

If you are picking sensors for a project and wondering whether your board's ADC is up to the job, Compoden's AI build assistant Soldr can plan the whole signal chain for you.

Back to blog