I just put together a first prototype of a low-power Arduino derivative using the ATmega644PA. As the first test, I'm trying to put this chip into its deepest sleep to measure/verify baseline power consumption (as low as 0.1uA according to the datasheet). But for some reason, no matter what I do there is an unexpectedly large static current draw even in full powerdown: about 100uA at 3.3V. The chip is driven by a 4MHz external crystal, which goes silent after executing sleep_cpu().
I've more or less confirmed this is being drawn by an on-chip resource (not floating pins or pullup/down resistors) - swapping the chip into an empty socket with only Vdd/GND, a 100nF bypass cap, crystal and RESET pullup has no effect. But for the life of me I can't find what it is.
Current fuse settings:
mosquino.bootloader.low_fuses=0xf7
(External crystal, not divided)
mosquino.bootloader.high_fuses=0xDC
(On-chip debugger off; JTAG off; SPI programming enabled; WDT not always on)
mosquino.bootloader.extended_fuses=0xFE
(BOD @ 1.8v when enabled)
The code so far: (just keeps growing longer as I find new things to try / fumble with)
#include <avr/power.h>
#include <avr/sleep.h>
/*
Sleeptest
Put the AVR all the way to sleep so we can measure board current consumption.
*/
int ledPin = 27; // LED connected to digital pin
void setup() {
// initialize the digital pins as outputs... no, now try inputs just to be anal...
int i;
for(i=0; i<32;i++)
{
//pinMode(i, OUTPUT); //ensure no floating pins
pinMode(i, INPUT); //ensure no sneaky leakage paths I'm not seeing
//digitalWrite(i, LOW);
}
// except for INT0, INT1 which have a pullup resistor
// //pinMode(14, INPUT);
// //pinMode(15, INPUT);
// digitalWrite(14, HIGH);
// digitalWrite(15, HIGH);
//
// // 25: SCL
// //26: SDA
//
// pinMode(27, OUTPUT);
// digitalWrite(27, LOW);
//
// pinMode(28, OUTPUT);
// digitalWrite(28, LOW);
//
// pinMode(29, OUTPUT);
// digitalWrite(29, LOW);
// pinMode(ledPin, OUTPUT);
// digitalWrite(ledPin, LOW);
//
// pinMode(30, OUTPUT);
// digitalWrite(30, LOW);
// Put various on-chip modules to sleep
// *CRASH!* CPU hangs if this is executed...
// Arduino does not like its timers disabled...
//power_all_disable();
// these "should" not matter much anyway as all clocks should stop in deep sleep anyway...
power_adc_disable();
power_spi_disable();
power_twi_disable();
power_usart0_disable();
////power_usart1_disable(); // not defined, wtf?
/* * In the avr/sleep.h file, the call names of these sleep modes are to be found:
*
* The 5 different modes are:
* SLEEP_MODE_IDLE -the least power savings
* SLEEP_MODE_ADC
* SLEEP_MODE_PWR_SAVE
* SLEEP_MODE_STANDBY
* SLEEP_MODE_PWR_DOWN -the most power savings
*/
// try disabling the BOD
// Requires an unlock sequence: Set BODS (bit 6) and BODSE (bit 5), then clear BODS within 4 cycles.
// "Then, to set the BODS bit, BODS must be set to one and BODSE must be set to zero within four clock cycles."
// (does this mean in the same instruction or not?)
MCUCR |= B01100000; // set BODS, BODSE
//MCUCR &= B10111111; // clear BODS
MCUCR &= B10011111; // clear BODSE (BODS again too for good measure)
MCUCR |= B00010000; // disable pullups - no change
// kill WDT if running
MCUSR = 0;
WDTCSR |= _BV(WDCE) | _BV(WDE);
WDTCSR = 0;
// turn OFF analog parts
ACSR = ACSR & 0b11110111 ; // clearing ACIE prevent analog interupts happening during next command
ACSR = ACSR | 0b10000000 ; // set ACD bit powers off analog comparator
ADCSRA = ADCSRA & 0b01111111 ; // clearing ADEN turns off analog digital converter
// Found in: http://www.mail-archive.com/tinyos-help@millennium.berkeley.edu/msg17215.html
// cbi(ADMUX,REFS0);
// cbi(ADMUX,(REFS1));
// cbi(ADCSRA,ADEN);
// cbi(ADCSR,ACIE);
// sbi(ACSR,ACD);
ADMUX &= B00111111;
// blink to show we're still alive and ready to sleep
digitalWrite(ledPin, HIGH);
delay(100);
digitalWrite(ledPin, LOW);
delay(100);
digitalWrite(ledPin, HIGH);
delay(100);
digitalWrite(ledPin, LOW);
delay(100);
digitalWrite(ledPin, HIGH);
delay(100);
digitalWrite(ledPin, LOW);
delay(100);
digitalWrite(ledPin, HIGH);
PRR = B11111111 ; // Bit 6, 5 are timers...
digitalWrite(ledPin, LOW);
// Digital Input Disable
DIDR1 = B00000011;
DIDR0 = B11111111;
}
void loop()
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_cpu();
while(1)
{
digitalWrite(ledPin, HIGH);
digitalWrite(ledPin, LOW);
}
}
Has anyone seen this before, or know what I'm missing?