accurate Moteino battery voltage monitoring

Started by WhiteHare, September 21, 2015, 01:56:43 PM

kobuki

Yes, for 5x the price they're bound to be better in at least one or 2 aspects. I have nothing against them (on the contrary, they're one of the best of their kind, apparently) and on the long term those extra few bucks are nothing even for hobbyists like many of us, I just don't feel their use justified for every case. With simple optimisations on the Moteino HW you admittedly used (8 MHz, regulator removed, etc) they last even longer, and in that case a cell can be used down to about 0.8V, which is pretty much their EOL. In that aspect, I can't see why I would want to keep their voltage above 1.5V, when what I need is > 3.3V (default case) for a 3-pack (temperature effects aside).

TomWS

To add to my last post, here is the difference between an Alkaline and a Lithium discharge curve (both Eveready brand).  Unfortunately they don't really spec at low drain levels, but the key takeaway should be, Lithium have a much sharper knee than Alkaline and Alkalines are practically useless below freezing temperatures.

Tom

kobuki

Yeah, I'm aware of these figures. data.energizer.com has the DS for many of their battery products, too. But again: why do I care about the curve, when all I need is > 3.3V (or less, about 2.4V, speaking specifically of mentioned Moteino mods), using 3 batteries in series? Naturally, I'd only bring the Lithium batteries out in the cold winter. But indoors, and in my case, I don't see obvious benefits.

I've just browsed this yesterday, very useful (there are lots of these on that forum), albeit they're at higher loads, compared to our needs (but not so unusual in practice, in small consumer devices): http://www.candlepowerforums.com/vb/showthread.php?64660-Alkaline-Battery-Shoot-Out

WhiteHare

#18
If it helps frame the objective at all, my most challenging use case is buried soil moisture sensors.  I'll probably have a lot of them, as my preliminary data indicates they will pay for themselves in water savings and a healthier landscape.  I really don't want to be digging these things up every 1.5-2 years to change the batteries.  If they could go 10 years or even longer, then that would be great.  The limiting factor for long timeframes seems to be the self discharge rate.

I asked about the quantum's because they are a lot cheaper and, according to Duracell (http://www.duracell.com/en-us/products/all-purpose-batteries/duracell-quantum), they have a "10 year guarantee in storage,"  which suggests a low self discharge rate.  I haven't yet found the hard data on that....

Also, thanks for the heads-up about freezing temperatures, as I'm planning other things (such as perimeter motion sensors) that would be above ground, and so I guess those should be lithium for at least that reason alone.

kobuki

As I've noted, it's different for everyone, and for each case. Your sensors are going to be underground, very inconvenient to maintain - naturally you'll try to have them running without maintenance as long as possible. Battery however is only one of the components. You probably have a lot of work ahead of you, writing the firmware, the low power parts and design, etc. Our current design goals are very different, that's all.

damonb

If you want to bury your entire sensing nodes you will severely compromise the range of your radio signal.
I have a network of Vegetronix sensors with Jeenodes, but I keep the controller and battery above ground. With a 10 minute sampling interval, i get about 2 years from 3x AA alkaline cells.

WhiteHare

#21
Epilog:  I found an interesting thread which outlines how to measure the bandgap voltage on a particular atmega328p rather than use an averaged figure:  http://forum.arduino.cc/index.php?topic=38119.0

Also, I'm thinking that since the best time to measure voltage is when it's under load, maybe measuring it sometime during an RFM69HW transmit would be a "free" way to generate a high load.  Not sure if that would introduce extra noise though that would undermine the result.  Many have posted that running the ADC while sleeping the rest of the atmega328p does help somewhat.

emjay


TomWS

Quote from: emjay on April 12, 2016, 03:35:46 AM
The same technique is documented here http://jeelabs.org/2012/05/12/improved-vcc-measurement/ with useful graphics and less cruft.
Thanks for the link, emjay.  It's curious that he takes 4 measurements but only uses the last one.  Are the first three to stabilize the charge on the input?

Tom

emjay

@Tom,

Exactly - when feeding the ADC input from a higher impedance than the usual recommended, it takes a while to get the (tiny) sampling cap charged up.  Even from a lower impedance, you can see a noticeable difference between the "first" sample (say after just switching to that channel) and the "second".

TomWS

Quote from: emjay on April 12, 2016, 08:54:46 AM
@Tom,

Exactly - when feeding the ADC input from a higher impedance than the usual recommended, it takes a while to get the (tiny) sampling cap charged up.  Even from a lower impedance, you can see a noticeable difference between the "first" sample (say after just switching to that channel) and the "second".
But in this case the sources (Vref==Vdd & Mux source==bandgap) are internal and presumably not high impedance.  ISTM that this algorithm might be faster if he changed the loop test slightly to stop on max of 4 times OR current reading == last reading (should be safe since presumably any change is monotonic).

emjay

#26
@Tom,

Sure, I hope Vdd is low impedance  ;)  But just set up for Vref to appear on that pin and try drawing a sip of current....
Certainly the successive readings could be logged and perhaps trimmed back to optimize, some scope for improvement if chasing microcoulombs is the target.

