Monitor 12v battery


#1

Hi,

Please can someone point me in the right direction regarding the circuit please?

I’d like to monitor the voltage of a 12v car battery (well my camper van) and when the voltage drops below a certain threshhold send an alert to my android device. So I can plug my trickle charger in.

I’ve got all the push notifications code already working as part of a shed alarm project.

I need help on the circuit and best practices regarding powering the spark core from 12v the battery that is being monitored.

I’ve found this link with regards to reading the 12v battery voltage which uses resistors to step down to a safe 4.5v, does it have to be 3.3v for the spark code?
http://fritzing.org/projects/voltage-divider

Thanks


Detecting charge level of a LiPo Battery
#2

The voltage divider will work but your top rail, the positive end will be connected to the battery voltage and you will need to calculate the resistor values required to achieve about a 3v value to feed into the Spark analog input when the battery is fully charged. These values should be quite high and you will need to take into account the input impedance of the Spark. To power the Spark from the same battery you could use a simple Linear regulator to drop the 12 V to a usable input for the Spark, however with a 12v input you will generate quite a lot of heat.
I would suggest a Switching Regulator, for example http://www.pololu.com/product/2844
There are many others out there depending on your current requirement.

Note that if you use the resistor divider and feed that directly into the Analog input, you will not have a very large change between a fully charged battery (13v?) and a flat battery (10v?). So depending on the accuracy and resolution that you need, you may want to consider an external ADC or an Op-Amp comparator.
If you are just trying to see the battery is charged or not, the simple divider will work fine.


#3

Brungle, I’m thinking of doing the exact same thing. Did you get this working? Do you have code you can share?


#4

bishopuniverse, unfortunately not, I gave up in the end as it was all a bit beyond me.
do let me know if you ever get anywhere though as I would like this functionality for my campervan which is often left stood for long periods.

thanks


#5

@bishopuniverse and @Brungle, there are two parts to your solution. The first is how to power the core from the 12V battery. This can be done a few ways: with an efficient “step-down” switching regulator like this Polulu unit or using a cigarette lighter USB phone charger adapter with a suitable USB cable. Both provide 5V to the Core. There are lots of other ways but you need to find the one you feel most comfortable with implementing.

The second part of the solution is monitoring the battery voltage (up to 15V) with the max 3.3V analog input of the Core. You can do that using a voltage divider to step the higher voltage down to a max of 3.3V.

            battery V+ -------R1----+----- A0 (Spark)
                                    |
                                    R2
                                    |
           battery GND -------------+

           R1 = 120K, R2 = 33K

With decent (1%) resistor, at 15V the analog input of the Core will be 3.235 volts. So, where you would read the analog voltage at A0 in your code, you would apply a ratio to calculate the equivalent battery voltage. The Core has a 12bit ADC so at 3.3V, the ADC value will be 4095. This gives a voltage-per-bit of 3.3v/4095.

const float voltsPerBit = 3.3 / 4095;  // Calculate volts per bit of ADC reading
const float ratioV = (120000 + 33000) / 33000;  //Calculates to 4.636363

int rawVolts = analogRead(A0) * voltsPerBit;  //Calculate voltage at A0 input
batteryVolts = rawVolts * ratioV;

At the typical battery voltage of 13.8V, you will get 2.976 volts at input A0 and an analogRead() value of about 3693. This makes rawVolts = 3693 * (3.3 / 4095) = 2.976 and batteryVolts = 2.976 * (120000 + 33000) / 33000 = 13.8. Hope that helps! :smile:

I hope that helps :smile:


#6

brilliant @peekay123 this is exactly what I needed.

Thank you


#8

@peekay123: Are there any dedicated ICs to do fairly HV (0-250v maybe) voltage sense? I’d like to essentially replicate a multi-meter or volt-meter. Any ideas how to do it? I’ve looked around before and never really found a good answer.


#9

@Brungle hopefully you are up and running now with your project. Reading over things I noticed you are thinking of powering your Spark Core from the battery you are monitoring. This will inevitably aid in it’s discharge rate more than you might think. I would like to suggest making use of the Spark.sleep(SLEEP_MODE_DEEP, int seconds); command, and making your Spark Core go to sleep for somewhat long periods of time (5 to 10 minutes) to conserve your battery’s energy.

