From a number to volts
analogRead gives a count, not volts. The count's share of full scale, times the voltage the board measures against, is SIG; five times SIG is the input. On an ESP32 the core does the first step for you, and does it better.
A count is a fraction
An analog pin does not report volts. It reports how far up its range the voltage is, as a whole number: 0 at the bottom, the largest count at the top. On an Uno that range is 0 to 1023 against its 5 V supply. On a Pico running arduino-pico it is 0 to 1023 against 3.3 V, unless the sketch asks for 12 bits.
So a count is a fraction of the board's reference voltage:
SIG = count × VREF / ADC_MAX
input = SIG × 5An Uno reading 368 has SIG at 368 × 5.0 / 1023, which is 1.80 V, and the input at five times that, 8.99 V.
One step of the input
The count moves in whole steps, so the input does too. On an Uno one count is 5 V / 1023, about 4.9 mV on SIG, and five times that on the terminal: about 24 mV. A 9 V battery reads to the nearest fortieth of a volt, which is finer than its own voltage stays still.
On a Pico at the default 10 bits, one count is about 16 mV of input. Call
analogReadResolution(12) and change ADC_MAX to 4095, and it is about 4 mV.
The ESP32 does its own conversion
The ESP32 and ESP32-S3 have a 12-bit ADC, 0 to 4095, but a count there is not a clean fraction of 3.3 V. With the Arduino core's default setting the ADC reads only to about 3.1 V, and its response bends near both ends. Dividing a raw count by 4095 and multiplying by 3.3 gives a number that is off by different amounts at different voltages.
Each chip carries calibration data for its own ADC. analogReadMilliVolts
applies it and returns SIG in millivolts, so the sketch divides by 1000 and
multiplies by five. MicroPython's read_uv does the same in microvolts. That
is why the sketches treat the ESP32s separately: not a different formula, but a
better first step.
When it does not work
The ATmega328P datasheet's formula uses 1024, and 1023 is the largest count the Uno returns. The difference is a tenth of a percent, smaller than the resistors' tolerance, and calibration absorbs it either way. The sketches use 1023 so that the top count reads as the top voltage.
Something in your sketch called analogReadResolution(12). That is fine and gives four times finer steps; change ADC_MAX to 4095 to match, or every voltage reads four times too high.
Because the ESP32's ADC is not a straight line, and its top is about 3.1 V rather than 3.3 V. A raw count times 3.3 / 4095 is wrong by different amounts at different voltages. analogReadMilliVolts, and read_uv in MicroPython, apply the calibration the chip carries for exactly this.
The Uno measures against its own 5 V supply, and that supply comes from whatever powers the board. A different cable or port can move it by a tenth of a volt or more, and every reading moves with it. Calibrate on the supply you will actually use.
One number from a multimeter, and sixteen readings instead of one.
Calibrating and averaging →Edit this page — content/books/voltmeter/from-a-number-to-volts.mdx
Questions about this product
See what other owners have asked, and read their solutions.
Voltmeter
Loading discussions…
Discuss this article
Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.