2C display.

" /> Arduino ADC as a Voltmeter

## Arduino ADC as a Voltmeter

### Arduino ADC as a Voltmeter

It seems like a single board computer would not make a suitable voltmeter, but almost all voltmeters have at their heart a resistive divider, an analog to digital converter, and a computer to read and display the results. This one is no different. What is different is the resolution of the ADC. Where many dedicated voltmeters have ADCs with 14 to 24-bit resolution, the Arduino only has 10 bits. We can only measure 1024 discreet voltages. We could add an external ADC that has higher resolution, like the AD976 or LT1605 16-bit converters, but that would defeat the purpose - to learn how to use the Arduino ADC for something useful.

All voltmeters work by measuring the voltage on a resistive ladder, designed to limit the voltage seen by the meter to the range of the ADC. The range of the Arduino ADC defaults to 5V. It can be changed, and we will do that later. For now, we will use 5V. The ATmega328 datasheet says the ATmega328's ADC doesn't work best when the source resistance is greater than about 10k Ohms. Since we have no control over the resistance of the voltage source we are measuring, we will keep the resistor divider values down to 1k Ohm. Later we will see how to get around that problem. This circuit is good for up to 10V. The voltage on the port will be divided by two, which puts it within the 5V range of the ADC. So what happens if you connect 100V to the input? What happens is the ATmega328 in the Arduino fries. There are maximum voltage ratings on the chip of around 7V before things go up in smoke. The fix for this is to keep the applied voltage below that maximum. One way to do that is with a zener diode. That zener diode will protect the Arduino from two things - over voltage and reverse voltage, by limiting the voltage to either +5.1V or -0.6V.

The problem with having the low value resistors in the ADC input is that they may actually change the voltage being read by loading the circuit. There is a way to get around that, by adding an op-amp as a buffer. You can continue by adding range switches, changing the values to satisfy the maximum input requirement of 5V full range. The accuracy of the meter depends on the precision of the resistors used.

## Voltmeter Software

The software to read the voltage divider and calculate the applied voltage is very simple. There is a formula which always applies to the ADC on Arduino:

• ADU = (Vin * 1024)/Vref
• -or-
• Vin = ADU * (Vref/1024)

So to find the voltage at the Arduino, we need to read the analog input, multiply the value read by (5V/1024) or 0.0048828125V. The voltage divider cuts the voltage in half, so to find the applied voltage, multiply by two. A reading of 100 ADU is 0.488V at the port pin, or 0.976V on the voltage divider. Changing the voltage divider only changes that multiplier - the first calculation remains the same.

```#define voltageInput A0
#define multiplier 2

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

void loop() {
double voltage = ADU * 0.0048828125 * multiplier;
Serial.println(voltage);
delay(1000);
}
``` ## Changing the ATmega328 ADC Reference Voltage

We changed the resistor divider to 1M&560k, giving a divisor of 1.78 rather than 2, so the multiplier in the code needs to be adjusted to be 1.78.

Now for the reference voltage. There is a precaution you need to take with this, because the external reference and the internal reference are shorted together when a reading is taken. Before the first reading of any analog input, you must set the reference to external. Once that is done, it is safe to read any analog pin. It prevents the internal references from being connected to the pin.

Since we changed the reference voltage we have to change the formula. It is still Vin = ADU * (Vref/1024), but Vref has changed from 5V to 2.5V. 2.5/1024 = 0.0025V per ADU. However that resistor divider network has to be considered. You can do the math, or you can do what I did:

1. Connect this meter to it's own reference voltage.
2. Connect a known good meter to the reference voltage.
3. Adjust the reference for 2.5 or as close as possible.
4. Read the number of ADUs as seen on the LCD screen.
5. Divide the exact reference voltage by the ADU number.
6. Enter the result as the multiplier in the following Arduino program. The maximum voltage you can read with this configuration is 1023 * 0.0066100795756 = 6.76V. You can adjust the input divider to be anything you want, and the multiplier may be determined as shown above. The tolerance of the parts does not matter at all, if you calibrate it.

```#include <LiquidCrystal.h>

int voltmeter_Pin = A3;
double multiplier = 0.0066100795756;

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
void setup() {

lcd.begin(16, 2);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Voltage:");
analogReference(EXTERNAL);

}

void loop() {

double voltage;

voltage = ADU * multiplier;

lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Voltage:");
lcd.setCursor(0, 1);
lcd.print(voltage,3);
lcd.print(" V ");