Go Down

Topic: Power saving in code for extended battery life. (Read 5433 times) previous topic - next topic

dc42

#15
May 03, 2012, 02:11 pm Last Edit: May 03, 2012, 02:18 pm by dc42 Reason: 1

hi dc42,
thanks for your very informative reply. i think it going to take me a while to digest all of that, there are a few things i dont understand and will have to google. like the "analog comparator function".
Quote
Preferably, use the internal 128KHz RC oscillator, which requires programming the fuses. If you don't want to program the fuses, you can still get a substantial power reduction by writing to the clock prescaler register, which allows the clock frequency to be divided by up to 256.

can either of these be done with the standard arduino board?


See the datasheet http://www.atmel.com/Images/doc8271.pdf for details of the analog comparator function and the clock prescaler. You can use both of these on a standard Arduino, but not switch to the internal 128KHz oscillator.

The following (untested) tested code should switch the clock prescaler to 256:

 CLKPR = 0x80;   // set the CLKPCE bit
 CLKPR = 0x08;   // set the prescaler to 256
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

gr0p3r

Thanks for testing that,
So i have put
  CLKPR = 0x80;   // set the CLKPCE bit
  CLKPR = 0x08;   // set the prescaler to 256
into my setup function, is that correct?
am i also correct in changing all my references to milliseconds to /256 eg Delay(50/256);  ?

in reading about the analogue comparator; i am reading the pdf u linked for me. i can see where its says what the analogue camparator does and that it has a few different ways of running. I think one of these 2 modes is what i need
Quote
• Bit 4 - ACI: Analog Comparator Interrupt Flag
This bit is set by hardware when a comparator output event triggers the interrupt mode defined
by ACIS1 and ACIS0. The Analog Comparator interrupt routine is executed if the ACIE bit is set
and the I-bit in SREG is set. ACI is cleared by hardware when executing the corresponding interrupt
handling vector. Alternatively, ACI is cleared by writing a logic one to the flag.
• Bit 3 - ACIE: Analog Comparator Interrupt Enable
When the ACIE bit is written logic one and the I-bit in the Status Register is set, the Analog Comparator
interrupt is activated. When written logic zero, the interrupt is disabled.

but i cant see where it says how to use it. im sorry, i must seam like an utter nonse to you. probaly because i am. :P

as far as wiring it up goes i think i need:
  a voltage divider on one pin to input around 4volts to the pin
  the photo transistor and a resistor on another pin for the ACI to compare the first pin
what pins on the arduino can be used for the analogue comparator?

dc42


So i have put
  CLKPR = 0x80;   // set the CLKPCE bit
  CLKPR = 0x08;   // set the prescaler to 256
into my setup function, is that correct?
am i also correct in changing all my references to milliseconds to /256 eg Delay(50/256);  ?


Yes and yes.


in reading about the analogue comparator; i am reading the pdf u linked for me. i can see where its says what the analogue camparator does and that it has a few different ways of running. I think one of these 2 modes is what i need
Quote
• Bit 4 - ACI: Analog Comparator Interrupt Flag
This bit is set by hardware when a comparator output event triggers the interrupt mode defined
by ACIS1 and ACIS0. The Analog Comparator interrupt routine is executed if the ACIE bit is set
and the I-bit in SREG is set. ACI is cleared by hardware when executing the corresponding interrupt
handling vector. Alternatively, ACI is cleared by writing a logic one to the flag.
• Bit 3 - ACIE: Analog Comparator Interrupt Enable
When the ACIE bit is written logic one and the I-bit in the Status Register is set, the Analog Comparator
interrupt is activated. When written logic zero, the interrupt is disabled.

but i cant see where it says how to use it. im sorry, i must seam like an utter nonse to you. probaly because i am. :P

as far as wiring it up goes i think i need:
  a voltage divider on one pin to input around 4volts to the pin
  the photo transistor and a resistor on another pin for the ACI to compare the first pin


That's one way, although it assumes that the analog comparator is OK with a common mode input voltage of 4V on a 5V supply. I would use the internal bandgap reference to provide the other input. It's about 1.1v, so in this case it would be best to wire the input pin with the phototransistor between the pin and +5v, and resistor between the pin and ground.

