Interrupt execution delay

MCU attiny 804/814
internal Oscillator running at 20Mhz
Mills (Disabled ) , make no change even keeping Enable timer 0
Voltage 5V
Library / Board , MegaTinyCore "GitHub - SpenceKonde/megaTinyCore: Arduino core for the tinyAVR 0/1/2-series - this is any ATtiny with 2, 4, 6, or 7 in the 1's place, 0, 1, or 2 in the tens, and the flash size in the remaining digits. LIBRARY AUTHORS - Does your library have issues with this core? Please touch base w/me so we can ensure a solution that works on all parts and won't be broken by future changes"

i am trying to build Hazard indicators for bike with some patterns, i am using Attiny814 and custom made PCB to fit requirement.

i am trying to use interrupt for break switch left, right , break and pattern change. flashing patterns are design using delay function.

using external interrupt which should interrupt process immediately and start executing code in inside ISR but MY ISR (Switch) code gets executed only after completion of execution of pattern which can be 1 sec to 15 sec long.

i.e. if there is long pattern 1-15 second long and if i am pressing break or Indicator, new process get executed only completion of existing process (pattern which can take upto 15 second)

looking for help from forum
Code

const int leftLed =  6;//  Left LED
const int rightLed =  10;// Right LED
const int brake Switch = 2; // brake Switch
const int patternSwitch = 1; // Pattern
const int leftSwitch = 3; // left Indicator Switch
const int rightSwitch = 5; // Right Indicator Switch

volatile int patternNumber = 1;
volatile byte mode = 0;
volatile bool power_state = false;

void setup()
{
  noInterrupts();
  pinMode(leftLed, OUTPUT);
  pinMode(rightLed, OUTPUT);
  pinMode(brakeSwitch, INPUT);
  pinMode(patternSwitch, INPUT);
  pinMode(leftSwitch, INPUT);
  pinMode(rightSwitch, INPUT);
  attachInterrupt(digitalPinToInterrupt(brakeSwitch), brake_isr, CHANGE);
  attachInterrupt(digitalPinToInterrupt(patternSwitch), pattern_isr, CHANGE);
  attachInterrupt(digitalPinToInterrupt(leftSwitch), indicator_isr, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rightSwitch), indicator_isr, CHANGE);
  interrupts();

}

void loop()
{
  if (mode == 0)
  {
    pattern_run();
  }
  if (mode == 1)
  {
    brake_pattern();
    if (mode == 2)
    {
      indicator_isr();
    }
  }
}

void brake_isr()
{
  mode = 1;
  brake_pattern();
}
void brake_pattern()
{
  if (digitalRead(brakeSwitch) == HIGH)
  {
    digitalWrite(leftLed, HIGH);
    digitalWrite(rightLed, HIGH);
    delay(100);
    digitalWrite(leftLed, LOW);
    digitalWrite(rightLed, LOW);
    delay(100);

  }
  else if (digitalRead(brakeSwitch) == LOW)
  {
    digitalWrite(leftLed, LOW);
    digitalWrite(rightLed, LOW);
    mode = 0;
  }

  return;
}


void indicator_isr()
{
  if ((digitalRead(leftSwitch) == HIGH) && (digitalRead(rightSwitch) == LOW))
  {
    digitalWrite(leftLed, HIGH);
    digitalWrite(rightLed, LOW);
    delay(500);
    digitalWrite(leftLed, LOW);
    digitalWrite(rightLed, LOW);
    delay(500);
    mode = 2;
  }
  else if ((digitalRead(leftSwitch) == LOW) && (digitalRead(rightSwitch) == HIGH))
  {
    digitalWrite(leftLed, LOW);
    digitalWrite(rightLed, HIGH);
    delay(500);
    digitalWrite(leftLed, LOW);
    digitalWrite(rightLed, LOW);
    delay(500);
    mode = 2;
  }


}
void pattern_isr()
{
  if (digitalRead(patternSwitch) == HIGH)
  {
    delay(50);
    if (patternNumber >= 1 )
    {
      patternNumber = patternNumber + 1;
    }
    if (patternNumber >= 3)
    {
      patternNumber = 1;
    }

  }
  mode = 0;
  pattern_run();
}

void pattern_run()
{
  yield();
  if (patternNumber == 1)
  {
    digitalWrite(leftLed, HIGH);
    digitalWrite(rightLed, HIGH);
    delay(550);
    digitalWrite(leftLed, LOW);
    digitalWrite(rightLed, LOW);
    delay(550);
  }
  if (patternNumber == 2)
  {
    digitalWrite(leftLed, HIGH);
    digitalWrite(rightLed, HIGH);
    delay(90);
    digitalWrite(leftLed, LOW);
    digitalWrite(rightLed, LOW);
    delay(2000);
    digitalWrite(leftLed, HIGH);
    digitalWrite(rightLed, HIGH);
    delay(90);
    digitalWrite(leftLed, LOW);
    digitalWrite(rightLed, LOW);
    delay(2000);
  }
}

Hello, do yourself a favour and please read How to get the best out of this forum and modify your post accordingly (including code tags and necessary documentation of your ask).

please edit your post, select the code part and press the </> icon in the tool bar to mark it as code. It's barely readable as it stands. (also make sure you indented the code in the IDE before copying, that's done by pressing ctrlT on a PC or cmdT on a Mac)

Right, but only one interrupt can be processed at a time. All other interrupts have to wait until the active interrupt handler terminates. That's why usually an ISR only sets a flag that is handled subsequently in loop().

