Go Down

Topic: attiny45 sleep mode? (Read 7463 times) previous topic - next topic

kduin

Dec 19, 2011, 01:27 am Last Edit: Dec 19, 2011, 01:29 am by kduin Reason: 1
Hello,

i recently built a project with an attiny45.
The attiny is powered by a 9V battery with a 5V regulator.

Unfortunately the battery is empty after a few days, because the attiny consumes about 4.8 mA while doing nothing.

I read about a sleep mode in the manual, so the attiny could wake up on a button-press for example.

What code is needed for the sleep mode?

(I'm programming the attiny with arduino code, like described here)



Coding Badly


Have you searched this forum?

Jack Christensen

#2
Dec 19, 2011, 02:15 pm Last Edit: Feb 22, 2012, 06:44 pm by Jack Christensen Reason: 1
Here is code I've used on ATtiny45s and 85s. Some notes:

1. This code assumes a momentary contact switch from PB2/INT0 to ground, this is used to wake the MCU.

2. Before calling goToSleep(), to minimize current consumption, I ensure that (a) output pins are set high or low as needed so that their loads do not draw current, and (b) all other pins are set as inputs with the pullup resistor enabled.

3. The 5V regulator will continue to draw quiescent current even if the AVR is in power-down mode, which defeats the whole purpose. A 7805 will typically draw 6mA even if it's not powering a load. LDO types can do quite a bit better, but I'd prefer just to run on two or three AA cells, which will last a lot longer than a 9V anyway.

Code: [Select]
#include <avr/sleep.h>
#include <avr/interrupt.h>
#define BODS 7                   //BOD Sleep bit in MCUCR
#define BODSE 2                  //BOD Sleep enable bit in MCUCR
uint8_t mcucr1, mcucr2;
...
void goToSleep(void)
{
   GIMSK |= _BV(INT0);                       //enable INT0
   MCUCR &= ~(_BV(ISC01) | _BV(ISC00));      //INT0 on low level
   ACSR |= _BV(ACD);                         //disable the analog comparator
   ADCSRA &= ~_BV(ADEN);                     //disable ADC
   set_sleep_mode(SLEEP_MODE_PWR_DOWN);
   sleep_enable();
   //turn off the brown-out detector.
   //must have an ATtiny45 or ATtiny85 rev C or later for software to be able to disable the BOD.
   //current while sleeping will be <0.5uA if BOD is disabled, <25uA if not.
   cli();
   mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE);  //turn off the brown-out detector
   mcucr2 = mcucr1 & ~_BV(BODSE);
   MCUCR = mcucr1;
   MCUCR = mcucr2;
   sei();                         //ensure interrupts enabled so we can wake up again
   sleep_cpu();                   //go to sleep
   cli();                         //wake up here, disable interrupts
   GIMSK = 0x00;                  //disable INT0
   sleep_disable();              
   sei();                         //enable interrupts again (but INT0 is disabled from above)
}

ISR(INT0_vect) {}                  //nothing to actually do here, the interrupt just wakes us up!


Edit 22Feb2012: Added defines and declarations for mcucr1, mcucr2 at top of sample code.
MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

MLeBlanc


    //must have an ATtiny45 or ATtiny85 rev C or later for software to be able to disable the BOD.


How do you tell which revision you have? The data sheet says that the revision numbers can be found on the back of the 8P3 (DIP) package, but all I see on the back are codes:

OF4     419
G5       1P
1025     e3


The reason I ask is because I tried testing this code using Arduino 0022 inside a minimal sketch (setup and loop empty), and it would not compile. The errors were:

sketch_feb22a.cpp: In function 'void goToSleep()':
sketch_feb22a.cpp: error: 'mcucrl' was not declared in this scope
sketch_feb22a.cpp: error: 'BODS' was not declared in this scope
sketch_feb22a.cpp: error: 'BODSE' was not declared in this scope
sketch_feb22a.cpp: error: 'mcucr2' was not declared in this scope


Jack Christensen

I could never make heads or tails out of the markings on the back of the package, either. I concluded that the ATtiny85s that I had were not revision C, since the current in power down mode only dropped to 20µA or so, whereas an ATtiny45 running the same code dropped to under 0.5µA.

Adding the following at the top of the sketch should address the compile errors. Not sure why the BODS and BODSE bits aren't already defined, I didn't look into it, just defined 'em myself.

Code: [Select]
#define BODS 7                   //BOD Sleep bit in MCUCR
#define BODSE 2                  //BOD Sleep enable bit in MCUCR
uint8_t mcucr1, mcucr2;
MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Go Up