Using an interrupt to wake up Attiny13a

Hi, I’m trying to make a battery-powered flashlight using an Attiny13a. It would have multiple modes with different light intensities using PWM. It has a button that uses the external interrupt to switch between light intensities. I also plan to make another mode for it to randomly blink.
Since it’s battery-powered, I wanted it to go to sleep mode when it’s off, and I didn’t want to use another button. so I have to use one interrupt pin to switch between modes and go to sleep and wake up at the same time.

I came up with this code and obviously it didn’t work because I’m a newbie:
Edit: I’m having trouble to wake the micro up

#include <avr/sleep.h>


byte pwmval=0;
byte randtime=0;
byte button=0;
byte fade=1;
//byte buttonState = 1;
const uint8_t interruptPin = 1;

void setup() {
  // put your setup code here, to run once:
  pinMode(interruptPin, INPUT_PULLUP);
//  ADCSRA &= ~(1<<ADEN);
  attachInterrupt(digitalPinToInterrupt(interruptPin), Button, RISING);

}

void loop() {

  // put your main code here, to run repeatedly:

  if (button == 0){
    pwmval = 10;
    randtime = 1;
  }
  else if(button == 1){
    attachInterrupt(digitalPinToInterrupt(interruptPin), Button, LOW);
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_enable();
    sleep_mode();
    Button();
  }
  else if(button == 2){
    pwmval = 100;
    randtime = 1;
  }
  else if(button == 3){
    pwmval = 255;
    randtime=1;
  }
    analogWrite(0,pwmval);
    delay(randtime);
}
void Button(){
  sleep_disable();
  detachInterrupt(digitalPinToInterrupt(interruptPin));
  button += 1;
  if (button >= 4)
    button =0;
}

what am I doing wrong?

I’m using MicroCore by MCUdude.

How is the button wired? Did you include a decoupling cap across the MCU power pins and a pullup on /RESET?

There is no reason to attach/detach interrupts in loop().

Variables shared with interrupt routines must be declared volatile.

In this code, Button() is called twice in immediate succession, once during wakeup from sleep (as an interrupt routine), then immediately again. Is that intended?

    sleep_mode();
    Button();

How is the button wired? Did you include a decoupling cap across the MCU power pins and a pullup on /RESET?

I pulled up the pin6 with an 8.2k resistor and pin1 is not attached to anything.

There is no reason to attach/detach interrupts in loop().
Variables shared with interrupt routines must be declared volatile.

In this code, Button() is called twice in immediate succession, once during wakeup from sleep (as an interrupt routine), then immediately again. Is that intended?

I tried to run the code while attach/detach interrupts are in the setup like this:

void setup() {
  // put your setup code here, to run once:
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), Button, RISING);
  attachInterrupt(digitalPinToInterrupt(interruptPin), Button, LOW);
}

and I declared button as volatile.

volatile byte button=0;

and commented the call to Button() as it was unnecessary.

The results are the same.

pin1 is not attached to anything.

Not even to a grounded button?

The results are the same.

What does it do?

There is no reason for the Button function or for attach/detach. Just put the button code in loop() and for the interrupt routine, include the following line, which will simply wake up the MCU. I would also set the interrupt to FALLING.

ISR(INT0_vect) {};

The loop() function should read and debounce the button pin with short delays (try 20-30 msec). See the Arduino State Change example.

HOWEVER, have you been able to get anything at all to work with your ATtiny setup? The first thing I would do to verify basic operation is write a simple program that turns on and off an LED using the button. Use that effort to get debouncing to work correctly.

What does it do?

PWM signal lights up the LED(it can only be seen in dark) and when I press the button, LED turns off. if I press the button again or hold it at this point, nothing happens.

There is no reason for the Button function or for attach/detach. Just put the button code in loop() and for the interrupt routine, include the following line, which will simply wake up the MCU. I would also set the interrupt to FALLING.

I had this code witch worked and I tried to combine it with examples of sleep mode on the internet.

byte pwmval=0;
byte randtime=0;
byte button=0;
byte fade=1;
//byte buttonState = 1;
const uint8_t interruptPin = 1;

void setup() {
  // put your setup code here, to run once:
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), Button, RISING);

}

void loop() {

  // put your main code here, to run repeatedly:

  if (button == 0){
    pwmval = 0;
    randtime = 1;
  }
  else if(button == 1){
    pwmval = 100;
    Button();
  }
  else if(button == 2){
    pwmval = 200;
    randtime = 1;
  }
  else if(button == 3){
    pwmval = 255;
    randtime=1;
  }
    analogWrite(0,pwmval);
    delay(randtime);
}
void Button(){
  button += 1;
  if (button >= 4)
    button =0;
}

in this code, the Button function has another purpose, and it works perfectly as expected.

Strange bit of code. I would not recommend it as a model. Any idea what the author had in mind with this bit? I don't.

  else if(button == 1){
    pwmval = 100;
    Button();

Excellent tutorial on interrupts here: https://gammon.com.au/interrupts

The code above was intended to be like this(I wrote it):

byte pwmval=0;
byte randtime=0;
byte button=0;
byte fade=1;
//byte buttonState = 1;
const uint8_t interruptPin = 1;

void setup() {
  // put your setup code here, to run once:
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), Button, RISING);

}

void loop() {

  // put your main code here, to run repeatedly:

  if (button == 0){
    pwmval = 0;
    randtime = 1;
  }
  else if(button == 1){
    pwmval = 100;
    randtime = 1;
  }
  else if(button == 2){
    pwmval = 200;
    randtime = 1;
  }
  else if(button == 3){
    pwmval = 255;
    randtime=1;
  }
    analogWrite(0,pwmval);
    delay(randtime);
}
void Button(){
  button += 1;
  if (button >= 4)
    button =0;
}

And thank you for the tutorial.

Also, this is the tutorial I used for sleep mode https://donalmorrissey.blogspot.com/2010/04/putting-arduino-diecimila-to-sleep.html

Oh, I see. I was trying to use multiple interrupts on the same pin. now I have to ask is it even possible? if not what alternative solution do you suggest for this problem?

Hi I know it’s been a long time but here’s my code for anyone who’s having trouble waking up attiny13 from sleep:

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

const int buttonPin = 1; //setting button pin
const int ledPin =  0;  // setting LED pin

void setup() {
  pinMode(ledPin, OUTPUT);  // Sets LED as output
  pinMode(buttonPin, INPUT);  // Sets button as input
  digitalWrite(ledPin, HIGH);
  delay(1000);
  digitalWrite(ledPin, LOW);
  delay(1000);
  digitalWrite(ledPin, HIGH);
  delay(200);
  ADCSRA &= ~(1 << ADEN);
}
void loop() {
    if(digitalRead(buttonPin) == LOW){
      digitalWrite(ledPin, LOW);
      delay(200);
      system_sleep();
    }
}
void system_sleep(){
  sei();
  sleep_enable();
  attachInterrupt(digitalPinToInterrupt(buttonPin), pin2Interrupt, LOW);
  delay(100);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_mode();
  sleep_disable();
  delay(100);
  detachInterrupt(digitalPinToInterrupt(buttonPin));
  digitalWrite(ledPin, HIGH);
}
void pin2Interrupt(void){
}