Power saving in code for extended battery life.

gr0p3r:
, but how would that work with a phototrasistor?? it outputs an analogue value, as far as im aware, how can you use that as a digital trigger? example code?

An analog value is just a voltage. digitalRead is also reading a voltage, it just "translates" that voltage to either a 0 or a 1. If the voltage at the digital pin gets low enough, digitalRead will start reading it as 0, so you would need to setup a voltage division circuit with the proper resistor values so that it falls below that voltage when you want it to turn on. I think there is a "floating" voltage level (2-3v?) where the digitalRead wouldn't be accurate, so you may have to use an additional device to account for that if the light change is fairly gradual.

i see, do you have a link to an example of the watchdog wakeup trigger? ill have to have a play around and see if i can get that to work. i have a feeling that the light cange is going to be too gradual and it will hit that "floating point" you described and confuse it. what is the device that will switch 0-4v to 0 and 4-5v to 5?

http://interface.khm.de/index.php/lab/experiments/sleep_watchdog_battery/

My first thought would be a zener diode for blocking lower voltages.

Oh awesome, i just googled zenner diode, and going from the pictures, i think i may have some of them already, i didnt know what they were :smiley:

if i can use the nightingale code and get the battery life to 3 years, that would be unbelievable!

anyone know if the 7805 voltage regulator is low-leak like Drmn4ea was suggesting?
also the Nightingale sketch doesnt have a voltage regulator. do i even need one??
will there be an harm in running straight off the battery? i was planning on using a 9v down to 5v through 7805, but if i can run off 4x1.2v AA...
i have found that the PIR i have will give continuous false positives if it is given less than 4v

Some suggestions:

  1. The power consumption of the chip is approximately A * f + B where f is the clock frequency and A and B are constants. At high clock frequencies, the A * f term dominates. So use a much lower clock frequency to save power. 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.

  2. To detect the light level, you can use the analog comparator function of the atmega328p. See the datasheet. This will be more reliable than using a digital input, and gives you two options:

a) Wake up every 8 seconds on the watchdog and read the comparator. This is much quicker than doing an analogRead. So if it is light you can have the processor go back to sleep immediately, having consumed hardly any power.

b) Use the analog comparator interrupt to wake the process up from deep sleep when it gets dark.

  1. How much current does the PIR detector draw? You could power it down during daylight.

  2. The standard 7805 has a quiescent current of about 5mA, so far too high for your application. You need something like LM2396-5.0 instead (9uA typical quiescent current when the load current is <100uA).

The capacity of a 9v battery is around 565mAH for alkaline and 1.2Ah for lithium. So you'll need to get the average current consumption (including PIR) down to 45uA for a lithium 9v battery to last 3 years.

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".

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?

  1. How much current does the PIR detector draw? You could power it down during daylight.

ive just done some testing with my multimeter as the datasheet is good for nothing.
it draws .055mA - .075mA while testing
it draws 1.11mA when its sending the HIGH signal.
its power is currently connected to an arduino pin and is only "powered up" by a HIGH to that pin (only when the light is dark)

So you'll need to get the average current consumption (including PIR) down to 45uA for a lithium 9v battery to last 3 years.

i never expected to be able to get 3 years life. i just saying that because thats what nightingale got. I would be happy with 6-12 months .

ARRCH:
ive found some diode, but am having trouble with them. 4 types, the markings are hard to read but from what i can make out these are what i have:
1N4534A
1N4138AF
1N94 could be 1N9_4_?
4148T could be T4148 or 8T141 etc (its in a loop)
Yellow Brown White ( this one is marked with bands, brown could also be dark purple or black, hard to tell)

I have tied googling all these but to not much avail. do any of these sound like what you are talking about?

The standard 7805 has a quiescent current of about 5mA, so far too high for your application. You need something like LM2396-5.0 instead

i cant find one of them how about a TDA3664? or know where i can get a LM2396-5.0 in australia without paying $60 postage from america :astonished:
http://www.ebay.com.au/itm/NEW-IC-TDA3664-N1-TDA3664-NXP-VOLTAGE-REGULATOR-/250814457643?pt=LH_DefaultDomain_0&hash=item3a65b4e72b
i can actually get these.

gr0p3r:
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".

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

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

• 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. :stuck_out_tongue:

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?

gr0p3r:
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.

gr0p3r:
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

• 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. :stuck_out_tongue:

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.

gr0p3r:
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.

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.)

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.

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:

#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

}
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.

Looks like people have beat me to all of the good answers :wink:

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.

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 :slight_smile:

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!

Looks like people have beat me to all of the good answers :wink:

i dunno, think you doing pretty well...

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 :astonished:
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?

gr0p3r:
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.

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 )"

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.

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.

Hi Guys,

Ive almost got it all working! :smiley:
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! :frowning:

please, what am i doing wrong now?

here is the relevent bits of code:

#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
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
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

}
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;
}

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

From the datasheet...

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.