Low battery warning

My project is going to be powered via a 12V battery connected to VIN. I've designed the sketch so that it will be in sleep mode 99% of the time. A button will trigger an interrupt, which will activate a 12V motor for < 1 sec then go back to sleep. The motor is pretty tolerable and will work with 9V.

What I'd like to do is when the interrupt is triggered, which will cause loop() to start/continue is to check the voltage on VIN and see if it is less than 9V. If it is < 9V I want to have the LED blink, otherwise fire the motor.

I've tried various code, such as the "secret voltmeter" but everything I've experimented with is not even close to what I'm getting with my DMM. I suspect I'm using the wrong type of read function and may need to use a resistor or two to accomplish this.

Does anyone know of a sketch and breadboard example to read the voltage level from VIN?

You could try posting your code so we can see what you are doing and offer assistance.

Weedpharma

Make a voltage divider over the 12V battery so that the voltage is 4V at X

GND --- [100K] ----x------[200K]---- 12V

measure that with analogRead() --> 4/5 * 1023 = ~819

if the 12V drops to 9V the 4V will drop to 3V

measure with analogRead() --> 3/5 * 1023 = ~614

The difference is significant enough to get an alarm beeping

float voltage = analogRead() * 12.0 /( 4/5 * 1023);
or
float voltage = analogRead() * 0.014652; //

1 Like

What battery technology are you using?

Lead acid batteries should not be discharged below 1.65VPC (Volts Per Cell) and typically a cyclic system should really not drop below about 1.8VPC.

How often will the battery discharge to 9v?
This low voltage will greatly affect cycle life and will void almost any warranty.

Does the battery get recharged in situ or do you remove it?
If charged in situ then be careful to ensure that your voltage divider circuit will not pass greater than 5 volts to the analog input (I use a 20VDC = 5VDC divider for 12v nominal Lead Acid batteries)

robtillaart:
Make a voltage divider over the 12V battery so that the voltage is 4V at X

GND --- [100K] ----x------[200K]---- 12V

measure that with analogRead() --> 4/5 * 1023 = ~819

if the 12V drops to 9V the 4V will drop to 3V

measure with analogRead() --> 3/5 * 1023 = ~614

The difference is significant enough to get an alarm beeping

float voltage = analogRead() * 12.0 /( 4/5 * 1023);
or
float voltage = analogRead() * 0.014652; //

By X, do you mean one of the analog pins?

yes.

robtillaart:
Make a voltage divider over the 12V battery so that the voltage is 4V at X

GND --- [100K] ----x------[200K]---- 12V

measure that with analogRead() --> 4/5 * 1023 = ~819

if the 12V drops to 9V the 4V will drop to 3V

measure with analogRead() --> 3/5 * 1023 = ~614

The difference is significant enough to get an alarm beeping

float voltage = analogRead() * 12.0 /( 4/5 * 1023);
or
float voltage = analogRead() * 0.014652; //

The equation for a voltage divider is:

And using the values for Vin (12) and R1 (100) and R2(200) that would yield

Vout = 12 * (100)/(100 + 200) which simplifies to

Vout = 12 * (1/3) = 4 (which is what you indicated what I should expect).

What I don't understand are your formulas:

analogRead() --> 4/5 * 1023 = ~819
analogRead() --> 3/5 * 1023 = ~614

Did you really mean I should do something like:

FourVolts = 4/5 * 1023;
ThreeVolts = 3/5 * 1023;

voltageGood = (analogRead(x) >= ThreeVolts);

You still didn't mention if your 12V battery is lead-acid. If so, 9V is far too low. Discharging to 9V can damage the battery.
A lead-acid battery is down to only 10% charge at about 11.9V, if only very lightly loaded, (C/100).
Under almost no load as you describe, 9V=dead. (or dying)


I cut off the top of the graph, because it only relates to charging, not discharge.

FutureTense:
The equation for a voltage divider is:

And using the values for Vin (12) and R1 (100) and R2(200) that would yield

Vout = 12 * (100)/(100 + 200) which simplifies to

Vout = 12 * (1/3) = 4 (which is what you indicated what I should expect).

What I don't understand are your formulas:

analogRead() --> 4/5 * 1023 = ~819
analogRead() --> 3/5 * 1023 = ~614

Did you really mean I should do something like:

FourVolts = 4/5 * 1023;
ThreeVolts = 3/5 * 1023;

voltageGood = (analogRead(x) >= ThreeVolts);

you got the idea 110%

OldSteve:
You still didn't mention if your 12V battery is lead-acid. If so, 9V is far too low. Discharging to 9V can damage the battery.
A lead-acid battery is down to only 10% charge at about 11.9V, if only very lightly loaded, (C/100).
Under almost no load as you describe, 9V=dead. (or dying)


I cut off the top of the graph, because it only relates to charging, not discharge.

I'm using 8 AA alkaline batteries. The sketch has the unit in sleep mode (to preserve battery life)and awoken by two interrupts. One is a manual interrupt fired by a simple button. The other is a Mercury switch.

Regardless of which switch wakes up the device, I want to check the battery level and if below 9V flash the LED to let the user know it's time to replace the batteries.

FutureTense:
I'm using 8 AA alkaline batteries. The sketch has the unit in sleep mode (to preserve battery life)and awoken by two interrupts. One is a manual interrupt fired by a simple button. The other is a Mercury switch.

Regardless of which switch wakes up the device, I want to check the battery level and if below 9V flash the LED to let the user know it's time to replace the batteries.

No worries. Often when people say 12V, they mean lead-acid, and I didn't want to see you kill a lead-acid battery.

At 9V, (1V per cell), your AA batteries will be getting pretty flat, but as long as they can power the motor at the speed you want down to that voltage that doesn't matter.

Carry on. :smiley:

(Did you get it working OK, using the suggested voltage divider?)

OldSteve:
No worries. Often when people say 12V, they mean lead-acid, and I didn't want to see you kill a lead-acid battery.

At 9V, (1V per cell), your AA batteries will be getting pretty flat, but as long as they can power the motor at the speed you want down to that voltage that doesn't matter.

Carry on. :smiley:

(Did you get it working OK, using the suggested voltage divider?)

Not yet. I had to order the resistors. One thing I've noticed is that my motor performs differently at various voltage levels.

I would like some consistency. Shouldn't it be possible to use a resistor to ensure my motor never gets more than 9V, even though it's rated for 12?

FutureTense:
I would like some consistency. Shouldn't it be possible to use a resistor to ensure my motor never gets more than 9V, even though it's rated for 12?

No. A resistor could be chosen such that when the battery voltage is 12.0V, the motor gets 9V, but then when the battery drops to 9V, the motor would only get 6.75V. Also the voltage dropped across the resistor would vary with load.

I would like some consistency. Shouldn't it be possible to use a resistor to ensure my motor never gets more than 9V, even though it's rated for 12?

The best you can do is use a SMPS (lots on eBay).
SMPS
.

LarryD:
The best you can do is use a SMPS (lots on eBay).
SMPS
.

And even then, with a buck converter, there'll be a dropout voltage, so at 9Vin the motor won't get the full 9V.
I'm not sure what the typical dropout voltage is for those converters. The specs of most seem to indicate a couple of volts.

I have no idea whether the 'automatic' step-up/step-down type can output the same voltage as the input.
(To be effective, I guess they should.)

I have no idea whether the 'automatic' step-up/step-down type can output the same voltage as the input.
(To be effective, I guess they should.)

Yes they can.

LarryD:
Yes they can.

Oh good. Thanks Larry, that's handy to know. I might grab a couple, just in case.

I did the the same thing :slight_smile:

analogRead() --> 4/5 * 1023 = ~819
analogRead() --> 3/5 * 1023 = ~614

What Im not clear is how analogRead works. It returns a value between 0 and 1023, where 0 volts is 0 and 5V 1023, yes?

So if I have a voltage divider dropping the voltage from 12V to 5V (not 4V in your example) analogRead would return 1023 assuming VIN is 12V?

And back to the 4V divider, the max analogRead could ever return (at VIN =12) would be 4/5*1023?

If you have a voltage divider that outputs 5V when the input to the divider is 12V.

const int analogInPin = A0;  // Analog input pin that the potentiometer is attached to

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


void loop() 
{
  // read the analog in value:
  int myReading = analogRead(analogInPin);            
  
// map it to the range of the analog out:
  float voltage = map(myReading, 0, 1023, 0, 1200);  
      
  Serial.println(voltage/100.0);   
  delay(500);                     
}