Solved: Help with interrupts

Hi everyone!

Hardware setup: I have a series of LEDs connected to a breadboarded 328mPU (with the arduino bootloader burned to it), which also has a simple push to make switch (like this one) connected from digital pin 3 to ground. The pull-up resistor for pin 3 is enabled.

Aim: When powered on, the chip causes the LEDs to flash in a pretty pattern. I want to be able to push the button, and have the lights change pretty much instantaneously to flash in a different pattern.

Soooo... I figured it would probably be best to use an external interrupt to achieve this. I created the code shown at the end of the post.

The problem: My interrupt seems to work intermittently at best. Sometimes I'll press the button and the flash pattern will change at the end of the sequence (i.e. before it loops round and starts again... but sometimes it will carry on with the same pattern, even though I know the interrupt fired (by including a short code segment to make 1 led flash when the interrupt fires).

The code:

#include <avr/interrupt.h>

volatile int flashmode = 1;
int buttonpin = 3;
boolean inReset = false;

void setup() {
  attachInterrupt(1, interrupt, LOW);
  // Set all the pins I'm using for the LEDs to output
  pinMode(buttonpin,INPUT);
  digitalWrite(buttonpin, HIGH);
}

void loop() {
  if (inReset) {
    inReset = false;
  }
  if (flashmode == 3) {
      flashmode = 1;
  }
  if (flashmode == 1) {
    // Start flash pattern 1. Timing for flashes managed using delay().
  } else {
    // flashmode must be 2, so start flash pattern 2. Similar to 1, timing of flashes managed using delay().
  }
}

void interrupt()
{
  flashmode++;
  if (flashmode == 3) {
      flashmode = 1;
  }
  inReset = true;
}

The references to inReset are my attempts to cause void_loop() to restart after the interrupt has fired, as per information from this thread

Is it possible for the interrupt trigger to be to quick? Will the interrupt only run when the interrupt conditions are met? Because, with this style of button I logically assume that unless one holds the button down, it will produce the FALLING, LOW and RISING signals within a very short interval.

Anyway, I have no real idea what the problem is, or how to solve it. Any help or suggestions would be very much appreciated!

ZeroCool42

You really just need to not use delay. There may be some silly hack where you have a goto or modify the delay function to check for the button, but modifying your light sequence to become a state machine is the most scaleable and best result.

Hi WizenedEE,

Thank you very much for taking the time to read to reply! I don't quite understand what you mean by a state machine... do you mean like the Blink Without Delay example?

Many thanks in advance!

ZeroCool42

Yes, a lot like that. Here's something to get you going:

void setup() {
  pinMode(13, OUTPUT);
}

const byte sequence[] = {0, 2, 3, 1, 0, 3, 2, 0, 1};
const unsigned long delayTime = 1000;
const size_t sequencelen = sizeof(sequence)/sizeof(sequence[0]);

void loop() {
  static int statenum = 0;
  unsigned long curTime = millis();
  static unsigned long baseTime = 0;
  
  if (curTime - baseTime > delayTime) {
    baseTime = curTime;
    statenum = (statenum + 1) % sequencelen;
  }
  switch(sequence[statenum]) {
  case 0:
    digitalWrite(13, HIGH);
    break;
  case 1:
    digitalWrite(13, LOW);
    break;
  case 2:
    digitalWrite(13, HIGH);
    break;
  case 3:
    digitalWrite(13, LOW);
    break;
  }
}

Many thanks for this! I shall pore through this code and modify my own accordingly! :slight_smile: