Sleepy Arduino

I've modified the above code and made some nice discoveries through empirical testing.
When the Atmel goes into Power Down sleep mode, it shuts down all the asynchronous clocks, and turns off the system clock (crystal oscillator stops, millis() won't be reliable), but it's important to disable the Analog to Digital Converter to squeeze out the most power saving. I'm running off a rechargeable battery that has a solar charging circuit, so I need the Atmel to sleep very deeply. It's also very important (see above) to keep track of what your pins are doing. If enough pins are not accounted for, the circuit can draw more current during sleep than when the MCU is operating! I'm using a P-channel MOSFET (BS250) as a power switch for the board. The Atmel +V pins are connected on the high side of the MOSFET, so it's always getting juice, but just before sleeping, the gate of the MOSFET is pulled HIGH (it's got a pullup to boot) and the board is shutdown. In this case, it's very important not to have any of the internal pullups enabled! that's where the power loss would come from in my setup: pulled up pins connected to GND will draw current. Happily, I'm getting really good results.

Besides the Atmel328, I've got the following chips on board:
MCP4551 digital potentiometer (I2C)
S-80835 voltage detector
Photo resistor
TNC75A Temperature sensor (I2C)

Here's the current draw specs:
MCU operating, reading sensors ~ 6.8mA
MCU in RESET (pin 1 LOW) ~ 1.2mA
MCU in Power Down (rest of board off with MOSFET) ~ 0.21mA
(tested within a curly hair on VellemanVC140 and RadioShack22-81)

Here's an app note that helped me out figuring the proper Power MOSFET to use
http://www.latticesemi.com/lit/docs/appnotes/pac/an6048.pdf?jsessionid=f03091fa05970c3c49b01838131a11167b40
On the PCB prototype I will use NDT456P MOSFET. It's got better stats.

/*
 Watchdog Sleepy Bones (the skeleton is the essential armature for any living thing)
 This is the basic structure that you need to Sleep_Mode_Pwr_Down/Watchdog interrupt wake
 Provided for general consumption by Rachel's Electronics http://www.rachelselectronics.com
 Under the CC licence here (http://creativecommons.org/licenses/by-sa/3.0/us/)
 Rachel's Electronics: Making the World Safe for Robots! -Joel Murphy joel@joelmurphy.net
 
          Built in part from code posted by: 
           * KHM 2008 / Lab3/  Martin Nawrath nawrath@khm.de
           * Kunsthochschule fuer Medien Koeln
           * Academy of Media Arts Cologne 
             http://interface.khm.de/index.php/lab/experiments/sleep_watchdog_battery/
*/


#include <avr/sleep.h>
#include <avr/wdt.h>
#define sleepTime  3                       //number of 8 second sleep cycles

volatile byte wdt=0;                       //used to cound number of sleep cycles

void setup(){
  
  setup_watchdog();                        // set prescaller and enable interrupt                  
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);     // sleep mode is set here Power Down uses the least current
                                           // system clock is turned off, so millis won't be reliable!
  delay(10);
}


void loop(){

         // do what you want to before you sleep here
           
    system_sleep();

         // do what you want to after you sleep here
}
 

void system_sleep() {
  ADCSRA |= (0<<ADEN);                     // disable ADC
  sleep_enable();                          // enable sleeping
  sleep_mode();                            // activate system sleep
  // sleeping ... 
  // first action after leaving WDT Interrupt Vector:
  if (wdt == sleepTime) {                  // sleep for this number times 8 seconds
    sleep_disable();                       // disable sleep  
    ADCSRA |= (1<<ADEN);                   // switch ADC on    
    wdt = 0;                               // reset watchdog counter   
    }else{
    system_sleep();                        // go back to sleep until it's time
  }
}


void setup_watchdog() {
cli(); //disable global interrupts
  MCUSR = 0x00;  //clear all reset flags 
  //set WD_ChangeEnable and WD_resetEnable to alter the register
  WDTCSR |= (1<<WDCE) | (1<<WDE);   // this is a timed sequence to protect WDTCSR
  // set new watchdog timeout value to 1024K cycles (~8.0 sec)
  WDTCSR = (1<<WDP3) | (1<<WDP0);
  //enable watchdog interrupt
  WDTCSR |= (1<<WDIE);    
sei(); //enable global interrupts
}

// Watchdog Interrupt Service Routine. 
// Very first thing after sleep wakes with WDT Interrupt
ISR(WDT_vect) {
  wdt++;  // increment the watchdog timer
}

Just a couple of other things.
In the code posted above, I said 'sleep_mode();' after the }else{ in system_sleep(). Well, that obviously caused me no end of trouble... except that the trouble did end. The program will sleep for any multiple of 8 seconds that you desire by adjusting the sleepTime value.
Also, the datasheet notes on PRR register says that you need to keep track of your settings if you're going to turn off the clocks to save power. I can only assume that the good folks at arduino are using this register to kill the clocks, and that they are also keeping track of the associated settings, because my I2C business picks right back up without any coding on my end. I did test manually flipping the PRR, and it didn't make a damn bit of difference in anything.
Finally, if you want to communicate (I2C,SPI,UART,etc) you must delay for 2 or 5 mS after waking up or else you will lose bits.

I will post a link on this thread when I get my pictures and bits all sorted out.
I hope this helps!
Joel