Electronic – How much current is a powered-down ATtiny84 supposed to take

attinycurrent measurementsleep

I know this sounds like a stupid question, but I'm wondering if the datasheet has an error or something.

I have an ATtiny84 connected to my bench power supply set for 3 volts. It's fused for the internal 8 MHz RC oscillator and a divide-by-8 clock. No watchdog, no brown-out detector.

8 of the I/O pins are hooked to LED anodes, with the cathodes grounded through 0 ohm resistors (yes, the duty cycle is low. Fear not). One of them is connected to a button with the other side grounded. Two of them (shared with MOSI and SCK of the ISP) are not connected (other than to the ISP which is itself disconnected for this test).

setup:

void setup() {

  power_adc_disable();
  power_usi_disable();
  power_timer1_disable();
  ACSR = _BV(ACD);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);

  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(UNUSED_1, OUTPUT);
  digitalWrite(UNUSED_1, LOW);
  pinMode(UNUSED_2, OUTPUT);
  digitalWrite(UNUSED_2, LOW);
  for(int i = 0; i < 8; i++) {
    pinMode(LED_PINS[i], OUTPUT);
    digitalWrite(LED_PINS[i], LOW);
  }
  while(1) sleep_mode();
}

The result is 240 µA of current draw. This is measured with a µCurrent Gold, so I have some confidence in the accuracy.

The datasheet (figure 21-1) says that powered down at 25°C the chip should take more like 100 nA.

WTF?

For reference, here's the actual sleep function used by the code (but not part of this test):

void sleepNow() {
  // All LEDs off
  for(int i = 0; i < 8; i++) {
    digitalWrite(LED_PINS[i], LOW);
  }
  cli();
  power_timer0_disable();
  PCMSK0 |= _BV(PCINT5);
  GIMSK |= _BV(PCIE0);
  sleep_enable();
  sei();
  sleep_cpu();
  sleep_disable();
  PCMSK0 &= 0xff ^ _BV(PCINT5);
  GIMSK &= 0xff ^ _BV(PCIE0);
  power_timer0_enable();
  button_debounce_time = millis();
  ignoring_button = 1;
  place_in_pattern = -1;
  milli_of_next_act = 0;
}

It yields the same current consumption, which is why I reduced this test down to just putting the chip to sleep in as little code as possible.

The schematic:

enter image description here

For this test, the battery is absent and 3.00 volts is being fed in to the Vcc and GND pins of the ISP header. No other ISP pins are connected.

I've repeated this experiment with an ATTiny85 on a breadboard. I programmed it with this:

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

void setup() {
  PRR = 0xff;
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);

  pinMode(0, OUTPUT);
  digitalWrite(0, LOW);
  pinMode(1, OUTPUT);
  digitalWrite(1, LOW);
  pinMode(2, OUTPUT);
  digitalWrite(2, LOW);
  pinMode(3, OUTPUT);
  digitalWrite(3, LOW);
  pinMode(4, OUTPUT);
  digitalWrite(4, LOW);
  while(1) { sleep_mode(); digitalWrite(2, HIGH); }
}

void loop() {}

I then fused it for a 1 MHz internal clock, and then disconnected everything but power and ground. The result: 240 µA.

Now, all of this would be explained if the graph in figure 22-11 (this is the ATTiny85 datasheet now) had the axis mislabeled and was actually in mA rather than µA. The power down current vs Vcc and temperature that I'm using lines right up with the graph 3 orders of magnitude higher.

Has anyone gotten an ATTiny to draw less than a micro-amp (other than just disconnecting power)? Can someone write a sketch that will make an ATTiny do nothing but just go permanently to sleep consuming as little power as possible with nothing connected except power and ground? That's what I've been trying to do, and there clearly is something that I'm missing and I'll be damned if I can figure out what it is.

Best Answer

This comment on reddit pointed me to this page, which says that clearing the ADEN bit in ADCSRA shed as many µA as are currently in excess in my test rigs. I am away from the lab right now, but when I get home tonight, that's the first thing I'll try. I'm optimistic. I do know that the ADEN bit gets set in init() in wiring.c...

If it's confirmed, then the lesson is that PRR is not enough to turn the ADC all the way off.

EDIT: It is confirmed. The one added caveat is that order matters. ADCSRA must be written before PRR.

My sleep_tiny_sleep sketch (last above) now takes < 100 nA.