Learn

analogRead, and what one step of the ADC is worth

Sign up freeor see every lesson
  • 192parts on the bench
  • 25boards running now
  • 1.00xreal time, on every board
Arduino Uno: analogRead on A0live0.000 s 0.00x
Click to open it in the editor
A 10 k knob on A0, the sketch printing the count and the millivolts, and a meter on the same pin.

A digital pin answers one question: is the voltage high or low? An analog pin answers a better one: how high is it? On an Arduino Uno the pins marked A0 to A5 are connected to an analog-to-digital converter, the ADC, which measures the voltage and hands your sketch a whole number from 0 to 1023. Knowing what one step of that number is worth is most of what there is to know about analogRead.

The circuit above is an Uno running its built-in analog sketch, which reads A0 five times a second and prints the raw count and the millivolts it works out from it. A 10 k potentiometer sits across 5 V and ground with its wiper on A0, and a multimeter reads the same pin so you can compare the two.

The knob starts in the middle, where the meter reads 2.502 V and the sketch prints A0 = 512 (2502 mV). Open the circuit in the editor, press Run, open the serial monitor and turn the knob. Three quarters of the way around it prints A0 = 767 (3748 mV) and the meter reads 3.748 V.

Want the step-by-step version? The lesson "Reading a voltage" walks through this with checkpoints.

Open the lesson

Digital pins: two answers and a gap

digitalRead compares the pin with two thresholds, not one. An ATmega328P running from 5 V is guaranteed to read LOW below 1.5 V and HIGH above 3.0 V, and between the two the answer is not defined by the datasheet. That gap is why a slowly changing signal, or a floating input, can read as either, and why the pull-up resistor page matters.

The analog pins are digital pins too: on an Uno, A0 to A5 can be used with digitalRead and digitalWrite as pins 14 to 19. The reverse is not true. The ADC only connects to A0 to A5, and on a Nano A6 and A7 are analog only.

1024 steps of 4.9 mV

The Uno’s ADC is 10 bits, which is 2 to the power 10 = 1024 possible results, 0 to 1023, spread across 0 V to the reference voltage, which by default is the 5 V supply. One step is therefore 5 V / 1024 = 4.88 mV. That is the resolution: a change smaller than about 5 mV may not move the reading at all.

Turning a count back into volts is one line of arithmetic, and the sketch does it in integers: millivolts = raw x 5000 / 1023. For the reading above, 767 x 5000 / 1023 = 3748 mV, which matches the meter’s 3.748 V. With the knob in the middle the count is 511 and the meter reads 2.497 V. Whether to divide by 1023 or 1024 is an old argument: 1024 is the ADC’s own definition, 1023 makes a full-scale reading come out as exactly 5000 mV. The difference is one step, which is smaller than a real Uno’s error anyway.

Resolution is not accuracy

Every reading is a fraction of the reference, so it is only as good as the reference. On a real Uno powered from USB, the 5 V rail is often 4.8 V or so, and every reading is then about four percent high if you assume 5 V. For a ratio, such as a knob position, that cancels out and does not matter. For an absolute voltage it does, and analogReference(INTERNAL) switches to the chip’s own 1.1 V reference, which is steadier and gives 1.07 mV steps for small signals.

A real ADC also jitters by a count or two with nothing changing, from noise on the supply and the pin. Mokxi’s ADC reads the simulated voltage exactly, so a still knob gives a still number here; on the bench, averaging a few readings is normal.

Other boards differ. The Uno R4 can be set to 12 or 14 bits with analogReadResolution. An ESP32 returns 12 bits, 0 to 4095, on a 3.3 V range. The Raspberry Pi Pico’s ADC is 12 bits, though its Arduino core returns 10 unless you ask for more. Always check the range before you do the arithmetic.

Keep the source impedance low

The ADC measures by charging a small capacitor from the pin, and the datasheet asks for the circuit feeding the pin to have a resistance of 10 k or less so that capacitor charges in time. A 10 k potentiometer is at most 2.5 k seen from its wiper, in the middle, so it is well inside that. A divider made of two 1 M resistors is not, and its readings come out low and are dragged towards whichever pin was read before it.

Common mistakes

Putting more than the supply voltage on an analog pin. The pins are rated to the board’s own supply, 5 V on an Uno and 3.3 V on most newer boards, and going over can damage the chip. To measure a 9 V or 12 V battery, bring it down with a voltage divider first. Reading a 3.3 V sensor against a 5 V reference throws away a third of the range. Forgetting the ground: a sensor on its own supply must share GND with the board or the reading means nothing. And doing float arithmetic you do not need: the integer version the sketch uses is exact to the millivolt and much faster on an 8-bit chip.

Questions

What is the resolution of analogRead on an Arduino Uno?

10 bits: a number from 0 to 1023 across 0 V to the reference, which is 5 V by default. One step is 5 / 1024 = 4.88 mV.

How do I convert an analogRead value to volts?

Multiply by the reference voltage and divide by 1023 (or 1024). In integers: millivolts = raw x 5000L / 1023. A reading of 511 is 2497 mV.

Can I measure more than 5 V with an Arduino?

Not directly; the pin must stay within 0 V to the board’s supply. Use a voltage divider to scale it down, for example 10 k over 10 k to halve it, and multiply the reading back up in the sketch.

Why do my analogRead values jump around?

On real hardware, noise on the supply and the pin moves the last bit or two, and a high-resistance source makes it worse. Keep the source under 10 k, add 100 nF from the pin to ground, and average several readings.

Build this for real

Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.