You can also use SYSTEM_MODE(MANUAL); http://docs.spark.io/firmware/#advanced-system-modes-semi-automatic-mode to keep the Core from powering up in a power hungry state, read your A/D input and if it’s sensing your battery is too low, you can call Spark.connect(); to get connected to the Cloud again. You’ll also have to call Spark.process(); from your user loop(); see the example code in the above Docs link.


#10

@BDub

nope I’ve still not had chance to revisit this we have a newborn so I’m a bit limited on tinkering time at the moment!

I had a brief look into the sleep functionality but wasn’t aware of the system_mode so thanks for that.

I will implement this little project at some point!

thanks


#11

@harrisonhjones, there are no dedicated ICs as such to monitor high voltage. Usually, it is done with a voltage divider. When you say 0-250V, do you mean DC or AC voltage?


#12

Well, I was really just curious about how the cheap $5 mulitmeters you can buy at Radioshack can measure low-high AC and DC voltages


#13

Hi @harrisonhjones

Usually the cheap multimeters have a single IC in them, sometimes in a package but more often under a blob of epoxy in what is called chip-on-board, that does all the measurement and display driving.

Generally these use low-speed dual-slope converters that measure the time it takes to charge/discharge a capacitor to fixed voltage levels derived from a band-gap reference. The meter IC itself often reads in the range of 0-100mV or 0-200mV. The meter IC also directly drives the LED or LCD display. Usually there are external resistors to get the different voltage ranges, just as outlined by @peekay123 above.

Here is a datasheet for an older part so you can get the idea:

Unless you have a lot of engineering experience, I cannot really recommend trying to build or hack something that measures higher voltages. There are a lot of potential safety problems.


#14

@harrisonhjones, to add to @bko’s fantastic comments, voltages above 60V AC or DC can be dangerous and potentially lethal. :smile:


#15

Hello, Im trying to duplicate your example, but Im getting 0 Volt on the Serialprint. Am I missing something?
the code is bellow. Thank You in Advance.

const float voltsPerBit = 3.3 / 4095;  // Calculate volts per bit of ADC reading
const float ratioV = (120000 + 33000) / 33000;  //Calculates to 4.636363

int rawVolts = analogRead(A0) * voltsPerBit;  //Calculate voltage at A0 input
int batteryVolts = rawVolts * ratioV;


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

void loop() 
{
   delay(3000);
   Serial.print("Voltage ");
   Serial.print(batteryVolts);
   
}

#16

@Kuto, if you want to print the voltage every 3 seconds, you need to do this:

const float voltsPerBit = 3.3 / 4095;  // Calculate volts per bit of ADC reading
const float ratioV = (120000 + 33000) / 33000;  //Calculates to 4.636363


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

void loop() 
{
   int rawVolts = analogRead(A0) * voltsPerBit;  //Calculate voltage at A0 input
   int batteryVolts = rawVolts * ratioV;
   Serial.print("Voltage ");
   Serial.print(batteryVolts);
   delay(3000);
}

The way you had it would not work since you are trying to initialize variables with functions prior to setup(). Declaring int rawVolts and batteryVolts is ok, making them globals but not the function part. With the code above, rawVolts and batteryVolts are now local to loop() but that’s ok because that’s the only place you use them. :smile:


#17

One thing that seems unusual, the voltage is not being read within the loop()
Second thing I would do to debug, is display the raw reading also.


#18

Thank You for your support.
Im still getting 0 voltage )-;


#19

What about the raw reading printout?
Can you show us your new/current script ?
What do you have hooked to A0 ?


#20

Here is the code. and right now I’m applying 5.0 v
Im getting in raw output 1453

const float voltsPerBit = 3.3 / 4095;  // Calculate volts per bit of ADC reading
const float ratioV = (120000 + 33000) / 33000;  //Calculates to 4.636363


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

void loop() 
{
   int Vin = analogRead(A0);
   int rawVolts = Vin * voltsPerBit;  //Calculate voltage at A0 input
   int batteryVolts = rawVolts * ratioV;
   Serial.print("Voltage ");
   Serial.print(batteryVolts);
   Serial.print("  Raw ");
   Serial.print (Vin);
   delay(3000);
}

#21

analogPins doesn’t allow > 3.3v… :see_no_evil: