Preserve battery with Sleep ?

I'm wondering about your hardware setup when it consumes so much power.

I measured about 270 uA with your original code, which is a lot less than the 4 mA you are getting.

I've just looked at the circuit for the Arduino Pro Mini. As far as I can see, it has a permanent LED connected between Vcc and Gnd via a 10K resistor. That would use close to a 1 mA wouldn't it? I would be trying to disconnect that.

Anyway, I amended your sleepNow to add a couple of things, and got the current consumption down to 75 uA.

In particular:

  • Turned off I2C (you would need to turn it on again afterwards of course)
  • Corrected my bug where PRR should be 0b11101111 not 0x11101111
  • Turned off the ADC converter
  • Enabled the pull-up on the wake-up pin
void sleepNow()         
{   

  pinMode(buzzerPin, INPUT);
  for(int i=0; i<6; i++) 
  {  
    pinMode(ledPins[i], INPUT); 
  } 

  // turn off I2C
  TWCR &= ~(_BV(TWEN) | _BV(TWIE) | _BV(TWEA));

  // turn off I2C pull-ups
  digitalWrite (A4, LOW);
  digitalWrite (A5, LOW);

  // disable ADC
  ADCSRA = 0;  

  // turn off various modules
  PRR = 0b11101111;

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  
  sleep_enable();         
  digitalWrite (3, HIGH);
  pinMode (3, INPUT);    
  attachInterrupt(1,wakeUpNow, LOW); 
  sleep_mode();            
  sleep_disable();         
  reset_application();      
}

