I know this is a common question but I cannot find the answer I'm looking for.
I'm powering the Uno with a 12V battery through the external power connector and I'm trying to measure the battery voltage. There are many explanations about how to scale down and measure voltages. I am wondering what are the pitfalls when measuring the same voltage that is powering the board.
Either is fine - if the uC is getting 5V from the regulator, than the 12V divided to under 5V for measurement works using EXTERNAL for ARef so 5V is full scale, or to under 1.1V if INTERNAL is used so 1.1 to 1.2V is full scale.
Get the voltage from wherever is convenient, as long as it gets divided down before going into an analog pin.
Default Aref is the 5volt supply.
That can vary a bit on external supply, USB supply or load changes (flashing LEDs, etc.).
Better to use the internal ~1.1volt Aref for voltage measurements.
Here is some code to try.
Leo..
/*
0 - ~16volt voltmeter for 3.3volt and 5volt Arduinos
uses the stable internal 1.1volt reference
6k8 resistor from A0 to ground, and 100k resistor from A0 to +batt
100n capacitor from A0 to ground for stable readings
(100k + 6k8) / 6k8 = 15.70588 | used in formula
*/
float Aref = 1.075; // ***calibrate here*** | change this to the actual Aref voltage of ---YOUR--- Arduino
unsigned int total; // can hold max 64 readings
float voltage; // converted to volt
void setup() {
analogReference(INTERNAL); // use the internal ~1.1volt reference | change (INTERNAL) to (INTERNAL1V1) for a Mega
Serial.begin(9600); // set serial monitor to this value
}
void loop() {
for (int x = 0; x < 64; x++) { // multiple analogue readings for averaging
total = total + analogRead(A0); // add each value to a total
}
voltage = (total / 64) * 15.70588 * Aref / 1024 ; // convert readings to volt
// print to serial monitor
if (total == (1023 * 64)) { // if overflow
Serial.print("voltage too high");
}
else {
Serial.print("The battery is ");
Serial.print(voltage);
Serial.println(" volt");
}
total = 0; // reset value
delay(1000); // one second between measurements
}
gerardospinelli:
Can I use different resistors than the one you used?
voltage = (total / 64) * 15.70588 * Aref / 1024 ; // convert readings to volt
This last formula is still somewhat mysterious to me (why 1024?), but I'll use it nevertheless.
Last question: where do I find the "actual Aref voltage of ---MY--- Arduino"?
Yes, but these values are calculated/optimised for the voltage range of a 12volt car battery.
When using 1.1volt Aref, the voltage divider has to bring down the "voltage to measure" to <= 1.1volt.
If you e.g. would use 1k and 100k, you could measure to ~100volt.
That will bring down resolution though. Now the 1024 steps of the A/D are spread out over 100volt.
Arduino has a 10-bit A/D.
10^2 = 1024.
1.1volt Aref is stable, but not factory calibrated. So it's different for every Arduino board.
It could be 1volt to 1.2volt. The boards I have used hover around the value I have used in the sketch.
Just change the value slightly untill you have the correct voltage readout.
Leo..
I would like to have some protection, meaning that even if the battery goes up to 15V (or 30V), the analog pin still doesnt get more than 5V and I dont burn it.
I'm currently using 1Mohm and 100Kohm for resistors that give me a factor of 1100k/100k=11.
I took this values from some post online so I'm not sure they will give good accuracy, but so far I'm reading reasonable voltage values.
Do you suggest I switch to your resistors? Would they provide the protection I'm looking for?
I'm not looking for perfect accuracy. I just need to know if a battery is healthy (about 12V) or it's about to die (below 11.5V).
When you say "Just change the value slightly untill you have the correct temp readout.", do you mean the correct voltage readout?
and what is the "correct" voltage readout? I suppose I could use my multimeter as a calibration tool...
I guess my question was: is there a way to output the 1.1Aref voltage from the Arduino?
gerardospinelli:
I would like to have some protection, meaning that even if the battery goes up to 15V (or 30V), the analog pin still doesnt get more than 5V and I dont burn it.
I'm currently using 1Mohm and 100Kohm for resistors that give me a factor of 1100k/100k=11.
I took this values from some post online so I'm not sure they will give good accuracy, but so far I'm reading reasonable voltage values.
Do you suggest I switch to your resistors? Would they provide the protection I'm looking for?
I'm not looking for perfect accuracy. I just need to know if a battery is healthy (about 12V) or it's about to die (below 11.5V).
When you say "Just change the value slightly untill you have the correct temp readout.", do you mean the correct voltage readout?
and what is the "correct" voltage readout? I suppose I could use my multimeter as a calibration tool...
I guess my question was: is there a way to output the 1.1Aref voltage from the Arduino?
100k/6k8 will keep the analogue pin under 5volt up to 78.5volt input.
That ratio might have been for default 5volt Aref, or to measure a 9volt battery.
Yes, yes.
My values and code give about the highest accuracy you can get from Arduino's 10-bit A/D.
100k:8k2 gives a fraction higher resolution at the cost of a lower ceiling of ~14volt.
Yes. Corrected. I just posted a temp sketch in another part of the forum. Duhhh.
Best to calibrate the final output with a DMM.
You could measure 1.1volt Aref on the Aref pin (with internal Aref enabled).
But calibrating the final result also eleminates the inaccuracy of the voltage divider resistors.
Leo..
Is it fine to connect the Arduino Uno to the battery with the 2.1mm barrel jack and then use the battery voltage from the Vin pin though the 100k resistor to A0 to measure battery voltage?
This would save me a cable going to the battery.
I see. So the best thing to do is to send another positive 12V from the battery into the 100k resistor of the voltage divider.
Is it safe to take the GND from the Uno for the 6.8K resistor?