Monday, May 18, 2015

Measuring Voltage with an Arduino and an External AREF

The Arduino Uno has 6 analog inputs, designed for measuring a voltage. Other versions of the Arduino can have several more. Voltages are analog, meaning they can have a range of values, versus digital, which only has two, on or off. Whether you are reading a potentiometer, a TMP36 or LM35 temperature sensor, or even the voltage of a battery, these devices output an analog signal. Many devices are strictly in the analog world.

The Arduino is very good at measuring these voltages, as long as they are in the 0-5v range (UNO) or 0-3.3v range on some other models. The issue we run into is that although the 5v is assumed, sometimes it's not 5v. If you have your Arduino plugged into your computer USB, or have a lot of devices connected to your Arduino, that 5v can be as low as 4.8 volts.

Why does this matter? The Arduino analog to digital converter has 1024 steps so 5v / 1024 = 0.0048828125 per step. But if the voltage was 4.8 volts, then each step would equal 0.0046875. Doesn't seem like a big difference does it? With a sensor like the TMP36, that difference could equal several degrees of inaccuracy.

So how do we correct this? Well, powering your Arduino from a 9v source through the barrel connector is a big help, as the onboard voltage regulator will do a good job of enforcing that the INTERNAL reference is really 5v. For real precision, a EXTERNAL reference is best.

We are using a LM4040 precision voltage source from Adafruit, which takes a nominal 5v input, and delivers a precision voltage reference of 2.048 and 4.096 volts, regardless of your supply voltage to the Arduino. By connecting one of these outputs to your AREF pin, and specifying the AREF voltage (verify with your meter), you now can precisely measure a analog signal from 0 - AREF voltage.

If your signal is greater than the AREF voltage, you can use resistors to create a voltage divider to bring it back into range.


Here is a sample sketch showing how to use a EXTERNAL reference, like the Adafruit LM4040.

When using AREF, always specify analogReference(EXTERNAL); before doing an analog read, as you could short the internal reference, damaging the Arduino. I recommend you upload this sketch before connecting the AREF pin.

#define aref_voltage 4.096 

int ADCPin = 1; //using A1 input for this sketch
int ADCReading;

void setup(){




void loop(){

  ADCReading = analogRead(ADCPin);  
  Serial.print("ADC reading = ");
  Serial.print(ADCReading);     // the raw analog reading
  // converting that reading to voltage, which is based off the reference voltage
  float voltage = ADCReading * aref_voltage;
  voltage /= 1024.0; 
  // print out the voltage
  Serial.print(" - ");
  Serial.print(voltage); Serial.println(" volts");



1 comment:

  1. Another advantage to using the precision reference is that the Arduino ADC is 10bits, so it has 0-1023 possible readings. By powering the AREF to say 2.048v, now 0-2.048 has 1024 graduations instead of 0-5v, making your readings much more precise.