# How to measure the supply voltage of Arduino without using an analog pin

I'm using Arduino Nano to measure temperature with a 10 kohm thermistor and a voltage divider. My problem is I'm getting only 4.2V on the 5V pin. The power is supplied via a USB cable from a desktop PC.

I measured the output voltage of a USB port on the PC and it was around 4.5V. It doesn't look normal. So I suspect the power supply unit of the PC is not strong enough.

But it still makes sense to measure the voltage at the 5V pin since there is no guarantee it's exactly 5V. Its error will affect the calculated resistance of the thermistor. So I got it by connecting the pin directly to the A1 pin.

On the other hand, it seems to me Arduino internally and digitally knows the value of the supply voltage. So it would be faster and easier to get it rather than using the A1 pin. But I don't know how to do it.

After searching on the Internet, I could find only these things which didn't help me much.

I also considered using an external power supply, say 9V to the VIN pin but I don't feel like doing that much.

How can I measure the supply voltage of Arduino without using an analog pin?

• The analog inputs measure a voltage ratio: input/reference. Thus the calculated resistance of the thermistor is not affected by variations in the supply voltage. – Edgar Bonet Mar 15 '18 at 14:30
• Okay, so the integer returned by analogRead() is input/reference(1.1V)/5V*1023? – dixhom Mar 15 '18 at 14:53
• In the case of your voltage divider, `analogRead()` returns Rthermistor÷(Rthermistor+Rpullup)×1024, irrespective of the supply voltage. – Edgar Bonet Mar 15 '18 at 15:28
• Yes, it's 1024. The ADC saturates at 1 step below Vref. C.f. the datasheet of the microcontroller, which is the only authoritative document for that matter. – Edgar Bonet Mar 17 '18 at 9:30
• Actually it's 1022÷1024×Vref, because when you read 1023 you don't know whether the input voltage is 1023÷1024×Vref or anything higher. Actually, any voltage above 1022.5÷1024×Vref is expected to give a reading of 1023. – Edgar Bonet Mar 17 '18 at 10:01

Yes, you can do it.

You can measure the voltage of the internal (approximately) 1.1V reference voltage using the ADC and use the results of that to calculate what the reference voltage you used (VCC) must have been to get the results you did.

This is a function I commonly use:

``````long readVcc() {
long result;
// Read 1.1V reference against AVcc
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(2); // Wait for Vref to settle
result = 1125300L / result; // Back-calculate AVcc in mV
return result;
}
``````

Depending on how close to 1.1V your internal reference voltage is, you may need to adjust the value `1125300L` in the code above. Measure the actual VCC voltage and adjust that value until it results in the same voltage being returned (multiplied by 1000 since that function returns millivolts).

However, as Edgar Bonet mentions, you don't need to care about the supply voltage in your situation, since your thermistor readings are just a ratio that input voltage, whatever it is. Change the input voltage and you will get the same results, since the ADC returns a value between 0 and Vcc in 1024 steps. With different supply voltages you still get 1024 steps.

• How did you get `1125300L`? And why is it `1125300L / result`? It seems to me `ADCL | ADCH << 8` is a 10 bit ADC value so something like `result = 1125300L * result / 1024` would make sense. But for this one `result` is the denominator. – dixhom Mar 24 '18 at 11:18
• 1125300 is 1100 (1.1v as mv) times 1023 (ADC max value). – Majenko Mar 24 '18 at 11:40
• In this page, it is `1126400L` = 1.1*1024*1000. I'm wondering which I should believe. – dixhom Mar 24 '18 at 12:18
• There are massive arguments around the net regarding if you should use 1023 or 1024. I say 1023. The max value of the ADC is not equal to VREF, but is VREF "minus one LSB" (as stated by the datasheet). 1024 would be VREF but you can't get 1024 out of the ADC. – Majenko Mar 24 '18 at 12:22
• IMHO it's 1024. Edgar Bonet's comments sound reasonable. For the denominator thing, I was wrong. the equation is Vin(1.1V) = ADC/1024*AVcc(5V) since it reads "1.1V reference against AVcc". That's equivalent to AVcc = 1.1*1024/ADC = 1126.4/ADC. – dixhom Mar 24 '18 at 13:16

The Nano has an ATMega328P MCU, which has an internal 1.1V reference voltage.

You use `analogReference()` to change the reference voltage that analogRead() compares the analog inputs against.

You will need to use a voltage divider to ensure that your maximum possible supplied voltage ends up being no higher than the 1.1V reference.

You'll still need to use an analogInput pin.

• If you do this, you will make the resistance reading dependent on the supply voltage, which is what the OP wanted to avoid in the first place. – Edgar Bonet Mar 15 '18 at 14:46
• I see. You are correct; I was only solving the problem of how to compute the supply voltage, but with the supply voltage known, the resistance reading for the thermistor can be calibrated in software. – jose can u c Mar 15 '18 at 14:57
• What Edgar was saying is that the thermistor measure is ratiometric, so using a ratiometric way of measuring the thermistor voltage the supply voltage perfectly cancel out. If you use the 1.1V reference you will have to make more calculations and will have a less precise measurement – frarugi87 Mar 16 '18 at 8:20
• Hi, my intention was to know the supply voltage without making the system complicated. I think the value of the voltage doesn't matter as @frarugi87 suggested the two voltages cancel out. If it were not so high it generates tremendous heat and break parts or so low it can't be measured, it's fine. – dixhom Mar 17 '18 at 7:56