An analog-to-digital converter or ADC is a device used to convert an analog voltage (like the output from a photocell or a thermistor) to an equivalent binary digital representation suitable to be processed by a digital computer or microprocessor.

Think about this: every word you say into your cell phone is an analog signal coming from the microphone and is converted to be digitally processed in the phone. The phone has to do this fast and is typically about ten times the highest frequency speed needed to be converted.

There are a few ways to convert an analog signal into a binary digital signal: flash, sigma delta, dual-slope, pipeline, and successive approximation. This tutorial will discuss successive approximation as this is probably the most common and the one you are likely to find in an Arduino.

Definitions and Specifications

We need to understand a few things if we intend to sample a particular type of analog source, for example, a stable battery voltage with a very different requirement to high-quality audio.

Sampling rate

Any AC waveform has a given frequency. If we want to reproduce/capture this with accuracy, we must take enough samples over each complete cycle to be sure to catch every fluctuation in the waveform. The Nyquist criteria say we must sample at twice the frequency of the highest frequency of the source. However, sampling a pure sine wave at this rate will have too few samples and only result in a triangular wave.

So, as a rule of thumb, sample at least ten times the highest frequency and even faster if you want better accuracy. Each sample takes the instantaneous value of the waveform during each sampling period. And it’s clear that the quicker you do this, the better.

Resolution and Accuracy

How many unique levels can a digital word represent? If we have 4 bits, that is 24 = 16. So if I wanted to convert an analog signal of 5V, you would have to be happy with 5V broken into 16 steps or 0.3V per step.

We can express this as an accuracy, i.e., 100/16 or 6.3%. That is quite rough!

Going to 10 bits (as used in Arduino), we have 210 = 1024 steps or 4.8mV per step. Now, we have an accuracy of 100/1024 or 0.1%, which should be OK for most things. Note that you should see that trying to display the result of any sensor, such as an LM35 temperature sensor with two or more decimal places, is quite silly.

How ADC works

Shown in Figure 1 below is a block diagram of an ADC as used in the Arduino 328. The clock CLK provides the sampling rate, SAR is the Successive Approximation Register, EOC is an output to the processor to indicate the current sample is complete, Vref is either the 5V supply, an internal 1.1V reference, or an external voltage reference (all select-able in code), DAC is the digital to analog converter, Vin is the analog input pin, S/H is the sample and hold and COMP is the comparator.

The conversion process is initiated by a signal from the processor to the ADC. Upon receiving the start, the control unit of ADC will give a command to successive approximation register, and it starts generating the digital signal by successive approximation method. The generated digital data is converted to an analog signal by D to A converter and then compared with the current analog signal and the reference voltage. The digital data available at this instant is given as output through the output register. Also, the control unit generates a signal to indicate the end of conversion (EOC) process to the processor.

In this diagram, all bits are initially set to 1, then for each bit or step of the clock, the output of the SAR is compared with the value. If it’s greater, it’s left at 1. Otherwise, it gets set to 0 until all the bits have been set. Then, the EOC signals to the processor that the output is valid.

Figure 1: Successive Approximation A to D

The heart of the ADC is the sample and hold (S/H) shown in Figure 2 below. For each sample clock cycle, S1 closes, S2 opens and allows the small capacitor to rapidly charge up to the current instantaneous value of the waveform (C1 is a few pF). S2 then closes while S1 opens, and the voltage is read by the comparator.

Figure 2: Sample and Hold

Working Backwards: Digital to Analog

Let’s assume we had a fixed voltage on an Arduino analog pin, and it gave us a sample of 0 0 0 1 1 0 0 1 0 0 (10 bits) and we wanted to see what this was as an integer. We set it out like below:

29 28 27 26 25 24 23 22 21 20
5122561286432168421
0001100100

Now, adding it up:

0*512 + 0*256 + 0*128 + 1*64 + 1*32 + 0*16 + 0*8 + 1*4 + 0*2 + 0*1 = 100

So, what voltage did we read?

In an Arduino, assuming we are using the local 5V as our reference, we have:

(1023/5V) * Vin = integer value returned.

So if Vin = analogRead(A0) gave us 100 above (an integer between 0 and 1023), what voltage is on pin A0?

Voltage = (5*Vin) /1023 = 0.488V on A0.

Note that Vin is an integer and Voltage is a float.

There you have it! Analog-to-Digital converters are rather complex devices. Bear in mind that they take a finite time to clock through the sample and stabilize the output. If available, you must then monitor the EOC, perhaps with an interruption if time is not critical. Pause a few mS after requesting the conversion to allow it to stabilize.

An interesting debate rages over whether to use a value of 1023 or 1024. You can read here to learn more.