attachinterrupt not working as expected on Attiny85

Hi,
I am trying to put together a simple program on Attiny85 that beeps twice if a tactile switch goes from Off to On, and beeps 3 times if it goes from On to Off. Looks nothing complicated, but it does not work. When the switch goes from Off to On it beeps 4 times instead of expected two. When switch goes from On to Off - it beeps 3 times as expected. Am I missing something specific to Attiny85 here?

const byte doorOpenLED = 0;
const byte OnOffSwitchPin = 2;
const byte speakerPin = 1;
int mySound = 1400;
volatile bool xInterrupted = false;

// Interrupt Service Routine (ISR)
void switchPressed ()  {  xInterrupted = true;  }  

void setup ()
{
  pinMode      (doorOpenLED, OUTPUT);           // so we can update the LED
  digitalWrite (doorOpenLED, LOW);
  digitalWrite (OnOffSwitchPin, HIGH);          // internal pull-up resistor for debounce
  delay(1000);
  attachInterrupt (0, switchPressed, CHANGE);   // attach interrupt (INT0) handler on pin D2
}  // end of setup

void loop ()
{   
  if (xInterrupted)
  {
    xInterrupted = false;
    delay(300);
    if (digitalRead (OnOffSwitchPin) == LOW)       // tactile switch ON 
    {
     digitalWrite(doorOpenLED, HIGH);
     tone(speakerPin, mySound, 200);     // play a note on pin 1 for 200 ms:
     delay(400);
     tone(speakerPin, mySound, 200);
     delay(3000);
    }
    else
    {  
     digitalWrite(doorOpenLED, LOW);
     tone(speakerPin, mySound, 200);
     delay(300);
     tone(speakerPin, mySound, 200);
     delay(300);
     tone(speakerPin, mySound, 200);
    }
  }
  
}

Think about it. You have all of those delays. Pressing or letting go of the button during one of those delays may give you unexpected results because the button may have actually gone through 2 changes but you only have one flag. Why use an interrupt at all? Your code would be much more readable/understandable/debuggable if you just polled the switch and reacted to a change in the loop() function.

Thanks! Thing is that I do not touch the switch until I hear the beeps. Sure I can poll the switch without using interrupt. I thought it would be easier to do it with interrupts.

You could do something like this:

const byte doorOpenLED = 0;
const byte OnOffSwitchPin = 2;
const byte speakerPin = 1;
const int mySound = 1400;
byte lastSwitchState;

void setup ()
{
  pinMode (doorOpenLED, OUTPUT);           // so we can update the LED
  digitalWrite (doorOpenLED, LOW);
  pinMode (OnOffSwitchPin, INPUT_PULLUP);          // internal pull-up resistor for debounce
  lastSwitchState = digitalRead (OnOffSwitchPin);
}  // end of setup

void loop ()
{   
  byte switchState = digitalRead (OnOffSwitchPin);
  
  if (switchState != lastSwitchState)
  {
    lastSwitchState = switchState;
    if (switchState == LOW)       // tactile switch ON
    {
     digitalWrite(doorOpenLED, HIGH);
     tone(speakerPin, mySound, 200);     // play a note on pin 1 for 200 ms:
     delay(400);
     tone(speakerPin, mySound, 200);
    }
    else
    { 
     digitalWrite(doorOpenLED, LOW);
     tone(speakerPin, mySound, 200);
     delay(300);
     tone(speakerPin, mySound, 200);
     delay(300);
     tone(speakerPin, mySound, 200);
    }
  }
}

Also, if you used a counter for the number of beeps and millis() instead of delay you could monitor the switch must faster but that may not be helpful for this application; however, if your program needs to do other functions then it could not do them while blocked by a delay().

Here are some helpful links on how to use millis() instead of delay:

BlinkWithoutDelay

Arduino Multiple Things

Several Things at a Time

I recall doing something similar a while ago with the Attiny 85 and I too used Pin PB1 and could not get it to work, I had to use PB0

// ATMEL ATTINY 25/45/85 / ARDUINO
//
// +-/-+
// Ain0 (D 5) PB5 1| |8 Vcc
// Ain3 (D 3) PB3 2| |7 PB2 (D 2) Ain1
// Ain2 (D 4) PB4 3| |6 PB1 (D 1) pwm1
// GND 4| |5 PB0 (D 0) pwm0
// +----+

@ToddL1962, thanks for the example.
I still want to understand why my sketch is not working as expected. I moved delays out of the ISR as advised in many threads. But I never came accross advice to avoid using delay in the main loop.
Could it be the reason that switch debouncing with internal pull-up resistor is not working reliably enough? However I am puzzled that in fact 2 times 2 beeps sound when there is Off-to-On transition. On the opposite transition the sketch sounds one sequence of 3 beeps as expected.

acode777:
I had to use PB0 ...

Don't you have to use PB2? This is the only pin on 85 that handles INT0 interrupts.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.