Making a More Accurate Arduino Analog Measurement Generally speaking, all measurements compare a known to an unknown. The unknown is whatever it is your measuring.

The known in the case of default Arduino voltage measurement is frequently it’s 5V supply.  Thus whatever error your 5V supply has is a source of error in your measurement.

One way to reduce that overall measurement uncertainty is to improve the accuracy of the known or reference voltage.  Fortunately, the Arduino allows us to provide a substitute for it’s default voltage reference by providing an Analog Reference (AREF) input.

Based on Texas Instruments LM4040 Shunt Voltage Reference,  this breakout module is a convenient addition to a project where voltage measurement resolution and accuracy are concerned.

Getting an LM4040 Breakout Module

You can try these vendors:

eBay Amazon

LM4040 Pin Outs

The module requires supply voltage and ground.  With this input, it will supply a 2.048 and 4.096 voltage reference.  These reference voltages should not be used to drive devices. LM4040 Breakout Module Accuracy

The breakout module’s being offered provide two output values.  One is 2.048 Volts and 4.096 volts.   Each of these are said to be accurate to +/- 0.1 percent at 25 degrees C.   Thus the outputs can range as follows:

2.048 Output:  from 2.045952 volts to 2.050048 volts.   ( +/- 0.002048 volts)

4.096 Output:  from 4.091904 volts to 4.100096 volts ( +/- 0.004096 volts)

When used as an Analog Reference to your Arduino, these outputs can greatly improve your voltage measurement.

Impact of the LM4040 on Arduino Measurement Range

The range of the Arduino’s Analog Measurement is dependent on the reference.  Specifically, it is the value of the voltage reference minus one LSB.   This is covered in more detail in the article on Arduino ADC Resolution and Accuracy.

In most default arduino analog measurements,  it is assumed that the reference is equal to 5 volts.  Thus we assume that the measurement range is 4.995 volts ( 5/1024).

However, using the LM4040 module  you will supply lower voltages, thus you will decrease the measurement range.  Here is how that works out.

2.048 Output  Max Range is 2.046

4.096 Output Max Range is 4.092 volts

Impact of the LM4040 on Arduino Absolute Accuracy

As discussed in Arduino ADC Resolution and Accuracy,   the absolute accuracy of the Arduino Atmel processor is expressed as plus or minus two LSB.

What’s important to recognize it that the value of one LSB bit is dependent on the value of the voltage reference as the value of that bit is determined as follows:

Value of 1 LSB = Voltage Reference / 1023

It therefore follows that a decrease in voltage will result in a lower LSB value and that this lower LSB value represents improved accuracy when expressed as a voltage.   For example:

With a 5 Volt Reference:

1 LSB = 5 / 1023 =  0.0049 Volts

Absolute Arduino Accuracy = 2 x 0.0049 = 0.0096 volts or 9.6 mV

With a 4.096 Volt Reference:

1 LSB = 4.096/1023 = 0.0040 Volts

Absolute Arduino Accuracy = 2 x 0.0040 = 0.008 volts or 8mV

With a 2.048 Volt Reference:

1 LSB = 2.048/1023 = 0.0020 Volts

Absolute Arduino Accuracy = 2 x 0.0020 = .004 or 4mV

Impact of LM4040 Accuracy on Overall Accuracy

The inaccuracy of the LM4040 is small enough to have a negligible impact on your measurement.

The Arduino Analog to digital converter has an output that can range from 0 to 1023.  It provides this output in a manner that is consistent with the following formula.

Binary ADC Output Value  = Vin x 1024 / Vref

4.096 Volt Reference Impact

Assume a perfect two volt input and a perfect 4.096 volt reference.   The analog to digital converter would output a value of 500.  In fact our sketch would apply  the following formula

Voltage In = 500 * 4.096 / 1024 = 2.00 volts

Now assume that same perfect 2.00 volt input,  BUT lets set the reference to lower accuracy limit of the LM4040 at 4.091904 volts.

The ADC output would be…

Binary ADC Output Value = 2 x 1024/ 4.092 = 500  (500.48 but rounded because the ADC outputs integers)

As you can see, there is negligible impact.  The same will be true of 2.048.

Combined Accuracy of the LM4040 and the Arduino

We’re dealing with two different kinds of inaccuracy expressions here, thus combining them takes a little bit of thought.

First, the Arduino has absolute accuracy of plus or minus 2 LSB or 8 mV with a 4.096 volt reference.  It is important to know that that 8mV in accuracy is applied to a reading at 100 mV and 4.00 Volts.  Thus at 100 mV we can have a 4 percent error and the 4.00 volt measurement a 0.2 percent error.

Second, the LM4040 affects our inaccuracy as a percentage of input.   In other words, the 0.1 percent uncertainty is applied uniformly to each measurement.   Thus,  a 100 mV input will have 0.1mV affect on uncertainty and a 4.00 volt measurement will have a 4 mV affect on uncertainty.

What I’m trying get you to see here is that the inaccuracy changes a bit for each input and given the different types of errors,  they cannot be universally described.  What we have here is a worse case error that can be described by the following formula

Worst Case Inaccuracy = +/-( 0.1 percent of Input + 4mV)

Thus:

Inaccuracy at  100 mV input =  +/- 4.1mV  (4.1 percent error)

Inaccuracy at 1.00 Volt = +/- 5mV  (0.5 percent error)

Inaccuracy at 2.00 Volt = +/- 6mV  ( 0.3 percent error)

Inaccuracy at 3.00 Volt +/- 7 mV (.23 percent error)

Inaccuracy at 4.00 Volt +/- 8mV (.2 percent error)

LM4040 Arduino Voltage Reference Tutorial

In this tutorial you will be supplying a 4.096 volt reference and measuring the value of your Arduino’s 3.3 Volt pin.

Key Points about using the external analog reference:

Do not use an Analog Reference that is greater than 5 volts.

Always set your reference before performing an analog read.

Connect the LM4040 to Your Arduino Load the Tutorial Sketch

Copy, Paste and Upload the Following:

/*
Henry's Bench
LM4040 Reference Tutorial
*/

const int analogIn = A0;

int RawValue= 0;
float Voltage = 0;

void setup(){
analogReference(EXTERNAL);
Serial.begin(9600);
}

void loop(){