John L Errington MSc

John Errington's Experiments with an Arduino

Measuring the supply voltage - two approaches.

The aim of this project was simple - to measure the supply voltage; Vusb if powered from the usb port, or Vraw if from a battery.
As you will see later, to get an accurate measurement I needed to bypass a protection diode. This could be fitted externally if running from batteries.

Problems with cheap clones of the Ardino Micro Pro

I bought some chinese "Pro Micro" clones as disposable assets. Just for junk experiments. I soon found out they were not "quite" the same. I had decided to build a little device to measure USB voltage. I knew it was almost exactly 5V - so why did the arduino measure it as 4.6?

Back of Pro Micro clone

pro Micro frontFront of Pro Micro clone



First approach - use a potential divider

My first approach to the measurement was very traditional. Use a potential divider to drop the voltage from Vcc and measure it by comparison with the internal 2.56V reference.

I connected a 33k resistor between Vcc (pin 21) and A8, with a 10k to ground. I calculated this should give me 5.0 * 10 / 43 = 1.163V on A8. With a reference of 2.56 and resolution of 1024 I should get a reading of 1024 * 1.163 / 2.56 = 465. However when I ran a sketch to measure it I was only getting about 425, indicating a USB voltage of 4.6V.

Second approach - use the "magic voltmeter"

Its not well documented but there IS a way you can measure the value of Vcc without ANY external components. Basically you use direct access to registers to measure an internal reference voltage as a fraction of Vcc. The sketch first sorts out which are the correct register codes to use.

The internal reference is ALWAYS the band gap reference voltage of 1.1V (specified as 1.0 - 1.2V so not very accurate, so you need to adjust the calibration constant in the sketch to suit) - even on a 32U4 board where the internal Vref is 2.56V.

Its like this: Vref / Vcc = n / 1024 so once we measure n, by some simple algebra Vcc = 1024 * 1.1 / n

so for Vcc = 5V and Vref = 1.1 n should read 225. However I was getting a reading of 245 - indicating Vcc to be 4.6V

Note - because we are comparing "upside down" a higher reading indicates a lower value for Vcc.

I found the readings fluctuated quite a bit, so I used a counted loop to average a set of readings.


Sketch for the secret voltmeter


Why was the reading incorrect?


I studied the circuit diagram for the Arduino Pro Micro, and there was nothing shown that could cause this voltage drop.

I took photos of the board (shown above) so that I could examine the components - but the labels were not helpful.

Taking voltage measurements around the board I found Vcc - ground was indeed 4.64V. However at JP1 I found 5.00V.

The clone had a protection diode which was not present on the genuine boards. By shorting out the jumper my measurements from both approaches gave the same result.

Its worth knowing about this, as if you used vcc as a 5v reference you would get silly results!


I needed to adjust the calibration constant to give more accurate readings as the band gap reference on this board is 1.0896V


(Schematic diagram using Autodesk Eagle with SparkFun libraries)



1: Arduino tutorial
2: ATmega datasheet Complete:
3: ATmega 328 datasheet:
4: ATmega 32U4 datasheet:
5: Voltage reference datasheet
6: Arduino reference:
7: USB standard: