Arduino Forum

Using Arduino => Microcontrollers => Topic started by: tlharv on May 02, 2013, 05:56 pm

Title: When sleeping helps
Post by: tlharv on May 02, 2013, 05:56 pm
Is there a threshold where having the microprocessor sleep has a noticible benefit on power consumption?  For example, if you have a delay(1000) statement in your loop() function, would it make sense to put the chip to sleep (or use watchdog timer) during that time?

Assuming there's a benefit to sleeping (one second is an eternity for a microprocessor), I'll need help writing that code into my sketch for the ATtiny85.

Thanks,
Tom
Title: Re: When sleeping helps
Post by: JChristensen on May 02, 2013, 07:01 pm
Depends on the sleep-vs.-wake ratio. It doesn't take many instructions to sleep an AVR MCU, so that represents little overhead. If the application truly has many seconds of CPU-bound processing to do, then sleeping for a second wouldn't make much difference. But that's an extreme example.

I heard a rumor that the Arduino-Tiny core (http://code.google.com/p/arduino-tiny/) might have a version of delay that sleeps the MCU in a future version. @Coding Badly may know something about that, maybe he can comment.

Another option, check out the sleep code in my Million Ohms project (http://github.com/JChristensen/millionOhms_SW).

I've been playing with low-power data loggers that sleep between samples. I added a DS18B20 temperature sensor to one, but it takes the DS18B20 750ms to do a temperature conversion. So as you suggested, I used the WDT. I send the command to the sensor to start the conversion, set the WDT for one second and sleep the MCU, then read the sensor when the WDT wakes it.
Title: Re: When sleeping helps
Post by: Coding Badly on May 03, 2013, 05:10 am
Is there a threshold where having the microprocessor sleep has a noticible benefit on power consumption?


The threshold is "always".  If there is no work to do, Idle sleep mode reduces the power consumption enough to make it worth the effort.  Essentially, the processor takes a short nap at the end of loop.

Quote
For example, if you have a delay(1000) statement in your loop() function, would it make sense to put the chip to sleep (or use watchdog timer) during that time?


Yes.

Quote
Assuming there's a benefit to sleeping (one second is an eternity for a microprocessor), I'll need help writing that code into my sketch for the ATtiny85.


Going to need more details.  And, typically, you will get more and better help if you make an attempt on your own.
Title: Re: When sleeping helps
Post by: Coding Badly on May 03, 2013, 05:22 am
I heard a rumor that the Arduino-Tiny core (http://code.google.com/p/arduino-tiny/) might have a version of delay that sleeps the MCU in a future version. @Coding Badly may know something about that, maybe he can comment.


I did what?   :D  I've stopped using delay to the point that it will be the very last thing added to version 2.

What I have done is made it possible to put the processor into any sleep mode (i.e. Power Down) without having to fiddle with millis.  I have a timer gadget that's used several times a day, is never turned off, is accurate to ±1% (stable temperature), and has been running from the same batteries for over a year.  It's essentially a blink-without-delay plus a Power Down sleep.  Oh, and it runs on an ATtiny13.  There two downsides: 1. The tuning tool is crude.  Currently it's a hodge-podge of Python, my eyeballs, and my brain.  2. Too much low-level stuff has to be included in the sketch.  (The Night Light should move version 2 along nicely.  My boards arrive Monday!)

Quote
Another option, check out the sleep code in my Million Ohms project (http://github.com/JChristensen/millionOhms_SW).


@tlharv, Jack's work is definately worth investigating!
Title: Re: When sleeping helps
Post by: JChristensen on May 03, 2013, 11:09 pm
@CB, thanks for the kind words, I will pay you later. You'd be surprised at the people investigating me :smiley-eek:
Title: Re: When sleeping helps
Post by: westfw on May 04, 2013, 01:39 am
Do we have data on how much power is consumed by an actual Arduino board in Sleep vs running, for various power sources?
I think I've dismissed this as "it doesn't get low enough for long-lived battery operation", but it occurs to me that that is not at all the same as "not significantly lower."
Title: Re: When sleeping helps
Post by: JChristensen on May 04, 2013, 02:10 am

Do we have data on how much power is consumed by an actual Arduino board in Sleep vs running, for various power sources?
I think I've dismissed this as "it doesn't get low enough for long-lived battery operation", but it occurs to me that that is not at all the same as "not significantly lower."


My assumption has been the same. I remember measuring an Uno at 42mA and about 11mA less with the MCU in power-down mode, but I couldn't swear as to the power source.

Seems like the best-case scenario would be to power it via the 5V pin, would you agree? That would minimize losses from the voltage regulator. I could test that scenario without too much trouble. The power LED would still be on, but that could always be removed with a soldering iron.
Title: Re: When sleeping helps
Post by: Coding Badly on May 04, 2013, 04:38 am
Do we have data on how much power is consumed by an actual Arduino board in Sleep vs running, for various power sources?


I can't recall anyone publishing numbers.  Everything I can find and everything I can remember starts with a single number for an Arduino running from external power and goes straight to direct 5V power to skip the hungry regulator.  (And then various combinations of sleep mode and peripheral control are tried.)

Quote
I think I've dismissed this as "it doesn't get low enough for long-lived battery operation"...


I'm in that camp as well.  I just assume the voltage regulator burns so much power as to make sleeping essentially irrelevant.

Quote
...but it occurs to me that that is not at all the same as "not significantly lower."


That is an excellent point.  Half of a bigger number is still half.
Title: Re: When sleeping helps
Post by: tlharv on May 04, 2013, 06:58 am
First things first: where does one download the avr/sleep.h and avr/power.h libraries?  I see them in others' code but it's not in the general Arduino set of libraries.  If I can get those, then I can start tinkering and post code with more specific questions.

*update*
I went ahead and included it in my sketch, and it worked.  So it's already part of my Arduino load.  (whew).

Commencing tinkering...
Title: Re: When sleeping helps
Post by: dc42 on May 04, 2013, 08:59 am

Do we have data on how much power is consumed by an actual Arduino board in Sleep vs running, for various power sources?
I think I've dismissed this as "it doesn't get low enough for long-lived battery operation", but it occurs to me that that is not at all the same as "not significantly lower."


The main problem with battery operation of an actual Arduino Uno, Mega etc. is that the USB-to-serial converter chip is still drawing power when the main mcu is sleeping. Barebones designs without a USB-to-serial converter are a different matter entirely. If your design needs a voltage regulator, you can get micropower regulators such as MCP1702.
Title: Re: When sleeping helps
Post by: westfw on May 04, 2013, 09:29 am
Quote
avr/sleep.h and avr/power.h libraries [are] not in the general Arduino set of libraries.

They're part of avr-libc, which is "underneath" the arduino libraries, and included with the Arduino distribution.
Title: Re: When sleeping helps
Post by: tlharv on May 04, 2013, 10:37 am
Ok, after much reading tonight about sleeping, timers and interrupts, I'm ready to ask for more guidance as I attempt to put it all together.  For starters, I'm trying to improve upon an existing sketch that samples a One-Wire temperature sensor, then flashes an RGB LED either red, blue or green according to the temperature read.  It does this once per second, so the improvement is to have the chip sleeping during its one-second break thereby improving upon battery life.  It's a simple blinky application, but if I understand this I can apply it to other projects I have going.

Would a correct approach be:
1. In setup(), initiate a timer and define a one-second ISR requirement, then put the chip to sleep
2. In loop(), do nothing
3. The ISR wakes the chip, samples the temperature, and calls a nifty LED glow routine based on temperature read, the returns chip to sleep.
4. Do nothing in the sleepHandler()

I'm still stitching together sketches from sleeping, timers and interrupt examples, so I don't have anything working yet.  It's kind of a FrankenSketch at the moment.

Thanks,
Tom

Sources read:
http://n0m1.com/2011/12/15/catching-some-zzzs-part-1-interrupted-sleep/
http://www.engblaze.com/we-interrupt-this-program-to-bring-you-a-tutorial-on-arduino-interrupts/
http://www.engblaze.com/microcontroller-tutorial-avr-and-arduino-timer-interrupts/
Title: Re: When sleeping helps
Post by: afremont on May 04, 2013, 04:48 pm
An Uno R3 with the CPU removed uses almost 42mA when powered by 12V on Vin.  With the RESET button held down, it uses almost 43mA.  The power LED and the LED connected to pin 13 are illuminated.

With the CPU installed, reset mode is 50mA and running at 16MHz it's burning 58mA.
Title: Re: When sleeping helps
Post by: Coding Badly on May 04, 2013, 09:13 pm
Would a correct approach be:
1. In setup(), initiate a timer and define a one-second ISR requirement, then put the chip to sleep
2. In loop(), do nothing
3. The ISR wakes the chip, samples the temperature, and calls a nifty LED glow routine based on temperature read, the returns chip to sleep.
4. Do nothing in the sleepHandler()


There are at least two serious problems with putting the working code in the interrupt service routine.  Don't do it.  Madness lies down that path.  In my experience, empty interrupt service routines are a much better choice.

Build your application without sleeping and without interrupts.  When you are satisfied the application works the way you want, at the bottom of loop add code to wake the processor under the desired conditions then put the processor to sleep.  At the top of loop, disable wake conditions that will interfere with the work.

Quote
1. In setup(), initiate a timer and define a one-second ISR requirement, then put the chip to sleep


Watchdog timer.  That allows you to use Power Down sleep mode.
Title: Re: When sleeping helps
Post by: tlharv on May 05, 2013, 07:39 am
Thanks, all, for the comments.  It runs!  The trick was structuring it as Coding Badly recommended.  Here's how it looks... I do have some questions about some of the statements in here, which I copied verbatim from the examples I read.  Perhaps I ought to move those questions to the programming room instead.  But for now, I seem to have my answer for getting the Uno to sleep for my project.  Next step will be interpreting it for the ATtiny85.  Any recommendations for making this less cluttered, feel free to provide.

Thanks,
Tom


Code: [Select]
#include <OneWire.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>

// pin assignments are for Arduino Uno
const int redPin = 3;     // red lead of an RGB LED, common cathode
const int greenPin = 5;  // green lead of the RGB LED
const int bluePin = 6;   // blue lead of the RGB LED

const int LL = 63; // Lower Limit of acceptable temperature range; below this the light is blue
const int UL = 73; // Upper Limit of acceptable temperature range; above this the light is red

OneWire  ds(10);  // center lead of the Dallas one-wire temp sensor, plugged in to digital pin 10.


void setup(void) {
  pinMode(bluePin, OUTPUT);
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  wdtSetup();  // this sets up the watchdog timer
}

void loop(void) {
  byte i;
  byte present = 0;
  byte data[12];
  byte addr[8];
  int Temp;

  digitalWrite(13, HIGH);  // indicate that the chip is awake
  // Disable wake conditions that interfere with the main body of work
  // cli();

// GET THE TEMPERATURE FROM THE DALLAS ONE-WIRE TEMP SENSOR
  if ( !ds.search(addr)) {
      ds.reset_search();
      return;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44,1); // start conversion, with parasite power on at the end
 
  delay(2000);     // Unsure what this does but it was included in the one-wire tutorial
 
  present = ds.reset();
  ds.select(addr);   
  ds.write(0xBE);         // Read Scratchpad
  for ( i = 0; i < 9; i++) // we need 9 bytes
  {           
    data[i] = ds.read();
  }
 
  //take the two bytes from the response relating to temperature
  Temp=(data[1]<<8)+data[0];
  Temp=Temp>>4; //divide by 16 to get pure Celsius readout
  Temp=Temp*1.8+32; // comment this line out to get Celsius 
 
// NOW LIGHT THE LED BASED ON THE TEMPERATURE READ

  if (Temp < LL) // then light the blue LED - it's cold!
  {
    analogWrite(greenPin, 0);
    analogWrite(redPin, 0);
    GlowLightOnce(bluePin);
  }
  else if (Temp >= LL && Temp <= UL) // then light the green LED
  {
    analogWrite(bluePin, 0);
    analogWrite(redPin, 0);
    GlowLightOnce(greenPin);
  }
  else // light the red LED
  {
    analogWrite(bluePin, 0);
    analogWrite(greenPin, 0);
    GlowLightOnce(redPin);
  }
 
  // DEFINE SLEEP MODE
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // choose your preferred sleep mode for the chip
  sleep_enable(); // this puts the chip into, sleep mode, but doesn't command it to sleep yet.
  // Define conditions by which chip should awake (watchdog timer for 1 second)

  // Go to sleep...
  digitalWrite(13, LOW); // turn LED off to indicate sleep
  sleep_mode();  // Last statement of loop() - this command actually puts the chip to sleep.
}

// Watchdog Timer Interrupt
ISR (WDT_vect) {
  // put whatever you want to have happen at regular WDT intervals in here.
}


void GlowLightOnce(int bulb)  // subroutine applies one fade in - fade out blink of an LED
{
  int brightness = 0;
  int fadeAmount = 5;
  int totalcount = 0;
    do
    {
      analogWrite(bulb, brightness);
      brightness = brightness + fadeAmount;
      totalcount++;
      if (brightness == 255)
      {
        fadeAmount = -fadeAmount;
      }
      delay(35);
    } while (totalcount < 103);
    delay(1000);  // pause for a second while the bulb is dark
}

void wdtSetup() // Set up watchdog timer
{
  cli(); // disable all interrupts
  MCUSR = 0;  // mystery statement, but is required
  // WDTCSR register gives you access to the Arduino WDT.
  // Bit 4 = Watchdog Change Enable.  Must be cleared to change or clear the WDE bit.
  // Bit 3 = WDT bit.  Must be cleared to set WDP3 through WDP0.
  WDTCSR |= B00011000; // clear WDTCSR register bits 3 & 4
  WDTCSR = B01000111;  // Set the WDP3 through WDP0 bits, to set the WDT prescale to two seconds.
  sei(); // enables all interrupts
}

void sleepHandler(void) {
}
Title: Re: When sleeping helps
Post by: Coding Badly on May 05, 2013, 10:41 am
Any recommendations for making this less cluttered, feel free to provide.


There are no references to sleepHandler.  You could remove it.
Title: Re: When sleeping helps
Post by: Coding Badly on May 05, 2013, 10:44 am
Code: [Select]
 delay(2000);     // Unsure what this does but it was included in the one-wire tutorial

I believe that's to allow time for the conversion.  I also believe it's only necessary for parasitic power.  How are you powering the 1-Wire device?

In either case, it should be replaced with a blink-without-delay pattern; a while-loop polling for 2 seconds to elapse.  In the while-loop body put the processor to sleep (Idle mode).
Title: Re: When sleeping helps
Post by: afremont on May 05, 2013, 10:58 am
750mS is the recommended minimum conversion time allowance, regardless of power mode.  That's for a 12-bit conversion.  The OP could cut that long delay in half at least.  12 bits is the default for a new part, but I believe it can be overridden by a flashable programming setting. 
Title: Re: When sleeping helps
Post by: Coding Badly on May 05, 2013, 11:03 am
750mS is the recommended minimum conversion time allowance, regardless of power mode.


I believe, when the device is fully powered, some devices can be polled for completion.  I recall the temperature sensor I was using took considerably less than 750ms.
Title: Re: When sleeping helps
Post by: afremont on May 05, 2013, 11:14 am

750mS is the recommended minimum conversion time allowance, regardless of power mode.


I believe, when the device is fully powered, some devices can be polled for completion.  I recall the temperature sensor I was using took considerably less than 750ms.



That's absolutely correct, but I've never actually timed any to see how long they take.  Do you recall how much less it was?  I'm a big fan of the 1-wire stuff, have been for many years.  I've also found that many times you can get away with doing a conversion using parasite power mode, but not supplying the so-called "strong pullup" on the bus.  Only one device at a time though.  Which reminds me of one other piece of probably useless trivia.  You can do a SKIP ROM and then start a conversion on all the devices on the bus simultaneously.  Conversions using less bits of precision take substantially less time to complete according to the datasheet.

EDIT:  I've had good success using a PIC I/O pin to power the 1-wire bus when awake and then powering it down when sleeping, but I wrote it in assembler so it was relatively easy to insert the control code.  Now that I've thought about it as long as it took me to type this, it probably wouldn't be that hard to wrap the library code with something to accomplish the same thing.  Possibly just powering up after sleep and down just before, but you probably have to wait up to 60uS for the RESET pulse from the temp sensors after releasing the bus from reset mode.  I don't know if you have to hold the bus in reset mode for an extra 480uS before releasing it after applying power.  Experimentation would be in order on that.
Title: Re: When sleeping helps
Post by: fungus on May 05, 2013, 01:06 pm

Do we have data on how much power is consumed by an actual Arduino board in Sleep vs running, for various power sources?
I think I've dismissed this as "it doesn't get low enough for long-lived battery operation", but it occurs to me that that is not at all the same as "not significantly lower."


Most of the power consumption is from the other chips on the board.

I don't think "long-lived battery operation" is realistic with an Uno. If that's what you want you'll have to start with something like this: http://evilmadscience.com/productsmenu/tinykitlist/180


Title: Re: When sleeping helps
Post by: tlharv on May 05, 2013, 05:10 pm
My long-term plan isn't to use my Uno for the final application; I'll use it to make the thing work, then build my own barebones or standalone unit with either an ATmega328 or an ATtiny85.  I know I'll have to peruse the ATtiny85 datasheet to get the addresses & settings correct, as they're probably different than the '328P.  But the approach & program structure should be the same.
Title: Re: When sleeping helps
Post by: tlharv on May 05, 2013, 05:24 pm
Quote
How are you powering the 1-Wire device?


On my breadboard, I'm powering the 5V rail straight from the Uno 5V pin.  The temp sensor gets its supply voltage from that rail.
Title: Re: When sleeping helps
Post by: afremont on May 05, 2013, 07:06 pm

My long-term plan isn't to use my Uno for the final application; I'll use it to make the thing work, then build my own barebones or standalone unit with either an ATmega328 or an ATtiny85.  I know I'll have to peruse the ATtiny85 datasheet to get the addresses & settings correct, as they're probably different than the '328P.  But the approach & program structure should be the same.


Building your circuit out on a new board with an efficient regulator, you'll be able to get average power consumption down to near nothing.  If you really want low power usage, look at running at relatively slow clock speeds such as 32kHz.  The power requirements become surprisingly low at those speeds.  You can be running and only consuming way less than 1mA (more like hight 10s or low 100s of uA) if you use a low voltage too.

Your big power consumer will be keeping the 1-wire bus powered during the lengthy temp conversion. 
Title: Re: When sleeping helps
Post by: Coding Badly on May 05, 2013, 08:19 pm
Do you recall how much less it was?


I don't.  Just enough less to make it worth investigating.
Title: Re: When sleeping helps
Post by: Coding Badly on May 05, 2013, 08:25 pm

Quote
How are you powering the 1-Wire device?


On my breadboard, I'm powering the 5V rail straight from the Uno 5V pin.  The temp sensor gets its supply voltage from that rail.


Change that to an I/O pin.  You will have to add code to "power up" the sensor after the processor wakes and "power down" the sensor before sleeping.  As @afremont mentioned earlier, you may need a short delay to give the sensor time for a bit of coffee.

Change the code to poll for the conversion to complete rather than waiting a fixed amount of time.
Title: Re: When sleeping helps
Post by: afremont on May 05, 2013, 09:18 pm
I'm not trying to start an argument, but I was just thinking that it might be an interesting case study to see where (or if) there is some break even point is on polling vs. just waiting it out with a slowly clocked CPU.  I'm wondering if there might be some point where beating on the bus dissipates more power than just waiting it out.  I really wish I knew now how much time you can shave off that 750mS with polling. 

Argh this is why everything takes me so long, I get obsessed over the most mundane oddities that I uncover in some code until I completely understand what is happening.  I spent a couple of days obsessing over the dropped time from delay() when micros() rolled over.  Found it though.  Now I feel 1-wire timing tests creeping up on me.  ;)
Title: Re: When sleeping helps
Post by: DamonHD on May 05, 2013, 09:44 pm
I have implemented both 'running the CPU clock with maximum prescaling' (which gets me 31.25kHz) and sleeping with watchdog timer.  I use the former for delays too short for the latter.

See the following for some experiments:

https://sourceforge.net/p/opentrv/code-0/HEAD/tree/trunk/Arduino/test/BlinkPower/BlinkPower.ino

Busy waiting with a slow CPU was taking ~3mA, which is a decent saving over running flat out, but sleeping with the watchdog timer takes maybe 1000th of that for me I think. (I confess that I was measuring power-save sleeping against the async timer 2 clock towards the end, rather than the watchdog, but I the datasheet seems to agree with me.)

Sleeping waiting for an interrupt can also be beneficial, eg for the ADC, if it's not too fast that the interrupt latency is a problem.

Rgds

Damon

Title: Re: When sleeping helps
Post by: Coding Badly on May 05, 2013, 09:56 pm
I was just thinking that it might be an interesting case study to see where (or if) there is some break even point is on polling vs. just waiting it out with a slowly clocked CPU.


You bring up a good point.  Polling may not be the best choice.

Polling vs waiting (sleeping it off) is more of an application question.  How quickly does the device need to get the data and react?  If the wait time is irrelevant then sleeping it off is the best choice.  My suspicion is that @tlharv's application could just sleep for the 750ms.

Polling is easily made efficient by bisection and sleeping (tweaked by the application requirements).  For example...
- Start the conversion
- Sleep for 750 * 1/2 ms
- Poll for completion.  If the conversion completed, mark the high time as 750 * 1/2, the low time as 750 * 0/2, and finish up.
- Sleep for the other half (another 750 * 1/2 ms)
- Conversion has to be completed, mark the high time as 750 * 2/2, the low time as 750 * 1/2, and finish up.

The next time around, we know to either sleep 750 * 1/4 ms or 750 * 3/4 ms to split the range in half.  Each time around, the range narrows and the sleep time becomes more precise.  Quickly we arrive at the perfect sleep time.  The process becomes...
- Start the conversion
- Sleep for the perfect amount of time
- Poll to ensure completion (make any necessary minor adjustments)
- Finish up


Now I feel 1-wire timing tests creeping up on me.  ;)


Resist.  ;)
Title: Re: When sleeping helps
Post by: DamonHD on May 05, 2013, 10:56 pm
@CB: conversion time may vary from sample to sample depending on the sensor/ADC/etc...

Rgds

Damon
Title: Re: When sleeping helps
Post by: Coding Badly on May 05, 2013, 11:28 pm
@CB: conversion time may vary from sample to sample depending on the sensor/ADC/etc...


That's not what I remember with 1-Wire temperature sensors.  I believe, for a given configuration / sensor, the conversion time is fairly consistent.
Title: Re: When sleeping helps
Post by: tlharv on May 06, 2013, 06:21 am
Quote
In either case, it should be replaced with a blink-without-delay pattern; a while-loop polling for 2 seconds to elapse.  In the while-loop body put the processor to sleep (Idle mode).


Ok, I've replaced my delay(2000) statement with IdleChip(2000), function defined as:

Code: [Select]
void IdleChip(unsigned long duration)
{
  unsigned long start = millis();
  set_sleep_mode(SLEEP_MODE_IDLE);  // choose idle mode for the chip
  sleep_enable();                              // this puts the chip into sleep mode, but doesn't command it to sleep yet
  sleep_mode();                                // put chip in idle mode
  while (millis() - start <= duration) {
    digitalWrite(13, LOW);                  // turn LED off to indicate sleep
  }
  sleep_disable();
  digitalWrite(13, HIGH);                   // turn LED on to indicate waking up
}
Title: Re: When sleeping helps
Post by: Coding Badly on May 06, 2013, 08:02 am

Might want to move that sleep inside the body or it doesn't do much good...

Code: [Select]
void IdleChip(unsigned long duration)
{
  unsigned long start = millis();
  set_sleep_mode(SLEEP_MODE_IDLE);  // choose idle mode for the chip
  sleep_enable();                              // this puts the chip into sleep mode, but doesn't command it to sleep yet
  digitalWrite(13, LOW);  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<                  // turn LED off to indicate sleep
  while (millis() - start <= duration) {
    sleep_mode();  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<                              // put chip in idle mode
  }
  sleep_disable();
  digitalWrite(13, HIGH);                   // turn LED on to indicate waking up
}
Title: Re: When sleeping helps
Post by: JChristensen on May 07, 2013, 09:14 pm

Do we have data on how much power is consumed by an actual Arduino board in Sleep vs running, for various power sources?
I think I've dismissed this as "it doesn't get low enough for long-lived battery operation", but it occurs to me that that is not at all the same as "not significantly lower."


Here is some data from various Arduino I had kicking around. 5V power supply in all cases, fed to the 5V pin. While I would have to call a 25% to 30% reduction "significantly lower", I'm still in the "it doesn't get low enough for long-lived battery operation" camp where actual Arduino boards are concerned.

Uno R1
38mA running, 26mA with MCU in power-down mode.

Uno SMD edition
42mA running, 31mA power-down.

Adafruit Boarduino
Power select jumper set to "USB", USB (FTDI) not connected.
15mA running, 3mA power-down.

Adafruit Boarduino sans power LED
12mA running, 0.1µA power-down.

ATmega328P-PU on a breadboard
12mA running, 0.1µA power-down.

Code: [Select]
//Sketch to measure current while sleeping.
//Wire a button from pin D2 (INT0) to ground.
//Pushing the button wakes the MCU.
//Once awake, the MCU flashes the pin 13 LED, then
//waits 10 seconds before going back to sleep.
//
//Jack Christensen 07May2013

#include <avr/sleep.h>

#define LED LED_BUILTIN            //LED on pin 13

byte intCounter;                   //interrupt counter

void setup(void)
{
   makePinsInput();
   EICRA = 0x00;                  //configure INT0 to trigger on low level
}

void loop(void)
{
   for (byte i=0; i<5; i++) {
       digitalWrite(LED, HIGH);
       delay(100);
       digitalWrite(LED, LOW);
       delay(100);
   }
   delay(10000);
   goToSleep();
}

void goToSleep()
{
   byte intCounter, adcsra, mcucr1, mcucr2;

   makePinsInput();
   sleep_enable();
   set_sleep_mode(SLEEP_MODE_PWR_DOWN);
   EIMSK = _BV(INT0);             //enable INT0
   adcsra = ADCSRA;               //save the ADC Control and Status Register A
   ADCSRA = 0;                    //disable ADC
   cli();
   mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE);  //turn off the brown-out detector
   mcucr2 = mcucr1 & ~_BV(BODSE);
   MCUCR = mcucr1;                //timed sequence
   MCUCR = mcucr2;                //BODS stays active for 3 cycles, sleep instruction must be executed while it's active
   sei();                         //ensure interrupts enabled so we can wake up again
   sleep_cpu();                   //go to sleep
   sleep_disable();               //wake up here
   ADCSRA = adcsra;               //restore ADCSRA
   makePinsInput();
}

ISR(INT0_vect)
{
   EIMSK = 0;                     //disable interrupts (only need one to wake up)
   ++intCounter;
}

//make all pins input pins with pullup resistors to minimize power consumption
void makePinsInput(void)
{
   for (byte i=0; i<20; i++) {
       pinMode(i, INPUT_PULLUP);  
   }
   pinMode(LED, OUTPUT);          //except the LED pin
   digitalWrite(LED, LOW);
}