Learn about the Arduino’s AREF pin and how to use it in this detailed tutorial.

**[Updated 09/01/2013]**

Today we are going to spend some time with the AREF pin – what it is, how it works and why you may want to use it. First of all, here it is on our boards:

**[Please read the entire article before working with your hardware]**

In chapter one of this series we used the *analogRead()* function to measure a voltage that fell between zero and five volts DC. In doing so, we used one of the six analog input pins. Each of these are connected to ADC (analog to digital conversion) pins in the Arduino’s microcontroller. And the *analogRead()* function returned a value that fell between 0 and 1023, relative to the input voltage.

But why is the result a value between 0~1023? This is due to the *resolution * of the ADC. The resolution (for this article) is the degree to which something can be represented numerically. The *higher *the resolution, the greater accuracy with which something can be represented. We call the 5V our *reference voltage*.

We measure resolution in the terms of the number of *bits *of resolution. For example, a 1-bit resolution would only allow two (two to the power of one) values – zero and one. A 2-bit resolution would allow four (two to the power of two) values – zero, one, two and three. If we tried to measure a five volt range with a two-bit resolution, and the measured voltage was four volts, our ADC would return a value of 3 – as four volts falls between 3.75 and 5V. It is easier to imagine this with the following image:

So with our example ADC with 2-bit resolution, it can only represent the voltage with four possible resulting values. If the input voltage falls between 0 and 1.25, the ADC returns 0; if the voltage falls between 1.25 and 2.5, the ADC returns a value of 1. And so on.

With our Arduino’s ADC range of 0~1023 – we have 1024 possible values – or 2 to the power of 10. So our Arduinos have an ADC with a 10-bit resolution. Not too shabby at all. If you divide 5 (volts) by 1024, the quotient is 0.00488 – so each step of the ADC represents 4.88 millivolts.

However – not all Arduino boards are created equally. Your default reference voltage of 5V is for Arduino Duemilanoves, Unos, Megas, Freetronics Elevens and others that have an MCU that is designed to run from 5V. If your Arduino board is designed for 3.3V, such as an Arduino Pro Mini-3.3 – your default reference voltage is 3.3V. So as always, check your board’s data sheet.

**Note** – if you’re powering your 5V board from USB, the default reference voltage will be a little less – check with a multimeter by measuring the potential across the 5V pin and GND. Then use the reading as your reference voltage.

What if we want to measure voltages between 0 and 2, or 0 and 4.6? How would the ADC know what is 100% of our voltage range?

And therein lies the reason for the AREF pin! AREF means** A**nalogue **REF**erence. It allows us to feed the Arduino a reference voltage from an external power supply. For example, if we want to measure voltages with a maximum range of 3.3V, we would feed a nice smooth 3.3V into the AREF pin – perhaps from a voltage regulator IC. Then the each step of the ADC would represent 3.22 millivolts.

Interestingly enough, our Arduino boards already have some internal reference voltages to make use of. Boards with an ATmega328 microcontroller also have a 1.1V internal reference voltage. If you have a Mega (!), you also have available reference voltages of 1.1 and 2.56V. At the time of writing the lowest workable reference voltage would be 1.1V.

So how do we tell our Arduinos to use AREF? Simple. Use the function* analogReference(type)*; in the following ways:

For Duemilanove and compatibles with ATmega328 microcontrollers:

- analogReference(INTERNAL); – selects the internal 1.1V reference voltage
- analogReference(EXTERNAL); – selects the voltage on the AREF pin (that must be between zero and five volts DC)
- And to return to the internal 5V reference voltage – use
*analogReference(DEFAULT);*

If you have a Mega:

- analogReference(INTERNAL1V1); – selects the internal 1.1V reference voltage
- analogReference(INTERNAL2V56); – selects the internal 2.56V reference voltage
- analogReference(EXTERNAL); – selects the voltage on the AREF pin (that must be between zero and five volts DC)
- And to return to the internal 5V reference voltage – use
*analogReference(DEFAULT)*

Note you must call *analogReference() ***before** using *analogRead();* otherwise you will short the internal reference voltage to the AREF pin – possibly damaging your board. If unsure about your particular board, ask the supplier or perhaps in our Google Group.

Now that we understand the Arduino functions, let’s look at some ways to make a reference voltage. The most inexpensive method would be using resistors as a voltage divider. For example, to halve a voltage, use two identical resistors as such:

For a thorough explanation on dividing voltage with resistors, please read this article. Try and use resistors with a low tolerance, such as 1%, otherwise your reference voltage may not be accurate enough. However this method is very cheap.

A more accurate method of generating a reference voltage is with a zener diode. Zener diodes are available in various breakdown voltages, and can be used very easily. Here is an example of using a 3.6V zener diode to generate a 3.6V reference voltage:

For more information about zener (and other diodes) please read this article. Finally, you could also use a linear voltage regulator as mentioned earlier. Physically this would be the easiest and most accurate solution, however regulators are not available in such a wide range nor work with such low voltages (i.e. below 5V).

Finally, when developing your sketch with your new AREF voltage for *analogRead();*, don’t forget to take into account the mathematics of the operation. For example, if you have a reference voltage of 5V, divide it by 1024 to arrive at a value of 4.88 millivolts per *analogRead()* unit. Or as in the following example, if you have a reference voltage of 1.8V, dividing it by 1024 gives you 1.75 millivolts per *analogRead()* unit:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// Example 22.1 int analoginput = 0; // our analog pin int analogamount = 0; // stores incoming value float percentage = 0; // used to store our percentage value float voltage =0; // used to store voltage value void setup() { Serial.begin(9600); analogReference(EXTERNAL); // use AREF for reference voltage } void loop() { delay(200); analogamount=analogRead(analoginput); percentage=(analogamount/1024)*100; voltage=analogamount*1.75; // in millivolts Serial.print("Percentage of AREF: "); Serial.println(percentage,2); Serial.print("voltage on analog input (mV): "); Serial.println(voltage,2); } |

So if necessary, you can now reduce your voltage range for analog inputs and measure them effectively.

Have fun and keep checking into tronixstuff.com. Why not follow things on twitter, Google+, subscribe for email updates or RSS using the links on the right-hand column, or join our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other – and we can all learn something.