What is the best option for waking from sleep?

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm working on a project using an ATtiny13. I have one momentary push button that is attached to PB0 and utilizes the internal pull-up resistor.

I would like to use this button to wake the device up from sleep mode. I am pretty sure I can do this by leaving the internal pull-up active and using the pin change interrupt to wake from shutdown-mode. Am I wasting a lot of power by leaving this pull-up enabled? Is this the best way to do it in my case?

I also noticed that PB0 has the alternate function of PCINT0. I read that an external PCINT0 can be used to wake up the device but I don't really understand how. Is there another option here? Since the button connects to ground I don't see how I could use it as an external interrupt but as I said I don't relaly understand how this option would work.

Thanks for your insight and guidance!

edit:
It seems I'm confusing PCINT0 with INT0. Upon further investigation I see that INT0 can wake up the device from power-down mode and can be done from a low level. Does this mean I still need the internal pull-up enabled and once again, how does having this enabled effect the power savings?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Am I wasting a lot of power by leaving this pull-up enabled?

The short answer is that it uses >>no<< power to have a button connected to the pullup. Yeah, it may not have infinite resistance but nothing to be measurable.

Interrupt on pin-change to wake from sleep is a very useful thing. If it is a spurious edge and nothing is happening you just yawn and stretch and go back to sleep. A null ISR often is enough.

For the low-level interrupt you must disable it in the ISR, then re-enable it before returning to sleep or it will fire continually while the button is held.

On a side note, I'd always consider starting with Tiny25 vs. Tiny13--more resources and more "modern" AVR toyz for about the same money.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Lee, that's good information. I'll see if I can get the interrupt on pin-change working for me.

As for the tiny25 v. tiny13, I'll keep it in mind. I ordered 6 of the tiny13 when I first started with AVR and ended up with nothing to really use them for. Now I'm just making up projects to do something with the surplus.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
What is the best option for waking from sleep?
Make sure you are still breathing...many people forget to breath when they wake up... sorry :wink:

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm running into a bit of a problem here. I decided to implement the Pin Change Interrupt to turn off and on an LED before actually running this sleep routines. This way I can make sure I've got the code right for the interrupt.

When I run the code it works perfectly.... the first time. I press the button, the LEDs go off, when I press it again they come back on. The problem is the second time I try this the LEDs just blink off and then back on as if the PCINT0 isr is tripping right away.

Here is the function I'm using to enable the PCINT as well as the ISR and supporting functions. Notice I am using a 500ms delay to prevent multiple button reads. Can anyone see where I'm going astray?

edit: Strange, I can make this problem go away if I also unset the PCINT0 bit during the PCINT0_vect ISR (using this code: PCMSK &= ~(1<<PCINT0);) Why do I need to unset this bit in addition to turning off the interrupt?

//Setup the timer to overflow without prescaler and enable overflow interrupt
void init_timers(void)
{
  cli();
  TCCR0B |= (1<<CS00);
  TIMSK0 |= (1<<TOIE0);
  sei();
}


void init_io(void)
{
  LED_PORT = 0x00;	//Set all outputs low
  LED_DDR |= LED_mask;  //Set LED pins as outputs
  KEY_DDR &= ~KEY_MSK; //Set Key pins as inputs
  KEY_PORT |= KEY_MSK; //Enable internal pull-up resistor for Key pins
}

//Setup pin change interrupt used to wake from sleep
void init_pcint(void)
{
  GIMSK |= 1<<PCIE;  //Enale Pin Change Interrupt
  PCMSK |= 1<<PCINT0; //Watch for Pin Change on Pin5 (PB0)
      //NOTE:This needs to change if button is connected to a different uC pin
}

//Sleep function
void sleep_now(void)
{
  _delay_ms(500); 		//Delay to stop buttons from being read by mistake
  TIMSK0 &= ~(1<<TOIE0); 	//Turn off the overflow interrupt
  LED_DDR &= ~(LED_mask);	//Set Charlieples pins as inputs
  LED_PORT &= ~(LED_mask);	//Set these pins low
  init_pcint(); 		//setup pin change interrupt
}

//Pin Change Interrupt
ISR(PCINT0_vect)
{
  GIMSK &= ~(1<<PCIE); //Disable the interrupt so it doesn't keep flagging
  _delay_ms(500); //Wait arbitrary amount of time so button doesn't get read upon resuming execution
  init_timers(); //Start execution again and exit
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

js wrote:
Quote:
What is the best option for waking from sleep?
Make sure you are still breathing...many people forget to breath when they wake up... sorry :wink:

OK, it started...

The best option, is to do so, rather than not.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

The problem is the second time I try this the LEDs just blink off and then back on as if the PCINT0 isr is tripping right away.

Buttons bounce, don't forget.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, I've gotten all of the bugs out (I think). I can now put the device to sleep, in which it consumes about 1uA of current according to my multimeter. I can also wake it up again (which really is the important part right?) using a pin change interrupt on pin 5 (PCINT0).

For anyone seeking guidance the pertinent code is below. Just a note: The button is on PB0 (pin5) of the tiny13 and has the internal pull-up enabled.

void init_pcint(void)
{
  GIMSK |= 1<<PCIE;  //Enable Pin Change Interrupt
  PCMSK |= 1<<PCINT0; //Watch for Pin Change on Pin5 (PB0)
}

void sleep_now(void)
{
  cli();
  lights = 0; //Turn all lights off
  TIMSK0 &= ~(1<<TOIE0); 	//Turn off the overflow interrupt
  LED_DDR &= ~(LED_mask);	//Set Charlieplex pins as inputs
  LED_PORT &= ~(LED_mask);	//Set these pins low
  _delay_ms(500);
  init_pcint(); 		//setup pin change interrupt
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sei();
  sleep_mode();
  init_timers(); //Start execution again and exit
  _delay_ms(500); //Wait arbitrary amount of time so button doesn't get read upon resuming execution
}

//Pin Change Interrupt
ISR(PCINT0_vect)
{
  sleep_disable();
  GIMSK &= ~(1<<PCIE); //Disable the interrupt so it doesn't keep flagging
  PCMSK &= ~(1<<PCINT0);
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Take a look at the finished project. The shut-down and wake-up are working well. Thanks for all the help!

http://jumptuck.wordpress.com/2008/11/13/led-menorah-powered-by-avr-tiny13/

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I made Hack-a-day with this project:

http://hackaday.com/2008/11/13/improved-led-menorah/

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

stevech wrote:
js wrote:
Quote:
What is the best option for waking from sleep?
Make sure you are still breathing...many people forget to breathe when they wake up... sorry ;)

OK, it started...

The best option, is to do so, rather than not.


Booby trap your alarm clock so it gives you an electric shock when you try to turn the darned thing off. :lol:

Read this in Readers Digest: wife puts dog biscuits under sleeping hubby and then sends in the large dog to fetch them.

If you think education is expensive, try ignorance.