Author Topic: Battery Voltage Monitoring  (Read 24331 times)

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 5841
  • Country: us
    • LowPowerLab
Re: Battery Voltage Monitoring
« Reply #30 on: August 27, 2014, 01:29:50 PM »
Unterminated ADC channels will show a bogus low value reading even if you wave your hand around the board ;)

Charly86

  • Jr. Member
  • **
  • Posts: 74
  • Country: fr
Re: Battery Voltage Monitoring
« Reply #31 on: August 27, 2014, 06:42:44 PM »
Sure, and don't forget to trash 1st reading also  ;)

Kitsibas

  • Newbie
  • *
  • Posts: 8
Re: Battery Voltage Monitoring
« Reply #32 on: October 11, 2014, 03:01:35 PM »
Hi,

i try to build battery voltage monitor using the P-FET element. i connected all like i read on this blog entry: http://fettricks.blogspot.com/2014/01/reducing-voltage-divider-load-to-extend.html

it dont work :) but I do not know if I have the correct element. i use: http://datasheet.octopart.com/IRF9Z34N-International-Rectifier-datasheet-7830620.pdf

It is good? if not could you give me correct one.

Thanks

dave_sausages

  • Newbie
  • *
  • Posts: 49
Re: Battery Voltage Monitoring
« Reply #33 on: August 30, 2016, 08:00:03 PM »
I know this thread has been silent for a while, but I thought I'd chime in as I'm sure people will will still be using the ideas in this thread.

Regarding the original post:
There was mention on the forum about using Moteino to measure its own battery supply voltage.  As already mentioned you can use a two resistor voltage divider and connect it to an analog pin.  The down side of this is that it always drains power from the battery.

Also mentioned was a solution using a transistor to turn the pwr off to the divider.  There was a concern about the number of parts/complexity.  An additional Moteino I/O pin is needed to turn the xstr on/off too.

If you decide you want to monitor your battery and not increase battery drain try this.  Take your two resistor divider and instead of connecting the bottom resistor to ground connect it to a digital I/O pin.

When you want to read the voltage set the pin for output and set it low.  After you get your analog voltage reading, set the pin to input (high impedance).

If you are crafty you can probably use a pin that is now dedicated for a single task.  For instance, say you have an I/O pin dedicated as a chip select line.  Maybe it's for external ram or the data input for a digital temperature chip.  Look at your circuit if you've run short on pins, I bet you'll figure out a way to 'code' multiplex a pin.

Am I correct in thinking that if the Digital Pin (ground of voltage divider) goes high impedance, then the Analogue Pin that is measuring the voltage will see the full voltage being supplied to the battery connection of the voltage divider? And as the ATmega's have protection diodes that short to ground if more than vcc + 0.5v is applied to them, then it will connect to ground anyway?

Just wanted to help out any future people looking for simple voltage measuring options with no wasted current.

TomWS

  • Hero Member
  • *****
  • Posts: 1877
Re: Battery Voltage Monitoring
« Reply #34 on: August 30, 2016, 08:29:11 PM »
I know this thread has been silent for a while, but I thought I'd chime in as I'm sure people will will still be using the ideas in this thread.

Regarding the original post:
There was mention on the forum about using Moteino to measure its own battery supply voltage.  As already mentioned you can use a two resistor voltage divider and connect it to an analog pin.  The down side of this is that it always drains power from the battery.

Also mentioned was a solution using a transistor to turn the pwr off to the divider.  There was a concern about the number of parts/complexity.  An additional Moteino I/O pin is needed to turn the xstr on/off too.

If you decide you want to monitor your battery and not increase battery drain try this.  Take your two resistor divider and instead of connecting the bottom resistor to ground connect it to a digital I/O pin.

When you want to read the voltage set the pin for output and set it low.  After you get your analog voltage reading, set the pin to input (high impedance).

If you are crafty you can probably use a pin that is now dedicated for a single task.  For instance, say you have an I/O pin dedicated as a chip select line.  Maybe it's for external ram or the data input for a digital temperature chip.  Look at your circuit if you've run short on pins, I bet you'll figure out a way to 'code' multiplex a pin.

Am I correct in thinking that if the Digital Pin (ground of voltage divider) goes high impedance, then the Analogue Pin that is measuring the voltage will see the full voltage being supplied to the battery connection of the voltage divider? And as the ATmega's have protection diodes that short to ground if more than vcc + 0.5v is applied to them, then it will connect to ground anyway?

Just wanted to help out any future people looking for simple voltage measuring options with no wasted current.
The resistor divider described in the original post would, when the digital pin is high, cause the voltage on the analog pin to be divided between VBat and VCC (ATMega328P)  power supply.  If this causes the pin voltage to go 0.5V above VCC then you've exceeded the Absolute Maximum ratings of the device (Section 29.1).   It would also reverse bias the output pin, but, if it's still configured as an output then this probably won't be an issue.  If it's High Impedance, then this would definitely exceed the maximum on two pins (Digital control and Analog input).  Whether this causes a problem or simply 'leaks' current is going to be determined by the internal transistor design of the device.  IMO (and experience), the Absolute Maximum ratings exist for a reason and shouldn't be trifled with.

Load switches are cheap and small.   On a breadboard you can probably get away with a lot of, uh, 'flexibility'.  On a mote you depend on, Mother Nature makes sure you don't mess with her...

Tom

dave_sausages

  • Newbie
  • *
  • Posts: 49
Re: Battery Voltage Monitoring
« Reply #35 on: September 15, 2016, 07:57:41 PM »
So I used a standard /2 voltage divider on all my nodes to measure the battery voltage, and all is well with reading the voltage. Except I'm currently chasing my tail on one of my Arduino Pro Mini nodes that communicates to my Moteino via bluetooth. When the voltage reported drops below 3.68 volts, the node stops functioning.

****edit****

Aha! I've worked it out. it does not stop functioning at 3.68 volts.....that's just the lowest point at which the voltage divider gives an accurate and or useful reading.

You see my pro-mini has a 3.3v regulator on it and I've measured a 350mv drop on it. So below about 3.7 battery volts, the regulator output and battery voltage fall by the same amount....meaning that the ADC never sees a change because the ratio of battery to 3.3v feed is the same!

So how can I get around this? Can I use the secret inbuilt voltage sense in the 328p? And switch to that when the input voltage to the 328p drops below 3.3v?


TomWS

  • Hero Member
  • *****
  • Posts: 1877
Re: Battery Voltage Monitoring
« Reply #36 on: September 15, 2016, 09:56:29 PM »
So I used a standard /2 voltage divider on all my nodes to measure the battery voltage, and all is well with reading the voltage. Except I'm currently chasing my tail on one of my Arduino Pro Mini nodes that communicates to my Moteino via bluetooth. When the voltage reported drops below 3.68 volts, the node stops functioning.

****edit****

Aha! I've worked it out. it does not stop functioning at 3.68 volts.....that's just the lowest point at which the voltage divider gives an accurate and or useful reading.

You see my pro-mini has a 3.3v regulator on it and I've measured a 350mv drop on it. So below about 3.7 battery volts, the regulator output and battery voltage fall by the same amount....meaning that the ADC never sees a change because the ratio of battery to 3.3v feed is the same!

So how can I get around this? Can I use the secret inbuilt voltage sense in the 328p? And switch to that when the input voltage to the 328p drops below 3.3v?
Battery voltage measurements should be made against the 1.1V reference voltage so that they are not a ratio of VCC but referenced to an absolute voltage.  There are plenty of references around this forum on the Web for this technique.

Tom

dave_sausages

  • Newbie
  • *
  • Posts: 49
Re: Battery Voltage Monitoring
« Reply #37 on: September 15, 2016, 10:32:40 PM »
So I used a standard /2 voltage divider on all my nodes to measure the battery voltage, and all is well with reading the voltage. Except I'm currently chasing my tail on one of my Arduino Pro Mini nodes that communicates to my Moteino via bluetooth. When the voltage reported drops below 3.68 volts, the node stops functioning.

****edit****

Aha! I've worked it out. it does not stop functioning at 3.68 volts.....that's just the lowest point at which the voltage divider gives an accurate and or useful reading.

You see my pro-mini has a 3.3v regulator on it and I've measured a 350mv drop on it. So below about 3.7 battery volts, the regulator output and battery voltage fall by the same amount....meaning that the ADC never sees a change because the ratio of battery to 3.3v feed is the same!

So how can I get around this? Can I use the secret inbuilt voltage sense in the 328p? And switch to that when the input voltage to the 328p drops below 3.3v?
Battery voltage measurements should be made against the 1.1V reference voltage so that they are not a ratio of VCC but referenced to an absolute voltage.  There are plenty of references around this forum on the Web for this technique.

Tom

I see, so I should change my voltage divider so the Arduino input never goes above 1.1v? And then configure my ADC to use the 1.1v reference instead of the vcc?

TomWS

  • Hero Member
  • *****
  • Posts: 1877
Re: Battery Voltage Monitoring
« Reply #38 on: September 16, 2016, 07:44:46 AM »
I see, so I should change my voltage divider so the Arduino input never goes above 1.1v? And then configure my ADC to use the 1.1v reference instead of the vcc?
That's one way. 

Another way is to measure 1.1V in relation to VCC as your reference and this will tell you exactly what the processor's VCC voltage is (see many examples of reading VCC).  Then, knowing this value, measure your incoming voltage still using VCC as the reference, but scale the result to the REAL VCC value, not some 'assumed' VCC value. 

Tom

WhiteHare

  • Hero Member
  • *****
  • Posts: 1297
  • Country: us
Re: Battery Voltage Monitoring
« Reply #39 on: September 19, 2016, 01:34:56 PM »

