# John Errington's Experiments with an Arduino

## Precise voltage measurement with the Arduino board.

The Arduino range of microcontrollers provides analog inputs that can be used to measure voltage.  We can use this to build a voltmeter.
The analogRead() function reads the voltage and converts it to a number between 0 and 1023 as shown below

// read the input on analog pin 0:
// Convert the ADC reading (which goes from 0 - 1023) to a voltage reading (0 - 5V):
float voltage = sensorValue * (5.0 / 1023.0);
(1)

This leads us to believe that a reading of 0 corresponds to an input of 0.000V; and 1023 corresponds to an input voltage of exactly 5.000 volts.  This is not entirely true. Lets look at the data sheet and see what it tells us.

### The ATMEGA chip used on the Arduino has analog inputs that can be used to accurately measure voltage

The Arduino microcontroller is provided with a successive approximation type Analog to Digital converter (ADC) which has the following specification.  References shown in brackets thus  (2: 26.1) refer to sections of the AtMega 2560 data sheet.
(2: 26.1)
Resolution 10-bits  (i.e. 00 0000 00000 to  11 1111 1111 binary, or 0 - 1023 decimal)
Integral Non-linearity .. 1 LSB
Absolute Accuracy  ± 2 LSB
Conversion Time 13 - 260 µs
Input resistance R_in =100M  (2: 31.8)
Input resistance of Reference voltage R_ref = 32k  (2: 31.8)

These specifications tell us the Arduino is capable of measuring voltages to an accuracy
of  ± 2 LSB  - so the maximum error is 2 bits (4 decimal) in 10 bits (1024 decimal)
So the worst case accuracy of the converter is 4 / 1024 or 1 part in 256  i.e. 0.25%.

However the limit of the measurement accuracy depends on the voltage reference used.

### The Arduino has its own voltage references - but they are not very precise

The chip - depending on type -  is provided with SOME of the following reference voltages
DEFAULT: the default analog reference of 5 volts (on 5V Arduino boards) or 3.3 volts (on 3.3V Arduino boards)
INTERNAL: a built-in reference, equal to 1.1 volts on the ATmega168 or ATmega328 and 2.56 volts on the ATmega8 (not available on the Arduino Mega)
INTERNAL1V1: Vint1 - a built-in 1.1V reference (Arduino Mega only)
INTERNAL2V56: Vint2 -  a built-in 2.56V reference (Arduino Mega only)
EXTERNAL: the voltage applied to the AREF pin (0 to 5V only).
(3)

However the accuracy of these "reference" voltages is very limited. For example
DEFAULT: depends on your computer power supply
(4: 7.3.2)  USB2  Vbus = 4.4V - 5.25V
(2: 31.8)  Vint 1 = 1.10V  actually 1.00 -- 1.20V
(2: 31.8)  Vint 2 = 2.56V  actually 2.40 -- 2.80V

The accuracy of the reference against which the voltage is measured - using any of the above references -  is at best only 5.25 - 5.0/5.0 * 100 = 5%  - much worse than the 0.25%. the ADC provides.  Clearly if we wish to measure voltages to the accuracy provided by the Arduino the on-chip references are not good enough. The diagram below shows these errors as compared to a 4.096v reference described below.

### For precise measurements we need to provide a more accurate voltage reference

The LM4040DIZ-4.1/NOPB (5) is a voltage reference diode, and if we connect this to the "5V" supply through a resistor, so that a current of >100 uA and <15mA flows through the diode, it provides a voltage of 4.096V ± 0.2%.

The input resistance of the reference terminal = 32k

Then Iref = 4.096V / 32k =  0.128mA

If the minimum diode current is 0.4mA then It = 0.4 + 0.128 = 0.528mA.

The minimum voltage from a USB port is 4.4V so R = 4.40 - 4.096 / 0.528 = 560 ohms.

The maximum current that will flow is 5.25V  - 4.096 / 0.560k = 2.16 mA

Using this voltage reference we can make voltage measurements to an accuracy of 0.25%

As an alternative the MCP1541 will provide the same 4.096V voltage reference, while the MCP1525 will give a 2.50V reference, and require a resistor of about 3k3.

N.B. In all cases the Vref terminal of the voltage reference should be decoupled to ground via a capacitor of 1uF across the regulator IC pins.

Now lets look at