Measuring DC Voltage using Arduino

Created on: 23 May 2013

How to measure DC voltage with an Arduino Uno. Arduino analog inputs can be used to measure DC voltage between 0 and 5V on 5V Arduinos such as the Arduino Uno when using the standard 5V analog reference voltage.

The range over which the Arduino can measure voltage can be increased by using two resistors to create a voltage divider. The voltage divider decreases the voltage being measured to within the range of the Arduino analog inputs. Code in the Arduino sketch is then used to calculate the actual voltage being measured. This allows voltages greater than 5V to be measured.

This video shows the Arduino being used to measure various voltages:

How to Measure Voltage with Arduino – Principle of Operation

The following sections explain the principles of measuring voltage with Arduino including input impedance, how a resistor voltage divider works, and some precautions.

Input Impedance

A digital multimeter set to measure DC voltage will typically have an input impedance of 10MΩ or greater.

What this means is that the resistance between the two multimeter probes is 10MΩ or more.

A high input impedance for a voltmeter (or multimeter on the voltage scale) is desirable as the higher the input impedance, the less likely the multimeter will influence or change the circuit being measured.

Measuring voltage across a component in a circuit with a multimeter that has an input impedance of 10M ohms, is the same as connecting a 10M ohm resistor across the component.

If a voltmeter has a low input impedance, say 10kΩ and a voltage across a 10kΩ resistor is being measured, the multimeter is effectively changing the resistor value to 5kΩ (two 10k resistors in parallel = 5k resistance). The multimeter therefore has changed the circuit and possibly the voltage being measured.

So a high input impedance is desirable in our voltage divider circuit if the impedance of this "voltmeter" is going to influence the circuit being measured.

As a general rule though, a high input impedance device will generally pick up more noise or interference (EMI) than a low input impedance device.

Voltage Divider Circuit

A voltage divider circuit consisting of two resistors in series will divide the input voltage to bring it within the range of the Arduino analog inputs.

The circuit shown below will divide the input voltage by 11 (from the battery as the example input voltage being measured).

The circuit with the particular values shown has an input impedance of 1MΩ + 100kΩ = 1.1MΩ and is suitable for measuring DC voltages up to about 50V.

How to measure voltage with Arduino: Arduino voltage divider circuit
How to Measure Voltage with Arduino – Arduino Voltage Divider Circuit Diagram

Precautions

It is important to take note of the following precautions when measuring voltage with Arduino.

Common Ground

If the Arduino is powered from an external power supply or a USB cable (i.e. not powered by a isolated battery or other isolated power supply) the circuit may share a common ground or 0V connection with the circuit under test.

If the GND connection of the Arduino is connected to any other part of the circuit under test except GND, then this is the same as shorting that part of the circuit to GND.

The GND of the Arduino is like the negative or common (COM) lead of a multimeter, except that it should be considered to be permanently connected to the GND of the circuit under test for safety, unless the Arduino or the circuit under test is completely isolated and "floating".

Input Protection

The resistor values in the circuit diagram above provide some over-voltage protection when measuring low voltages such as 5V, 9V or 12V. So if a voltage of say 30V is accidentally measured, it will not blow the Arduino analog input pin.

Any voltage higher than about 55V could damage the Arduino. The point on the resistor divider network connected to the the Arduino analog pin is equivalent to the input voltage divided by 11, so 55V ÷ 11 = 5V. In other words, when measuring 55V, the Arduino analog pin will be at its maximum voltage of 5V.

Providing this basic over-voltage protection is at the expense of not using the full 10-bit range of the analog input ADC if only lower voltages are to be measured, but changes of about 0.054V can still be measured.

No other protection for voltage spikes, reverse voltage or voltages higher than 55V is shown in the circuit.

Sketch to Measure Voltage with Arduino

The sketch below measures voltage with Arduino. It reads the value on pin A2 of the Arduino. It provides some simple filtering by adding up 10 analog values from pin A2 sampled at 10ms intervals.

After taking 10 samples, the voltage is calculated using the average of the 10 sample values and sent out of the serial port for display on the Arduino Serial Monitor window.

Note that calibrated values are used in this sketch – these will need to be changed for your particular reference voltage and actual resistor division factor, explained below.

