9
\$\begingroup\$

I'm trying to get an ATTiny85 to run off a battery. I have it clocked from a 16.384 MHz crystal, with the divide-by-8 fuse set. Vcc is 3.3 volts. Figure 22-7 in the datasheet says that at idle ( set_sleep_mode(SLEEP_MODE_IDLE); sleep_mode(); ), it should draw around 300 µA. In actual fact, I see it drawing more like 850 µA. I can't figure out why the power consumption is double expected. I've turned off everything in PRR except for timer0, which I've configured to interrupt every 25 ms. So it should spend the vast majority of its time in the idle state, which is the best I can do given that I still want the timers to count.

The fuses are 0x7f, 0xdf, 0xff.

Here's the code it's running for this test:

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

#define P0 0
#define P1 1
#define P_UNUSED 2

ISR(TIMER0_COMPA_vect) {
  // do nothing - just wake up
}

void setup() {
  power_adc_disable();
  power_usi_disable();
  power_timer1_disable();
  //PRR = _BV(PRADC) | _BV(PRTIM1) | _BV(PRUSI); // everything off but timer 0.
  TCCR0A = _BV(WGM01); // mode 2 - CTC
  TCCR0B = _BV(CS02) | _BV(CS00); // prescale = 1024
  // xtal freq = 16.384 MHz.
  // CPU freq = 16.384 MHz / 8 = 2.048 MHz
  // count freq = 2.048 MHz / 1024 = 2000 Hz
  OCR0A = 50; // 25 msec per irq
  TIMSK = _BV(OCIE0A); // OCR0A interrupt only.

  set_sleep_mode(SLEEP_MODE_IDLE);

  pinMode(P_UNUSED, INPUT_PULLUP);
  pinMode(P0, OUTPUT);
  pinMode(P1, OUTPUT);
  digitalWrite(P0, LOW);
  digitalWrite(P1, LOW);

  while(1) { sleep_mode(); }
}
void loop() {}
\$\endgroup\$
  • 1
    \$\begingroup\$ Did you kill the comparator? \$\endgroup\$ – Ignacio Vazquez-Abrams Aug 10 '14 at 20:55
  • 1
    \$\begingroup\$ Have you have a look at some of the tricks the jeelabs guy did? See here (start reading at the bottom): jeelabs.org/tag/lowpower \$\endgroup\$ – RJR Aug 11 '14 at 5:13
  • 1
    \$\begingroup\$ @RJR I took a look, and unfortunately a lot of their tricks won't work because I can only use SLEEP_MODE_IDLE because I need to keep the timer running. This application is a clock. \$\endgroup\$ – nsayer Aug 11 '14 at 13:59
  • 1
    \$\begingroup\$ If this is a clock, can I suggest running off the internal oscillator and using a watch crystal on timer 2 to fire the watchdog interrupt? You can then use deep sleep. I think there a jeelabs blog post about that somewhere too. \$\endgroup\$ – RJR Aug 11 '14 at 23:56
  • 1
    \$\begingroup\$ All the googling I see suggests that they're using an external RTC module. If you have an RTC, then, yes, you can use the watchdog and the internal oscillator because the CPU clock isn't important. In this case, however, I want the accuracy of the crystal. And also, this is an ATTiny85 - there is no timer 2, just 0 and 1, and timer 1 consumes an order of magnitude more power than timer 0. I don't know how you'd hook a crystal up to an ATTiny without any extra external components other than as the system clock. \$\endgroup\$ – nsayer Aug 12 '14 at 4:10
6
\$\begingroup\$

You say that according to Figure 22-7 in the datasheet it should only draw 300µA, but that graph shows the current draw for operation without clock division. A crystal oscillator running at 16MHz is bound to draw more current than one running at 2MHz, and the 3 stage divider will add a bit more. The question is - how much more?

The datasheet also suggests that idle current can be reduced by dividing the clock down, but again it doesn't say how much it will be reduced. Extrapolating the 3.3V line suggests that it would normally draw about 1.5mA at 16.4MHz, and 850µA is a significant reduction - but should it be less?

If you can't use a lower frequency crystal on the boards you have coming then there may be nothing you can do. However, while you have the circuit on a breadboard you could at least try a 2MHz crystal, to see if that really is the problem.

enter image description here

\$\endgroup\$
  • \$\begingroup\$ Ok. I'll bite. I'll go to the store today and pick up a 2 MHz crystal and re-fuse the chip for no clock division and check it. \$\endgroup\$ – nsayer Aug 11 '14 at 14:10
  • \$\begingroup\$ Another difficulty is the need for 2^x crystal frequencies. I went to the store and found a 4.096 MHz one, but 1.024 and 2.048 are hard to find. But not using a 2^x clock makes it hard to pick a prescale and OCR0A value that results in even fractions of a second interrupts. But if 8.192 MHz divided by 16 saves significant power, I'd certainly be happy with that over 16.384 divided by 32. \$\endgroup\$ – nsayer Aug 11 '14 at 17:32
  • 2
    \$\begingroup\$ With a 4.096 MHz crystal in place and a CPU clock prescale value of 8, it now draws around 450 µA. \$\endgroup\$ – nsayer Aug 12 '14 at 1:14
  • \$\begingroup\$ a few years late, but why not buy a RTC and use it's PPS, hard sleep the processor and have it only wake on interrupt. \$\endgroup\$ – HilarieAK Feb 10 '16 at 11:31
3
\$\begingroup\$

I had a similar issue with that chip. The power consumption was 30% more than expected.

The issues was unused GPIO !

They were configured as inputs and left floating. The lack of a clear defined input state did make the GPIO driver consume a lot more that what is specified.

The answer was to enable the pull-ups or configure unused pins as outputs.

Are you sure that the pins are set correctly? In your code it seems so, but did you check?

\$\endgroup\$
  • \$\begingroup\$ Well, shit. If pinMode(P_UNUSED, INPUT_PULLUP); isn't enough, then WTF? \$\endgroup\$ – nsayer Aug 11 '14 at 13:35
  • \$\begingroup\$ Yeah, but sometimes this is not sufficient. For instance, you may have pins that are ADC input or analog input by default, regardless of the direction you program. There, you first have to disable the secondary function. That's what I meant by "checking". \$\endgroup\$ – Blup1980 Aug 11 '14 at 13:48
  • \$\begingroup\$ This is an ATTiny85. There are 6 pins, but 3 of them are RESET and the two xtal pins. Two of them are outputs and one is P_UNUSED. The entire ADC has been explicitly powered down. I'll try the INPUT_PULLUP trick on the other 3 pins, but I suspect it won't change anything. There is an errata for the Tiny45 that talks about not setting the xtal pins to OUTPUT because of power consumption. \$\endgroup\$ – nsayer Aug 11 '14 at 14:08
  • \$\begingroup\$ Adding pinMode(3, INPUT_PULLUP); and the same for 4 and 5 did nothing. \$\endgroup\$ – nsayer Aug 11 '14 at 14:17
1
\$\begingroup\$

I would like to add that for a separate project, I asked this question, and the answer dramatically impacted this question as well. clearing ADCSRA brought the idle consumption down to what figure 22-6 says it's supposed to take - around 100 µA at a divided system clock rate of 500 kHz - and that's the post-divided clock frequency, not the crystal frequency.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.