From the datasheet, it looks like the analog comparator takes 70uA @ 5V and the bandgap reference takes about 10uA. So if you are using the watchdog timer to wake the unit up regularly, I suggest you power these units down when you put the device to sleep.


what pins on the arduino can be used for the analogue comparator?


From the diagram on page 248, the +ve input of the comparator can be selected to be either the bandgap reference or pin Ain0. The -ve input can be either Ain1, or (when you are not using the ADC) any of the analog input pins. The pin mapping diagram at http://arduino.cc/hu/Hacking/PinMapping shows that Ain0 is digital pin 6 and Ain1 is digital pin 7.
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

SirNickity

http://arduino.cc/it/Hacking/PinMapping168

Looks like pins 12 and 13 (D6 and D7).

A regulator is only necessary if you're trying to keep a constant voltage from a source either too high to run directly, or too variable to run reliably.  Batteries are fine.  You may want to devise a low-battery alarm or power-off though.  (Look into the on-chip brown-out detector.)

gr0p3r

i dont think burning a new boot loader or changing fuses is for me at this stage, so the BOD might be a bit hard.

I was under the impression that running from a 9v and regulating it to 5v would produce a longer life as there is 5v it can drop whereas if i used a 6v hooked up without regulation there is only 2v to drop before its considered flat.

will a low voltage cut off draw more power? im not sure that it is entirely necessary, i have discovered already that with flat batteries the PIR trips constantly, so i will have a pretty good idea when the batteries run down.

any thoughts on the TDA3664? ive fond them on ebay and am waiting to hear before i buy some.

Quote
http://arduino.cc/it/Hacking/PinMapping168

Looks like pins 12 and 13 (D6 and D7).

That's great, defiantly helps make more sense of the datasheet.
any idea what the code would look like for a analogue comparator interrupt?
im looking at the nightingale sketch for a bit of inspiration but as it sleeps and wakes on a timer not an interrupt i dont think its much use.

i have devised this from http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1272923299 and the nightingale sketch:
Code: [Select]

#include <avr/sleep.h>
ACSR =
(0<<ACD) |   // Analog Comparator: Enabled
(0<<ACBG) |   // Analog Comparator Bandgap Select: AIN0 is applied to the positive input
(0<<ACO) |   // Analog Comparator Output: Off
(1<<ACI) |   // Analog Comparator Interrupt Flag: Clear Pending Interrupt
(1<<ACIE) |   // Analog Comparator Interrupt: Enabled
(0<<ACIC) |   // Analog Comparator Input Capture: Disabled
(1<<ACIS1) | (1<ACIS0);   // Analog Comparator Interrupt Mode: Comparator Interrupt on Rising Output Edge

void system_sleep() {

  cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF

  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
  sleep_enable();

  sleep_mode();                        // System sleeps here

    sleep_disable();                     // System continues execution here when watchdog timed out
    sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON

}
Code: [Select]

ISR(ANALOG_COMP_vect )
{
lightReading = analogRead(lightPin);
if(lightReading > 1000) {
  Wakeup                           <<--- whats the code for this??
}

this will obviously have to be inserted into my original sketch. i am yet to test it as i dont know what the code will be to compare the analog signals or to wake up.

Drmn4ea

Looks like people have beat me to all of the good answers ;-)

Quote

I was under the impression that running from a 9v and regulating it to 5v would produce a longer life as there is 5v it can drop whereas if i used a 6v hooked up without regulation there is only 2v to drop before its considered flat.


There is some truth to that (the discharge curve of alkalines is anything but flat), but also consider what a "9V" battery actually is: if you saw one open, it is 6 "AAA" cells (actually something much smaller) wired in series! So the internal resistance is higher, and a lot of the space in the battery is wasted (round cells in a square case), so the capacity (mAh rating) per $ and per volume is not great. You may get much better runtime from 4 "AA" (or larger if you have room) cells in series, even if the voltage "headroom" is less.

Quote

will a low voltage cut off draw more power? im not sure that it is entirely necessary, i have discovered already that with flat batteries the PIR trips constantly, so i will have a pretty good idea when the batteries run down.


In general a low-battery cutoff will draw "some" extra ("some" may not be enough to worry about; there are very efficient circuits/ICs for this nowadays), but it sounds like you wouldn't need it anyway :-)

Quote

any thoughts on the TDA3664? ive fond them on ebay and am waiting to hear before i buy some.


Here is the datasheet for TDA3664 - looks good! Some lesser leakage ones exist (I am partial to Microchip's MCP170x family, but not sure if you have easy access to those) but 15uA is pretty respectable. And sometimes "available" is the most important spec of all!

gr0p3r

Quote
Looks like people have beat me to all of the good answers ;-)

i dunno, think you doing pretty well...
Quote
There is some truth to that (the discharge curve of alkalines is anything but flat), but also consider what a "9V" battery actually is: if you saw one open, it is 6 "AAA" cells (actually something much smaller) wired in series! So the internal resistance is higher, and a lot of the space in the battery is wasted (round cells in a square case), so the capacity (mAh rating) per $ and per volume is not great. You may get much better run time from 4 "AA" (or larger if you have room) cells in series, even if the voltage "headroom" is less.

i have pulled apart a 9v when i was a kid, so i can picture what your saying. I see what you mean.
the MCP1702 are sourceable, but not economically with the postage. .50c item with $12 postage   :smiley-eek:
What sort of battery life would you expect if i did away with the regulator and its 2 capacitors, hooked up it directly to 4x 2500mAH rechargable NiMH which are 1.2V fully charged? Assuming i can get the sleep code working too. know how to wake it after its sleeps, and is the sleep method from the nightingale sketch the way to go?

dc42

#22
May 04, 2012, 10:17 am Last Edit: May 04, 2012, 10:20 am by dc42 Reason: 1

What sort of battery life would you expect if i did away with the regulator and its 2 capacitors, hooked up it directly to 4x 2500mAH rechargable NiMH which are 1.2V fully charged? Assuming i can get the sleep code working too. know how to wake it after its sleeps, and is the sleep method from the nightingale sketch the way to go?


If you use regular NiMH cells, they will lose their charge through self-discharge in a small number of months. If you use low self-discharge (also called hybrid) cells, they should last longer than a 9v battery, probably several years if you get the current consumption low enough. The starting voltage of a fully charged NiMH cell can be as high as 1.4v so you may briefly be running the processor at 5.6v.

Another possibility is 3 x lithium AA cells. These have a long shelf life and flat discharge curve, see http://data.energizer.com/PDFs/l91.pdf.
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

gr0p3r

Quote
The starting voltage of a fully charged NiMH cell can be as high as 1.4v so you may briefly be running the processor at 5.6v.

The batteries ive got ive had for a while and tested them alot, after a full charge they sit at 1.2V. so i dont think ill be running the risk of running at over 5v. What is the likelihood of causing damage by doing this out of interest?
Because i already have loads (like 30) NiMH hanging around, ild be inclined to use them. If i can get a couple of months out of them a few times in a row, then ild probably go get some of them lithums. that datasheet was a good one, i like the look of the graph for Lithium vs Alkaline for low current continuous usage. very steady.

the last bit of info ill need before i go and make all these changes is to know for sure that the "void system_sleep()" function is from the nightingale is right for me and how to wake it up from the "ISR(ANALOG_COMP_vect )"

SirNickity

Another thing about regulators:  Even the most efficient regulators are not 100% efficient.  Linear regulators are far, far from efficient.  So, if you're dropping 4v from a 9v to reach 5v, that's 4v that's just heating the air around your regulator.  This pretty much scraps any advantage from trying to conserve power through sleep modes.  Running it direct from batteries removes this waste.

The ATmegas are rated to 5.5v, so while four alkalines might be pushing it (don't fresh ones start around 1.45 or so?  I don't know), NiMH would likely be just fine.  Remember, 5.5v is the serving suggestion.  The actual capabilities of the chip could be well beyond that.  (You take a risk if you overvolt it, but if it's worth the $4 to you to try it and see what happens, by all means.. give it a shot.)

Fuses aren't bad.  Don't be intimidated, just devote an afternoon to reading up on them.  There are online calculators that let you pick your options and it'll spit out the values.  Then, you follow a tutorial on using avrdude from the command line -- which also isn't a big deal.  You can just about copy the command line used by the IDE.

The BoD would be worth it, in my opinion.  I would rather have a clear indication when the batteries need to be swapped than slowly having performance turn to crap.  Ultimately, it's your call, just don't let having to set fuses scare you off.  It's not hard.

Coding Badly

Quote
so while four alkalines might be pushing it (don't fresh ones start around 1.45 or so?  I don't know)


The ones I use start life at 1.6 volts, quickly run down to 1.5 volts, very slowly run down to 0.8 volts (almost linearly), at which point they are effectively dead.

gr0p3r

Hi Guys,

Ive almost got it all working! :D
i have the analog interrupt working and it going to sleep and the clock being wound back. all great.

BUT....

i cannot get the analog interrupt to trigger while its is in sleep mode! :(

please, what am i doing wrong now?

here is the relevent bits of code:
Code: [Select]
#include <avr/sleep.h>

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

Code: [Select]
void setup(){
ACSR =
(0<<ACD) |   // Analog Comparator: Enabled
(1<<ACBG) |   // Analog Comparator Bandgap Select: AIN0 is applied to the positive input
(0<<ACO) |   // Analog Comparator Output: Off
(1<<ACI) |   // Analog Comparator Interrupt Flag: Clear Pending Interrupt
(1<<ACIE) |   // Analog Comparator Interrupt: Enabled
(0<<ACIC) |   // Analog Comparator Input Capture: Disabled
(1<<ACIS1) | (0<ACIS0);   // Analog Comparator Interrupt Mode: Comparator Interrupt on Rising Output Edge

Code: [Select]
void system_sleep() {

  cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF

  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
  sleep_enable();

  sleep_mode();                        // System sleeps here

    sleep_disable();                     // System continues execution here when watchdog timed out
    sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON

}

Code: [Select]
ISR(ANALOG_COMP_vect )
{
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);
    sleep_disable();                     // System continues execution here when watchdog timed out
    sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON
    wake = 1;
}

Coding Badly

Quote
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here


From the datasheet...

Quote
When entering Idle mode, the Analog Comparator should be disabled if not used. When entering ADC Noise Reduction mode, the Analog Comparator should be disabled. In other sleep modes, the Analog Comparator is automatically disabled.


gr0p3r

Hey Guys,
Thanks for all your help. ive finally got it finished. Ended up using a couple of watchdogs as i could not get the Analog Comparator to work in sleep mode.
Quote
In other sleep modes, the Analog Comparator is automatically disabled.
"Automatically", i couldn't find the manual on. and sleeping to IDLE mode wasnt going to give the power savings needed, so watchdog timers set to differing lengths for different light levels and slowing the clock down.
Could not have a slow clock while fading on the lights as analogWrite doesn't work properly and the lights flash on and off instead of fade till the are on. i worked around that with 2 little subroutines.

here are my initial power consumption results:
Quote

  • it draws 22mA (both with the PIR off or on)

  • it draws 47mA when LED's are at full brightness (for 9 seconds)

   

here they are now:
    In dark: 0.03mA - 4mA (16 Second sleep)
    In Light: 0.3mA - 5mA (1/2 Second Sleep)
    LED on: 40.7mA (on for 4 Seconds)
Last night tested battery at 5.18v at 8:30PM and tested again at 8:30am (12 Hours) 5.1v

Thanks so much for everyones help. been a great learning.

aleph8nought

Hey Great project! I have a write up about a similar project posted on my blog that friend just finished. He had the same problems but ended up tackling them in different ways. You might want to take a look since the project is so similar.

http://n0m1.com/2012/05/13/mday-low-power-motion-sensor-arduino-night-light/

We wrote an arduino sleep library that was used in the project. It has both wake from interrupt as well as watchdog sleep. Its here:
https://github.com/n0m1/Sleep_n0m1

I hope this helps someone out!

Go Up