Please read the forum guidelines how to present code properly.

Your post was MOVED to its current location as it is more suitable.

Please follow the advice given in the link below when posting code , use code tags and post the code here to make it easier to read and copy for examination

Thanking You, that was very good advice.

Also, delay() does not work inside an ISR since it relies on interrupts which are OFF during the ISR.
Maybe something like this...

const int leftLed =  6;//  Left LED
const int rightLed =  10;// Right LED
const int breakSwitch = 2; // break Switch
const int patternSwitch = 1; // Pattern
const int leftSwitch = 3; // left Indicator Switch
const int rightSwitch = 5; // Right Indicator Switch

volatile int patternNumber = 1;
volatile byte mode = 0;
volatile bool power_state = false;

void setup()
{
  noInterrupts();
  pinMode(leftLed, OUTPUT);
  pinMode(rightLed, OUTPUT);
  pinMode(breakSwitch, INPUT);
  pinMode(patternSwitch, INPUT);
  pinMode(leftSwitch, INPUT);
  pinMode(rightSwitch, INPUT);
  attachInterrupt(digitalPinToInterrupt(breakSwitch), break_isr, CHANGE);
  attachInterrupt(digitalPinToInterrupt(patternSwitch), pattern_isr, CHANGE);
  attachInterrupt(digitalPinToInterrupt(leftSwitch), indicator_isr, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rightSwitch), indicator_isr, CHANGE);
  interrupts();

}

enum { RUN, BREAK, INDICATOR };

void loop()
{
  switch (mode) {
    case RUN:
      pattern_run();
      break;

    case BREAK:
      break_pattern();
      break;

    case INDICATOR:
      indicator_pattern();
      break;
  }
}


void break_isr()
{
  mode = BREAK;
}

void pattern_isr()
{
  if (digitalRead(patternSwitch) == HIGH)
  {
    patternNumber++;
    if (patternNumber >= 3) patternNumber = 1;
    mode = RUN;
  }
}

void indicator_isr()
{
  mode = INDICATOR;
}

void break_pattern()
{
  if (digitalRead(breakSwitch) == HIGH)
  {
    digitalWrite(leftLed, HIGH);
    digitalWrite(rightLed, HIGH);
    delay(100);
    digitalWrite(leftLed, LOW);
    digitalWrite(rightLed, LOW);
    delay(100);
  }
  else
  {
    digitalWrite(leftLed, LOW);
    digitalWrite(rightLed, LOW);
    mode = RUN;
  }
}


void indicator_pattern()
{
  if ((digitalRead(leftSwitch) == HIGH) && (digitalRead(rightSwitch) == LOW))
  {
    digitalWrite(leftLed, HIGH);
    digitalWrite(rightLed, LOW);
    delay(500);
    digitalWrite(leftLed, LOW);
    digitalWrite(rightLed, LOW);
    delay(500);
  }
  else if ((digitalRead(leftSwitch) == LOW) && (digitalRead(rightSwitch) == HIGH))
  {
    digitalWrite(leftLed, LOW);
    digitalWrite(rightLed, HIGH);
    delay(500);
    digitalWrite(leftLed, LOW);
    digitalWrite(rightLed, LOW);
    delay(500);
  }
}


void pattern_run()
{
  yield();
  if (patternNumber == 1)
  {
    digitalWrite(leftLed, HIGH);
    digitalWrite(rightLed, HIGH);
    delay(550);
    digitalWrite(leftLed, LOW);
    digitalWrite(rightLed, LOW);
    delay(550);
  }
  if (patternNumber == 2)
  {
    digitalWrite(leftLed, HIGH);
    digitalWrite(rightLed, HIGH);
    delay(90);
    digitalWrite(leftLed, LOW);
    digitalWrite(rightLed, LOW);
    delay(2000);
    digitalWrite(leftLed, HIGH);
    digitalWrite(rightLed, HIGH);
    delay(90);
    digitalWrite(leftLed, LOW);
    digitalWrite(rightLed, LOW);
    delay(2000);
  }
}

A further improvement would be to make the code more of a state machine and remove all those delay() calls. It would also allow you to get rid of all the interrupts and just read the state of the switches each time through loop() and still be responsive.

Hello blh64,

Will try suggestions you have given, thanking you for your advice.

Have a look at the Blink Without Delay example in the IDE (File->examples->02.digital->Blink Without Delay) as well as several things at the same time to learn how to break you code up so it doesn't try to do everything in a single pass through loop()

Not that it really matters, but it should be "brake". Unless you have a switch on the bike for when you are a bit tired and need a rest :slight_smile:

now that's call observation :slight_smile:

Hello
Do you have any need to do this job by using interrupts?

i just wanted execute new code/function immediately after pressing button, cannot wait other function to finish i.e. long blinking pattern. left right brake indicator should be instantaneous and that's whole purpose of using interrupt.

Or you could, of course, write your functions in a way that does not block loop() running freely which would allow the input to be read frequently without using an interrupt

upps,
I have not seen the usage of delay()´s.

Hello,
I have forgotten to give my recommendation:
In this case, I can only recommend to studying the IPO model.
Input: push buttons
Processing: starting and stopping the related timers
Output: LEDs

Thanking Everyone for your support, instead of delay i am using timer 0 now , similar like mills ( blink without delay) lot of changes simple flow turned into complex conditions but worth doing.

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