Pages: [1]   Go Down
Author Topic: attiny45 sleep mode?  (Read 7042 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Sr. Member
****
Karma: 2
Posts: 260
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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)


« Last Edit: December 18, 2011, 07:29:08 pm by kduin » Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 210
Posts: 13039
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


Have you searched this forum?
Logged

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 95
Posts: 4092
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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.
« Last Edit: February 22, 2012, 12:44:43 pm by Jack Christensen » Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Halifax, Canada
Offline Offline
Jr. Member
**
Karma: 0
Posts: 50
Don't anthropomorphize computers. They hate that.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

    //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

Logged

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 95
Posts: 4092
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#define BODS 7                   //BOD Sleep bit in MCUCR
#define BODSE 2                  //BOD Sleep enable bit in MCUCR
uint8_t mcucr1, mcucr2;
Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Pages: [1]   Go Up
Jump to: