Hi!
In my project i'm using 12v car battery to power arduino mega. As this is going to be used outside in minus degrees Celsius I want to measure batteries voltage, so I know when to charge it so I wont damage it. So below I have drawn schematic of my whole system. And following this thread I plant to implement this function. But before i wire anything up I wanted to ask you guys two thing:
Is this going to work? And not blow up my battery or arduino
Maybe i should connect arduino to 5v converter not to 12v battery? Is this going to save battery more?
/*
0 - ~17volt voltmeter
works with 3.3volt and 5volt Arduinos
uses the internal 1.1volt reference
150k resistor from A1 to +batt
10k resistor from A1 to ground
optional 100n capacitor from A1 to ground for stable readings
*/
float Aref = 1.063; // change this to the actual Aref voltage of ---YOUR--- Arduino, or adjust to get accurate voltage reading (1.000- 1.200)
unsigned int total; // A/D output
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() {
analogRead(1); // one unused reading to clear old sh#t
for (int x = 0; x < 16; x++) { // 16 analogue readings and 1/16 voltage divider = no additional maths
total = total + analogRead(1); // add each value
}
voltage = total * Aref / 1024; // convert readings to volt
// print to serial monitor
Serial.print("The battery is ");
Serial.print(voltage);
Serial.println(" volt");
total = 0; // reset value
delay(1000); // readout delay
}
Automotive electrical systems can be very noisy with lots of voltage spikes. I recommend putting a series diode in line with the power for your electronics. I would do some filtering on the power before it gets to your regulator. Not just a capacitor, but also a series inductor to act as a block to voltage spikes.
I usually design for an expected maximum voltage of 60 volt spikes. I have used a circuit to cut off the power when the voltage gets above 22 volts.
atis-sedlenieks:
Isn't this just the same as I have drawn, just drawn differently?
No. Yours is not a voltage divider. It does not have two resistors connected in series between 12V and ground and the A1 pin is not connected to the junction between them.
damn, your right, I'm s#it at schematics..
So based on previous suggestions, I have updated my schematic.
Not sure about diode though.. I picked this 15v. Not sure if this is right one.
No, the diode is neither needed nor helpful in series with the voltage divider. The suggestion was to put the diode in series with the voltage converter to provide "additional" protection but as it only protects against reverse voltage, not surges, that is somewhat moot.
Also you are showing powering the Arduino from the raw 12 V. That is what was strictly advised against. If you have a voltage converter ("buck" regulator) rated to mange an automotive voltage input, then that is what powers the Arduino via the 5V pin.
If you use the internal
ADC reference , which is around 1.1v , you can make your divider up to give 1.1v at say 13v input .
As the ADC is still protected to 5v , this protects the input to much higher input voltages. ( around 65v)
outsider:
That IS a TVS diode, 15V, but in the wrong place
ohh, so where should I consider placing it?
outsider:
5V to the barrel jack won't work, must be at least 7
yeah I found out that I'm planning on connecting one end of usb cable to 5V converter. In that way I will get solid connection and won't worry about accidentally using USB and 5V pin together and burning down arduino..
You cannot damage the UNO/ Nano by connecting both 5 V input and USB.
The only concern is that you may upset the PC or (especially) Laptop by feeding current at 5 V back into its USB port. Some people have reported this, but since the great majority of powered USB hubs will do exactly that and there is no outcry, it would seem unlikely.
Of course if your external supply is say, 5**.8** Volts, that may be a problem.
Paul__B:
You cannot damage the UNO/ Nano by connecting both 5 V input and USB.
ahh ok, good to know. But I still prefer sturdy usb connection.
So I managed to hook everything up and it work, kind of..
The problem is, reading differs from multimeter reading.
I get 12.75V from arduino and 12.53V from multimeter..
Why is that?
Should I just adjust Aref value?
I use this code (together with temp.sensor):
#include <Tlc5940.h>
unsigned long startMillis; // some global variables available anywhere in the program
unsigned long currentMillis;
const unsigned long period = 2000; // the value is a number of milliseconds
// //////////////TEMP////////////
// //////////////TEMP////////////
unsigned int totalTemp;
const int sensor = A5; // Assigning analog pin A5 to variable 'sensor'
float vout; // temporary variable to hold sensor reading
float tempC;
// //////////////TEMP////////////
// //////////////TEMP////////////
/*
0 - ~17volt voltmeter
works with 3.3volt and 5volt Arduinos
uses the internal 1.1volt reference
150k resistor from A1 to +batt
10k resistor from A1 to ground
optional 100n capacitor from A1 to ground for stable readings
*/
//float Aref = 1.063; // change this to the actual Aref voltage of ---YOUR--- Arduino, or adjust to get accurate voltage reading (1.000- 1.200)
float Aref = 1.1;
unsigned int totalVolt; // A/D output
float voltage; // converted to volt
/////////////////////
void setup()
{
// //////////////TEMP//////////////
analogReference(INTERNAL1V1); // use the internal ~1.1volt reference, change INTERNAL to INTERNAL1V1 for a Mega
pinMode(sensor, INPUT); // TEMP PIN
Serial.begin(9600);
startMillis = millis();
Tlc.init();
}
void loop()
{
currentMillis = millis(); // get the current "time" (actually the number of milliseconds since the program started)
if (currentMillis - startMillis >= period)
//test whether the period has elapsed
{
readBattery();
readTemp();
// ////////////////
Tlc.clear();
startMillis = currentMillis;
}
}
float readTemp() {
vout = analogRead(sensor); // one unused reading
//
for (int x = 0; x < 20; x++) { // 20 readings for averaging
vout = analogRead(sensor); // one unused reading
totalTemp = totalTemp + vout; // add each value to a totalTemp
}
if (totalTemp == 20460) { // max value with 20 readings
Serial.println(" ----too hot----");
}
else {
tempC = totalTemp * 0.00519043; // calibration maths, depends on actual Vref, (0.0048828125 * Vref in volts)
Serial.print("The temperature is ");
Serial.print(tempC, 2); // two decimal places
Serial.println("C");
}
totalTemp = 0; // reset value
}
float readBattery() {
analogRead(1); // one unused reading to clear old sh#t
for (int x = 0; x < 16; x++) { // 16 analogue readings and 1/16 voltage divider = no additional maths
totalVolt = totalVolt + analogRead(1); // add each value
}
voltage = totalVolt * Aref / 1024; // convert readings to volt
// print to serial monitor
Serial.print("The battery is ");
Serial.print(voltage);
Serial.println(" volt");
totalVolt = 0; // reset value
}
One of the things I have been doing recently, with the Arduino A:D circuit is putting an unused A:D channel to ground. I then take a measurement of that grounded channel and subtract that measurement from the actual A:D reading. Not all the time, but I found, with the A:D having a multiplexed input, that sometimes the ground reading is not a 0.
I have, also, found soldered joints are one of the great noise reducers.
You may need to apply a voltage above and below, in steps, of your ideal voltage to be measures to find the curve of accuracy and, perhaps, an offset value.
For the Uno and MEGA, I found a ceramic capacitor pushed into the aref pin and ground, also, adds to A:D stability.
From using a Mini Pro, I soldered the resistor divider to the board A:D input pins and ground. A stabilizing and accuracy improving solution that I applied to the Uno and MEGA. I use hot glue to keep the resistors in place and to insulate them from the board. I bring the voltage to be measure to the, on board, soldered divider and, after soldering, apply hot glue as an insulator. Keeping the connections short to the A:D seems to be a big help.
I found the A:D converter on the DUE to behave quite well and its 12 bit to boot.
Hmm some very strange things are happening! :o
Everything, voltmeter and temp. meter works fine when I connect arduino to 12v battery via dc jack and test via usb to pc serial monitor.
BUT when i connect arduino to 5v converter via usb i get 0 volt. and 0 temp. readings! ( i send them via gsm shield to server)
It has something to do with internal reference not working from same battery??
I use scheme below:
#include <Tlc5940.h>
unsigned long startMillis; // some global variables available anywhere in the program
unsigned long currentMillis;
const unsigned long period = 2000; // the value is a number of milliseconds
// //////////////TEMP////////////
// //////////////TEMP////////////
unsigned int totalTemp;
const int sensor = A5; // Assigning analog pin A5 to variable 'sensor'
float vout; // temporary variable to hold sensor reading
float tempC;
// //////////////TEMP////////////
// //////////////TEMP////////////
/*
0 - ~17volt voltmeter
works with 3.3volt and 5volt Arduinos
uses the internal 1.1volt reference
150k resistor from A1 to +batt
10k resistor from A1 to ground
optional 100n capacitor from A1 to ground for stable readings
*/
//float Aref = 1.063; // change this to the actual Aref voltage of ---YOUR--- Arduino, or adjust to get accurate voltage reading (1.000- 1.200)
float Aref = 1.1;
unsigned int totalVolt; // A/D output
float voltage; // converted to volt
/////////////////////
void setup()
{
// //////////////TEMP//////////////
analogReference(INTERNAL1V1); // use the internal ~1.1volt reference, change INTERNAL to INTERNAL1V1 for a Mega
pinMode(sensor, INPUT); // TEMP PIN
Serial.begin(9600);
startMillis = millis();
Tlc.init();
}
void loop()
{
currentMillis = millis(); // get the current "time" (actually the number of milliseconds since the program started)
if (currentMillis - startMillis >= period)
//test whether the period has elapsed
{
readBattery();
readTemp();
// ////////////////
Tlc.clear();
startMillis = currentMillis;
}
}
float readTemp() {
vout = analogRead(sensor); // one unused reading
//
for (int x = 0; x < 20; x++) { // 20 readings for averaging
vout = analogRead(sensor); // one unused reading
totalTemp = totalTemp + vout; // add each value to a totalTemp
}
if (totalTemp == 20460) { // max value with 20 readings
Serial.println(" ----too hot----");
}
else {
tempC = totalTemp * 0.00519043; // calibration maths, depends on actual Vref, (0.0048828125 * Vref in volts)
Serial.print("The temperature is ");
Serial.print(tempC, 2); // two decimal places
Serial.println("C");
}
totalTemp = 0; // reset value
}
float readBattery() {
analogRead(1); // one unused reading to clear old sh#t
for (int x = 0; x < 16; x++) { // 16 analogue readings and 1/16 voltage divider = no additional maths
totalVolt = totalVolt + analogRead(1); // add each value
}
voltage = totalVolt * Aref / 1024; // convert readings to volt
// print to serial monitor
Serial.print("The battery is ");
Serial.print(voltage);
Serial.println(" volt");
totalVolt = 0; // reset value
}
All the talk about car systems having loads of spikes and all is only relevant if there are any 'coils' spinning and relays switching. If you are just waiting for the battery to go flat while the engine isn't running and the windscreenwipers are off and you do not want to start the car, these spikes don't happen, Battery power is extremely stable. But on another note, why do you use a voltage divider and not an OP-amp ? and where is your inductor ? aren't inductors the way to remove unwanted AC-current from a circuit (there is one in you step-down i suspect) Also if you are just looking for a specific low power level to decide if you should start charging why don't you just use a low voltage-chip ?
Deva_Rishi:
All the talk about car systems having loads of spikes and all is only relevant if there are any 'coils' spinning and relays switching. If you are just waiting for the battery to go flat while the engine isn't running and the windscreenwipers are off and you do not want to start the car, these spikes don't happen, Battery power is extremely stable. But on another note, why do you use a voltage divider and not an OP-amp ? and where is your inductor ? aren't inductors the way to remove unwanted AC-current from a circuit (there is one in you step-down i suspect) Also if you are just looking for a specific low power level to decide if you should start charging why don't you just use a low voltage-chip ?
Battery is off car, sitting in my art installation. i use voltage divider because when searching for how to measure voltage, I found this approach. Yes, i'm waiting for battery to go below 12v to know when to replace it with charged one- nevar heard of low-voltage chip.. And voltage divider system did work and do work when I supply 12v to arduino. When supplying 5v it doesn't