TomWS

Quote from: emjay on April 12, 2016, 10:59:24 AM
... some scope for improvement if chasing microcoulombs is the target.
Good point, but I was chasing microseconds  ;)

Good discussion, thanks!

WhiteHare

#28
In addition to being sometimes erroneous, I notice the first reading of the ADC also seems to take quite a bit longer than subsequent readings.  On an atmega328p running at 8Mhz, what I get is:

0. raw relative bandgap voltage=486  Elapsed time=0uS
1. raw relative bandgap voltage=397  Elapsed time=216uS  deltaT=216uS
2. raw relative bandgap voltage=360  Elapsed time=336uS  deltaT=120uS
3. raw relative bandgap voltage=348  Elapsed time=456uS  deltaT=120uS
4. raw relative bandgap voltage=344  Elapsed time=576uS  deltaT=120uS
5. raw relative bandgap voltage=343  Elapsed time=696uS  deltaT=120uS
6. raw relative bandgap voltage=343  Elapsed time=816uS  deltaT=120uS
7. raw relative bandgap voltage=343  Elapsed time=936uS  deltaT=120uS
8. raw relative bandgap voltage=343  Elapsed time=1056uS  deltaT=120uS
9. raw relative bandgap voltage=343  Elapsed time=1176uS  deltaT=120uS


from this sketch:
// number of microseconds for ADC to setttle before taking a measurement
#define ADC_SETTLE_MICROSECONDS 1000 
#define NUM_ADC_SAMPLES 10

uint16_t getRelativeBandgapVoltage() {
  uint16_t rawBandgapMeasurement;
  
  // Read bandgap voltage reference (~1.1V) against AVcc
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);    //need to do this for every sample or just the first?
  //delayMicroseconds(ADC_SETTLE_MICROSECONDS); // Settle before taking ADC measurement
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  rawBandgapMeasurement = ADCL;  //get the low order bits of ADC
  rawBandgapMeasurement |= ADCH<<8;  //combine with high order bits of ADC 
  return rawBandgapMeasurement;
}

void setup() {
  long timeInMicroseconds[NUM_ADC_SAMPLES];
  uint16_t rbgv[NUM_ADC_SAMPLES];  // relative bandgap voltage
  
  Serial.begin(115200);
  
  for (int i=0;i<NUM_ADC_SAMPLES;i++) {
    timeInMicroseconds[i] = micros();
    rbgv[i] = getRelativeBandgapVoltage();
  }
  for (int i=0;i<NUM_ADC_SAMPLES;i++) {
    Serial.print(i);
    Serial.print(F(". raw relative bandgap voltage="));
    Serial.print( rbgv[i]);
    Serial.print(F("  Elapsed time="));
    Serial.print(timeInMicroseconds[i] - timeInMicroseconds[0]);
    Serial.print(F("uS"));
    if (i>0) {
      Serial.print(F("  deltaT="));
      Serial.print(timeInMicroseconds[i]-timeInMicroseconds[i-1]);
      Serial.print(F("uS"));
    }
    Serial.println();
    Serial.flush();
  }
}

void loop() {
}


With just minimal testing so far, I've already noticed a variation of anywhere from one to seven samples needed before arriving at the final number, so Tom's idea of only waiting for the same number to repeat two times in a row sounds nicely frugal while remaining easy to implement.  Not sure if there are conditions under which more than two in a row would be preferable.

The number of cycles can also be reduced just by adding some delay (ADC_SETTLE_MICROSECONDS, which is presently commented out in the above sketch).  So, maybe adding some sleep time (or simply attending to other matters) in place of a pure delay would be even more energy efficient.  Some of the common sketches for readVcc do sleep during the samples (to minimize noise and/or save energy), but I don't know of any that purposely sleep extra long so as to reduce the number of samples needed.

As illustrated by the above example in this post, the amount of elapsed time before converging on a particular number can definitely add-up to become non-trivial.  With that in mind, I'm curious to know whether freezing temperatures and/or high ambient heat and/or low VCC and/or a weak battery might affect the convergence time, and so I'll eventually run some tests to try to characterize that.  For instance, a weak battery might easily affect the settle time and/or samples required because AVcc might be falling from one sample to the next due to load.  For that reason, perhaps the number of samples and/or settle time should be reported and monitored as yet another possible indicator that a battery may need to be changed.  In the worse case, a weak battery might become even weaker just from chasing after an accurate measure of how weak it is!  With BOD turned off, it might even run itself into the ground.  So, for really weak batteries that are just barely holding on, maybe it might even make sense to halt reading the Vcc until it can be replaced...

Can anyone think of any other concerns that might play a role?  If so, I can maybe run some tests for those as well and post the results afterward.

TomWS

@Whitehare, if you're running this test as soon as your system turns on, the culprit might be the cap on ARef settling into its final charge.  What happens if you don't run the test (leaving the ADC ref at its power on default) for a few milliseconds?

Measuring voltages at first application of power are likely to be wrong and in most cases unnecessary.  Measuring voltage after reset is valid if the proc is in a stopped state and reset via RTC, for example, should be ok.

Tom