/*--------------------------------------------------------------
  Program:      volt_measure

  Description:  Reads value on analog input A2 and calculates
                the voltage assuming that a voltage divider
                network on the pin divides by 11.
  
  Hardware:     Arduino Uno with voltage divider on A2.
                
  Software:     Developed using Arduino 1.0.5 software
                Should be compatible with Arduino 1.0 +

  Date:         22 May 2013
 
  Author:       W.A. Smith, http://startingelectronics.org
--------------------------------------------------------------*/

// number of analog samples to take per reading
#define NUM_SAMPLES 10

int sum = 0;                    // sum of samples taken
unsigned char sample_count = 0; // current sample number
float voltage = 0.0;            // calculated voltage

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

void loop()
{
    // take a number of analog samples and add them up
    while (sample_count < NUM_SAMPLES) {
        sum += analogRead(A2);
        sample_count++;
        delay(10);
    }
    // calculate the voltage
    // use 5.0 for a 5.0V ADC reference voltage
    // 5.015V is the calibrated reference voltage
    voltage = ((float)sum / (float)NUM_SAMPLES * 5.015) / 1024.0;
    // send voltage for display on Serial Monitor
    // voltage multiplied by 11 when using voltage divider that
    // divides by 11. 11.132 is the calibrated voltage divide
    // value
    Serial.print(voltage * 11.132);
    Serial.println (" V");
    sample_count = 0;
    sum = 0;
}

How the Code Works

To measure voltage with Arduino, first ten analog samples are taken using the following code:

while (sample_count < NUM_SAMPLES) {
    sum += analogRead(A2);
    sample_count++;
    delay(10);
}

The sum or total of all 10 values added together are stored in sum. The variable sample_count keeps track of the number of samples.

Both variables are reset after calculating and displaying the voltage:

sample_count = 0;
sum = 0;

The number of samples taken can be changed at the top of the sketch:

#define NUM_SAMPLES 10

Don't make this value too high or the sum of all the samples will be too big to fit in the sum variable.

The voltage is calculated using:

voltage = ((float)sum / (float)NUM_SAMPLES * 5.0) / 1024.0;

A calibrated value is used in place of 5.0 in the above sketch – calibration is explained later.

The 10 samples (sum) is divided by 10 (NUM_SAMPLES) to get the average value read.

5.0 is the 5V ADC reference voltage. 1024.0 is the maximum value that the ADC can have plus 1 (1023 + 1 or 2 to the power of 10 plus 1) 1023.0 can also be used here.

This calculates the divided voltage – i.e. the voltage on the A3 pin.

The actual voltage is calculated by multiplying the divided voltage by the division factor from the voltage divider network:

Serial.print(voltage * 11.0);

The above line of code calculates the actual voltage and then sends it out the serial port for display in the serial monitor window.

The sketch uses a calibrated value instead of 11.0 as shown here.

Calibrating the Arduino and Circuit

A more accurate voltage could be obtained by using a precision reference voltage for the ADC and using 1% tolerance resistors or better.

Another way to obtain a more accurate reading is to calibrate the circuit. Calibration can be done by measuring the actual value of the reference voltage and the actual values of the voltage divider resistors. These values can then be used in the calculations in the Arduino sketch code.

Each Arduino and set of resistors would need to be individually calibrated because the voltage from the 5V regulator and the resistance of the voltage divider resistors will probably be slightly different for each Arduino and set of resistors.

Performing the Calibration

To perform the calibration, you will need a multimeter.

Calibrating the ADC Reference Voltage

First measure the 5V on the Arduino from the regulator (found on the Arduino 5V pin). This voltage is used for the Arduino ADC reference voltage by default.

Now put the measured value into the sketch as follows.

voltage = ((float)sum / (float)NUM_SAMPLES * 5.015) / 1024.0;

In the above example, the voltage measured on the 5V Arduino pin was 5.015V.

Calibrating the Resistor Network

Connect a stable power supply, such as a 9V battery across the resistor network. Measure the voltage across both resistors together i.e. measure the battery voltage.

Now measure the voltage across the 100k resistor (R2) i.e. between Arduino pin A3 and GND.

The voltage divider factor is calculated by dividing the first voltage by the second voltage or:

dividing factor = input voltage ÷ output voltage

For example, if the first or input voltage measured is 10.02V and the second or output voltage is 0.9V, then the division factor is:

10.02 ÷ 0.9 = 11.133

Now use this value in the Arduino sketch code:

Serial.print(voltage * 11.133);

If calibration is used, then 5% tolerance resistors can be used for the voltage divider.