John L Errington MSc

John Errington's Experiments with an Arduino

How the Arduino ADC measures an input voltage

The system on an Arduino chip that measures an input voltage is a "Successive Approximation Analog to Digital Converter".

Here is a block diagram showing the important parts:

ADC figure

How it works

The first step is that the applied voltage Vin is "locked" by the Sample and Hold circuit. (As the conversion process proper has not yet started I've called this clock cycle zero.)

After that the Successive Approximation register and control logic (SAR) applies a series of ten "test value" numbers to the DAC.

The corresponding voltage Vt is compared with the "locked" signal, Vi, by the comparator. This returns a logic signal K to the SAR as follows: If Vt > Vi k=1; else k=0.

If the voltage Vt generated by the DAC is bigger than Vi the test value is removed and a smaller value tried. Otherwise the test value is left and a another test value added. The process can be seen in the chart below.

ADC data

When the last test value has been applied the comparator output is used to apply any final correction to the data value. Then on the last clock cycle (now 13 in all) the result is recorded and conversion is complete.

ADC conversion chart

In effect we have divided the input voltage range into a series of steps. The smallest change we can measure is between one step and the next. In all there are 1024 steps, corresponding to values N of 0 to 1023, so the height q of each step is q=Vref/1024.

If you would like to try different values you can download the excel spreadsheet I used.

Converting a measurement from a number to a voltage

The result from our measurement above shows a reading of 736 or 0B10 1110 0000 for an input of 3.597V.
To convert this to a voltage reading we need to multiply the reading by the size of step (q).

So Vmeasured = N * Vref / 1024

and for our reading of 736 Vmeasured= 736 * 5.000 / 1024 = 3.5938 Volts

CORRECTION

To be strictly accurate our reading lies in the band between 736 * 5.000 / 1024 and 737 * 5.000 / 1024 volts, so we can add a very small correction factor like this

Vmeasured = (N + 0.5) * Vref / 1024

so our reading of 736 gives Vmeasured= 736.5 * 5.000 / 1024 = 3.5962 Volts

CAUTION

We can only be certain of measurements that do not exceed the range of the ADC. If we apply a voltage of a little more than 5V to the ADC it will do no harm - but the result will not be correct. So we can not legitimately convert a reading of 1023 to a voltage.

Its also true that a small negative voltage will not be correctly measured, but usually the circuit does not allow voltages of less than zero at the input.

Also, the above assumes that you are computing the voltage as measured from a voltage reference. If you are using a calibrated value you will need to use those values, as shown in the "calibration" page.

Clock Prescaler

Its possible by choosing a different clock prescaler to perform conversions more quickly; however because the circuit - particularly the comparator - takes time to settle FASTER READINGS WILL BE LESS ACCURATE.

External Analog to Digital converters

The ADS1115 module offers 4 16 bit analog inputs and connects to the arduino via I2C. However the ADC is not a successive approximation type, but a Sigma-Delta converter.

This achieves high resolution (lots of bits) - but at the expense of much slower conversion rates.

Further reading

Nick Gammon's page has lots more very useful information.