I did have a few changes to the original hardware.
I no longer used the lilypad RGB but use RGB Diffused (http://www.sparkfun.com/products/9264).
I connect R to 180 ohm resistor and G to 100 ohm before linking to respective pins.

Question: Why do I need to have it in the sleepnow() since it is already declare in the setup?

digitalWrite (3, HIGH);
pinMode (3, INPUT);

Even with the additional turning off code it still only goes down to 4mA for arduino fio.

While the IR sensor uses the exact same setting as

Before addressing those questions, following up from an idea here:

http://jeelabs.org/2009/05/16/power-consumption-more-savings/

I discovered that by programming the fuse to disable brown-out detection it reduced the consumption on my test from about 75 uA to 6 uA, a huge saving.

Question: Why do I need to have it in the sleepnow() since it is already declare in the setup?

You don't, I had it there because I was experimenting with turning all pins to inputs, and low, then I put that one back.


The diagram you posted doesn't seem to match the Arduino Fio or the Arduino Pro Mini.

If you are using a board with an on-board LED, a USB conversion chip, or a voltage regulator, these are all likely to consume power. I am testing with a "bare bones" board which is basically the processor chip, a couple of decoupling capacitors, and a resonator. This, basically:

I would suggest if you start from the Pro Mini/Fio alone without any external peripheral.
It will be very hard to pin point where the current consumption is going into when you have several possible contributors.
Then, once the main board is low in current, start adding the external peripheral one by one.
Eventually you'll get there. :slight_smile:

You can disable the BOD on the fly but with strict timing and sequence.
You might want to check a simple library I wrote some time ago:
http://www.rocketscream.com/blog/2011/07/04/lightweight-low-power-arduino-library/

There's something wrong with that URL, I can't load it by clicking.

Anyway, working around that, the BOD disable doesn't seem as effective as setting the fuse. I still measure 61 uA using the test sketch compared to 6 uA with setting the fuse.

Fixed the link!

The software BOD disable works in my case. I always get a reduce of ~17 uA when disabling them through software. I also started using the hard coded way of disabling the fuse but I thought the BOD is an important feature to keep. So, I went with the software method and only disabling them when needed.

I am actually using pro mini and arduino fio but the diagram I posted is from the example I find on IR sensor.
Sorry for the confusion. :sweat_smile:
I have already solder everything together so removing everything and adding them back one by one doesn't seem like a preferable choice. :cold_sweat:

48X24X48X:
You can disable the BOD on the fly but with strict timing and sequence.
You might want to check a simple library I wrote some time ago:
http://www.rocketscream.com/blog/2011/07/04/lightweight-low-power-arduino-library/

I check out for library by loading the current hardware setting with your "Wake External Interrupt" example and it is still 4mA.
So it is definitely something to do with the hardware setting !!!!

Yeast:
I have already solder everything together so removing everything and adding them back one by one doesn't seem like a preferable choice. :cold_sweat:

You can make, as a test, a "bare bones" board, even on a breadboard. Also there are cheap circuit boards, for example this one for $US 3:

Then solder on a chip header (eg. the ZIF socket they have on the page), a couple of decoupling caps, a resonator, and then the wires leading to your circuit.

Then you are in a position to test the sketch/hardware combination. You can power it, for testing, from an external 5V supply. For example, I powered my test board by simply connecting to the 5V/Gnd pins on an Arduino Uno, which supplies me with regulated 5V.

I know this is an old thread but I can tell you where your extra 4 mA is coming from because I've spent the last few hours trying to figure out the exact same problem. NewSoftSerial adds 4mA of extra current to all of your sleep mode settings. I was following some of Nick's code to use as a baseline. Try the simple sketch below with and without creating an instance of NSS and you'll see a 4mA difference. The numbers on the left are without NSS and on the right with NSS. Now my question is can you delete an instance of NewSoftSerial after you've created one?

#include <avr/sleep.h>
#include <NewSoftSerial.h>

//NewSoftSerial ThisIsKillingME(8,9);


void setup () 
{
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  //480uA  4.35mA
//  set_sleep_mode (SLEEP_MODE_STANDBY);  //636uA  4.5mA
//  set_sleep_mode (SLEEP_MODE_EXT_STANDBY);  //775uA  4.65mA
//  set_sleep_mode (SLEEP_MODE_PWR_SAVE);  //775uA  4.648mA
//  set_sleep_mode (SLEEP_MODE_ADC);  //967uA  4.84mA
//  set_sleep_mode (SLEEP_MODE_IDLE);  //1.16mA  5.03mA
  sleep_enable();
  // disable ADC
  ADCSRA = 0;  
  // turn off various modules
  PRR = 0xFF; 
  // turn off brown-out enable in software
  MCUCR = _BV (BODS) | _BV (BODSE);  // turn on brown-out enable select
  MCUCR = _BV (BODS);        // this must be done within 4 clock cycles of above
  sleep_cpu ();              // sleep within 3 clock cycles of above
}  // end of setup

void loop () { }

You could do new and delete rather than statically allocating it. But that may or may not return the power consumed. There would be an underlying reason (it has configured an interrupt to fire for example). So unless it has a destructor, and the destructor is designed to undo whatever the constructor does, you may not achieve much.

I'm sure it can be done, but you will need to figure out exactly what, in NewSoftSerial, is consuming the power.

A quick browse indicates the constructor doesn't do much apart from configuring the input and output pins (although that might have a small effect, eg. the pull-ups).

But it does link in the pin change interrupts, possibly activating the pin change interrupts causes a higher power consumption. I'm guessing a bit here. Probably best to make a copy of NewSoftSerial, use that, and then comment out stuff until the current consumption drops.

Thanks Nick. I had a different response but just found the problem so I deleted it.

It looks like NSS is using (or not) Timer0 and that is what is consuming all the power. If you look through the code there's actually a public function to enable Timer0 so if you send this:

ThisIsKillingME.enable_timer0(1);

it seems to knock out the 4mA :slight_smile: . I'll have to test further to see if setting back to 0 after wake up causes any problems.

I thought sleep mode "power down" stopped timer 0? There are some figures on page 404 of the datasheet that show the consumption of various modules. At 5V Timer 0 apparently consumes around 61 uA. However a side-effect of it running is it cancels sleep mode (because of the interrupt).

I would be starting to wonder if your code stays asleep. Try flashing an LED or something in loop() to see if you exit sleep mode when you don't think you do.

I did confirm it was staying asleep, I set it up to toggle a pin in a loop and it didn't toggle. I also need to rescind the observation I made about calling that function. I was making multiple changes in the sketches before finishing up at work and the last change I made before calling that function was create an instance using pins 0 and 1 instead of 8 and 9 just to see what would happen. I think that in combination with the function dropped the power. I'm going to try it again after dinner but if that's the case it may be related to the pin change interrupts. Which kind of sucks because I wanted to use one to be able to wake up from a low battery alert.

I don't see where you are enabling the internal pullups on unused pins.

If pin change interrupts were enabled, which I didn't think the constructor did, then they would probably fire like crazy if there were floating voltages on the pins.

Actually I can't reproduce your problem.

Running this exact code:

#include <avr/sleep.h>
#include <NewSoftSerial.h>

NewSoftSerial ThisIsKillingME(8,9);


void setup () 
{
  pinMode (9, OUTPUT);
  digitalWrite (9, HIGH);
  delay (1000);
  digitalWrite (9, LOW);
  
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  //480uA  4.35mA
//  set_sleep_mode (SLEEP_MODE_STANDBY);  //636uA  4.5mA
//  set_sleep_mode (SLEEP_MODE_EXT_STANDBY);  //775uA  4.65mA
//  set_sleep_mode (SLEEP_MODE_PWR_SAVE);  //775uA  4.648mA
//  set_sleep_mode (SLEEP_MODE_ADC);  //967uA  4.84mA
//  set_sleep_mode (SLEEP_MODE_IDLE);  //1.16mA  5.03mA
  sleep_enable();
  // disable ADC
  ADCSRA = 0;  
  // turn off various modules
  PRR = 0xFF; 
  // turn off brown-out enable in software
  MCUCR = _BV (BODS) | _BV (BODSE);  // turn on brown-out enable select
  MCUCR = _BV (BODS);        // this must be done within 4 clock cycles of above
  sleep_cpu ();              // sleep within 3 clock cycles of above
}  // end of setup

void loop () { }

I got a reading of 0.42 uA (420 nA). And that was with the NewSoftSerial object there.

I added the stuff to flash an LED because I could hardly believe my eyes. But yes, the LED comes on for one second, and then the current drops to that reading.

Oh, wait. Pin 9 is what you are using for NSS. Well anyway there is the proof.

But this is interesting. I commented out the 4 lines that flashed the LED. And now look what happens:

Not only is it now using 4.345 mA (a big jump!) but the LED lights up! Well that's where your power is going.

I should have posted this last night but I was too tired. The problem is the Tx pin on NewSoftSerial because the idle state is HIGH which means the pin is still sourcing current when you put it too sleep. Simply changing the pinMode to input and disabling the internal pull up resistors seems to fix the issue. This would probably be a handy function to add to the sleep file, one function to scan all the digital ports, record their states and change them all to high impedance and then another wakeup function to restore the previous states. Any way... thanks for the help.