Step 4: Analog to Digital Conversion

Picture of Analog to Digital Conversion
Most of you will want to skip this step.

If you are curious, or having analog problems, or looking to design some analog circuits, this may be helpful.

The ATmega328 has six analog input pins (see pin mapping). I am assuming the chip has only one A/D (analog to digital) converter chip in it. It is called a ten bit converter because it uses ten bits, 210 or 1024. The next drawing is a pretty good representation of how the converter works. The description is pretty technical and not that important for most Arduino users. But look at the analog signal represented by the smoothly curving signal on the top left. The stair step picture on the bottom left is representative of the digital output. You should note that instead of a smoothly curving line like the analog signal, the digital output is very jagged, often called a stair step. For the Arduino, the digital input goes from 0000000000 to 1111111111 which is 1023 steps in decimal.

This digital output doesn’t come out of the ATmega directly. It is only used internally by the software.
For the standard Arduino if you have 5V on the analog pin, the analogRead() will be 1023. Since there are only 1023 different possibilities that means each step is 0.004888 V. What that means is if you have analogRead() of 1023, it might mean 5.000V or 4.996V or somewhere in between. So each stair step means that the actual voltage can be off by 0.004888 V.

Practically speaking: So many of you will say who cares and in most cases you are correct. The accuracy of this reading is dependent on the accuracy of Vcc. If the Arduino is using a 7805 voltage regulator, then the 5V is +/- 1.5% which is 0.075V. The actual voltage could be anywhere for 5.075V to 4.925V which is much greater that the tolerance of a step. Another factor is noise on Vcc and on the analog signal. With a PC USB, the 5V tolerance is usually worse. Mine measured 4.84V.

Practically speaking with the standard Arduino, your Analog accuracy is limited to +/- 1.5% of the 7805 anyway.

NOTE: I am not 100% sure the following is accurate.
Advanced information: The 5V equals 1023 is not always true for the Arduino. The 1023 value is the voltage on the AVcc pin (pin 20 of the ATmega) under most conditions. Usually AVcc is tied to Vcc and is 5V. However, if the sketch contains the function AnalogReference(INTERNAL), then an internal reference of 1.1V (for the ATmega 168 and 328) is used. I am fairly certain what this means is that if you have a 1.1V signal on an analog pin, then the analogRead will be 1023. What this means is each step equals 0.001075V which means you can get more accuracy but it also means your maximum analog input can only be 1.1V. Now AnalogReference() can also be set to EXTERNAL. What this means is the analog reference is equal to the voltage you put on the AREF pin.
WARINING: Be careful if you use EXTERNAL and an external voltage source; this could interfere with and damage the ATmega. If you run a different sketch, that doesn’t have AnalogReference(EXTERNAL) set, then the external voltage reference is going to be fighting the default voltage on AVcc. It’s like connecting two batteries of different voltages together. You have a complete circuit with voltage but zero resistance so lots of current. I think there is a way around this by connecting it through a resistor but am not sure.

The reason I mentioned AVcc and analog reference is that I was setting my Arduino-clone up to use the Nokia LCD. I noticed that LCD worked fairly well when I was using the USB power but it was very dark when I plugged in an Adafruit 9 volt battery adapter. So I grabbed my trusty little DMM and did some troubleshooting. With the USB power, the Vcc and the Aref pin on the ATmega were at 4.84V. With the 9 volt battery connected to the 7805 regulator the two pins were at 5.03V. I also had a temperature sensor attached and further testing verified that the temperature reading varied depending on what the AVcc voltage was.

So if you want to improve upon the accuracy of the ‘standard’ Arduino, there are ways to do it.
If you set AnalogReference(INTERNAL), the ATmega will use 1.1V as a reference, adjust your calculations accordingly.
TIP: Any time you change AnalogReference(), discard the first analog reading as it will be meaningless.

If you set AnalogReference(EXTERNAL), you can provide you own reference, assumed it has a tighter tolerance.
See WARNING above.
TIP: Any time you change AnalogReference(), discard the first analog reading as it will be meaningless.

Those same six analog pins use a different method for output. 
D/A (Digital to Analog): The Arduino does not use a D/A (Digital to Analog) converter. Instead it uses, something called:
Pulse Width Modulation (PWM). PWM is not an analog signal. It is a pulsed digital signal. The drawing is from http://arduino.cc/en/Tutorial/PWM.
What the Arduino sends out is a digital signal that pulses off and on at different rates.

Instruction               Output
analogWrite(0)         0 volts out
analogWrite(64)       see drawing
analogWrite(127)     see drawing
analogWrite(255)     5 volts out

The drawing depicts the output over a period of time. As the drawing shows as the analogWrite value goes farther above 0, the width of the positive pulse gets wider. In other words, the time the output stays at 5 volts is longer. Now this is hard to explain but if you think in terms of average voltage when analogWrite is 0 then the average voltage is 0 and when it is 255, then the average voltage is 5V. Now when it is 127, you can see that it is on ½ the time and off ½ the time so the average voltage is 2.5 volts. Now as the value goes larger than 127, you should see that the average voltage goes up.

For those of you who like real world “proof”, here is a way to demonstrate this. A capacitor smooths out DC voltages. That is why you will always see them on Vcc and power supply outputs. Now if you take a capacitor (I’m guessing a 1ufd or maybe .5ufd) from an analog pin to ground. If you write your sketch to set up the analog pin as output and send an analogWrite(127), your DMM should show the voltage at 2.5V. By the way, the mathematics of PWM is beyond me but I know it gets into AC circuitry which is way beyond what this Lazy Old Geek wants to get into.

To put it simply, PWM puts out a signal that simulates an analog signal for most purposes.
TIP: One thing to remember, while the analogRead goes from 0 to 1023, the analogWrite only goes from 0 to 255, a byte by the way.

Non-essential Info: Most adequately designed Arduinos and clones have a 0.01ufd capacitor from Vcc to GND and next to the ATmega chip. The reason is to filter noise from the digital ATmega. When running a sketch, most of the internal circuitry is trying to switch from 0 to 5 volts almost instantly. This produces a lot of noise, a lot of which is high frequency. The capacitor will absorb most of this and smooth it out, just like it did in our little experiment.
squiggy22 years ago
Great 'ible, very comprehensive!
Just one question;
Why does referencing 1.1v make the analog read more accurate?
Does it not also have 1.5% error?
msuzuki777 (author)  squiggy22 years ago
You are correct, there would still be a 1.5% error. But 1.5% of 1.1V is a smaller voltage than 1.5% of 5V. However, this is only speaking theoretically due to the inaccuracy of the A to D conversion.
One of the factors that will affect 'accuracy' is the tolerance of the 1.1V reference which is between 1.0 and 1.2V.

However, for real applications, this is pretty meaningless. Generally, I choose a reference voltage based on the sensors connected to the Arduino. If the maximum analog voltage is going to be 1.1V or less than choosing the internal 1.1V reference would probably be best.
I usually like to use 3.3V reference as shield compatible Arduinos have a 3.3V source and so do most USB to Arduino converters. These are usually much more accurate then the USB 5V or (I think) the 7805 regulators.