SupaJah

  • Newbie
  • *
  • Posts: 4
Re: Battery Voltage Monitoring
« Reply #40 on: February 27, 2018, 07:45:22 PM »
Hi. I hope some of you guys are still around to help me with this.

I have tried the battery voltage monitoring technique described in the opening post without any success on an ATMega328p running at 1Mhz. Instead of connecting R2 of the voltage divider directly to GND, R2 is connected to D12 and set low just before reading the battery voltage. The analogRead function always returns the maximum, 1024. Initially, I thought it was the sketch looping too fast, so I introduced a 10 ms delay after the analogRead function so that D12 can be properly 'grounded' before the battery voltage is read but that still didn't work.

My voltage divider circuit resembles this: Vin(3v) -- 1M(R1) -- A1 (Vo) -- 300K(R2) -- D12

D12 is the BATTERY_ENABLE_PIN.
My AnalogRefence is set to INTERNAL(1.1v).

Here's the code:
Code: [Select]
    pinMode(BATTERY_ENABLE_PIN, OUTPUT);
    digitalWrite(BATTERY_ENABLE_PIN, LOW);
    voltage = analogRead(A1);
    delay(10);
    pinMode(BATTERY_ENABLE_PIN, INPUT);

BTW, the battery monitor works if R2(300K) is connected directly to GND. Problem is when it is connected to D12, to save energy consumed by the divider as described above.
« Last Edit: February 27, 2018, 07:56:38 PM by SupaJah »

TomWS

  • Hero Member
  • *****
  • Posts: 1877
Re: Battery Voltage Monitoring
« Reply #41 on: February 27, 2018, 09:18:39 PM »
I'm not sure why you're doing it the way you're doing it if the input voltage <= VCC of the ATmega chip.  You can just read the input voltage directly in this case.  However, given your question, I think you should move the delay BEFORE the analogRead() call.  This will give the voltage time to settle on the input prior to reading it.

What are you trying to read?  If it is the ATmega's power supply voltage, there are already a ton of routines posted on this forum that do that AND you don't need any resistors!  Search the forum for "readVCC".  I'm sure you'll find something useful (probably a lot of crap too, but ignore that).

Tom

SupaJah

  • Newbie
  • *
  • Posts: 4
Re: Battery Voltage Monitoring
« Reply #42 on: March 01, 2018, 07:44:21 AM »
Thanks for the reply @TomWs. I didn't realise that the Vcc of the ATmega328p could be measured without a potential divider circuit. Since your reply, I have tried a readVcc function which works well, except the result seems to be about 9.7% off when I verify it against my multimeter reading. But a little calibration takes care of that.

TomWS

  • Hero Member
  • *****
  • Posts: 1877
Re: Battery Voltage Monitoring
« Reply #43 on: March 01, 2018, 09:19:01 AM »
I have tried a readVcc function which works well, except the result seems to be about 9.7% off when I verify it against my multimeter reading. But a little calibration takes care of that.
The 1.1V reference is not perfect but it should produce better accuracy than this.  It may be that you need a bit more settling time between setting your ADC MUX and taking the reading.  Taking two readings, back to back and using the second one also helps, but this is mostly if you're taking an external reading from a high impedance source.

Here is what I've found in my collection of goodies...
Code: [Select]
unsigned int readVcc() {
  unsigned long result;
  byte saveADMUX;
 
  saveADMUX = ADMUX;
  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
  #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284P__)
    ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
    ADMUX = _BV(MUX5) | _BV(MUX0);
  #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
    ADMUX = _BV(MUX3) | _BV(MUX2);
  #else
    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #endif

  #if defined(__AVR_ATmega2560__)
    /****
    it took me a while to figure-out the problem, but on MEGA 2560, immediately after analogRead(A8), ADCL started returning zero.
    So every attempt to read from A8-A16 on Arduino MEGA will damage the functionality of readVcc().
    I've resolved the problem by adding:
    ADCSRB = 0;
    just before
    delay(20);
    **********************************/

    ADCSRB = 0;
  #endif

  delay(20); // Wait for Vref to settle (this can probably be shortened a bit)
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA,ADSC)); // measuring

  uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH
  uint8_t high = ADCH; // unlocks both

  result = (high<<8) | low;
  result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 (because...= 3300*1023/3 since 1.1 is exactly 1/3 of 3.3V)

  ADMUX = saveADMUX;  // restore the MUX to previous setting

  return result; // Vcc in millivolts
}


« Last Edit: March 01, 2018, 09:25:30 AM by TomWS »

perky

  • Hero Member
  • *****
  • Posts: 871
  • Country: gb
Re: Battery Voltage Monitoring
« Reply #44 on: March 01, 2018, 02:12:41 PM »
I suspect it's not just the settling time, you'd need to slow the ADC clock right down so that the sample and hold window is large enough to allow the high impedance source to charge the S&H capacitor. Just allowing a longer settling time on the pin isn't enough.

Mark.