External Pin Change Interrupt not working Instantly

Hi, I want to make a small circuit for my Bike Indicator. (1st button connect with Nano pin D11). (2nd button connect with Nano pin D12)
Here I install two buttons. One for Left indicator(connected with pin D9 of nano) to be flashed and other for led flashing (connected with pin D8 of nano) pattern change. But whenever I press the button for left indicator, the function occure after the led flashing patter fully completed. I need to run the left indicator to run instantly whenever i press the 1st button.

The Code is below:

schematic

/Name:chandrasekhar
developed for putting this pcb to bike for indicator flashing
contact t_tuku@yahoo.com
/

#define leftLedOn PORTB |= (1 << PB0)
#define leftLedOff PORTB &= ~(1 << PB0)
#define rightLedOn PORTB |= (1 << PB1)
#define rightLedOff PORTB &= ~(1 << PB1)

bool Flag = 0;
bool Flag1 = 0;

/FUNCTION PROTOTYPE/
void Breath(); void Hazard(); void Flasher1(); void Flasher2(); void LeftLedFlash();
void RightLedFlash(); void PoliceStrobe(); void LeftIndicator(); void RightIndicator();
/FUNCTION PROTOTYPE END/
volatile int counter = 0;

void setup() {
cli();
PCICR |= (1 << PCIE0);
PCMSK0 |= (1 << PCINT3) | (1 << PCINT4);

DDRB |= (1 << PB0) | (1 << PB1) ; //LEDs ARE CONNECTED TO PB0 AND PB1, GND IS COMMON

DDRB &= ~(1 << PB3) | ~(1 << PB4);//INPUT BUTTON ON PB3 AND PB4
PORTB |= (1 << PB3) | (1 << PB4); //ACTIVATE INPUT_PULLUP
sei();
}
void loop() {

if (counter == 1) {

RightLedFlash();

}
if (counter == 2) {

LeftLedFlash();

}
if (counter == 3) {

Flasher1();

}
if (counter == 4) {

Flasher2();

}
if (counter == 5) {

PoliceStrobe();

}

if (counter == 6) {

LeftIndicator();

}
}

ISR(PCINT0_vect)
{
if ((PINB & (1 << PB3)) && Flag == 0)
{
delay(25);
counter++;
if (counter > 5)counter = 1;
}

if ((PINB & (1 << PB4)) && Flag1 == 0)
{

counter = 6;

}

}

void Hazard() {
leftLedOn;
rightLedOn;
delay(500);
leftLedOff;
rightLedOff;
delay(500);
}
void Flasher1() {
LeftLedFlash();
LeftLedFlash();
LeftLedFlash();
LeftLedFlash();
delay(200);
RightLedFlash();
RightLedFlash();
RightLedFlash();
RightLedFlash();
delay(200);

}

void Flasher2() {
rightLedOn;
delay(50);
rightLedOff;
leftLedOn;
delay(50);
leftLedOff;
delay(300);
leftLedOn;
delay(50);
leftLedOff;
rightLedOn;
delay(50);
rightLedOff;
delay(300);
}
void LeftLedFlash() {
leftLedOn;
delay(50);
leftLedOff;
delay(50);

}
void RightLedFlash() {
rightLedOn;
delay(50);
rightLedOff;
delay(50);

}

void PoliceStrobe() {
for (int i = 0; i < 3; i++) {
LeftLedFlash();
}
for (int i = 0; i < 3; i++) {
RightLedFlash();
}
}

void LeftIndicator() {
leftLedOn;
delay(500);
leftLedOff;
delay(500);
}

void RightIndicator() {
rightLedOn;
delay(500);
rightLedOff;
delay(500);
}

Please read the sticky topics on top of the forum, how to present code. As you did it essential characters have been dropped from your text.

Don't use delay() and interrupts at the same time. Best do not use delay() any more. Else you may encounter (have already encountered) strange unexpected unwanted effects.

What you are doing would require no interrupts if you get rid of all delay() calls. If you use millis() for timing the loop() function would run often enough that polling the inputs would be plenty fast. Here is the using millis() for beginners tutorial.

Read the forum guidelines to see how to properly post code.
Use the IDE autoformat tool (ctrl-t or Tools, Auto format) before posting code in code tags.'

One way to fix the problem is to write your own bool myDelay() function that checks to see if 'counter' has changed while delaying and returns true immediately if it has:

bool myDelay(unsigned long milliseconds)
{
   unsigned long startTime = millis();
   while (millis() - startTime <= milliseconds)
  {
    if (counter != OldCounter)
      return true;
  }
  return false;
}

Then, in place of 'delay(x)' use:
if (myDelay(x)) return;

Thanks. But my problem is whenever i press the left indicator button, the code fully run in the main loop "for example Flasher(); function" then run the LeftIndicator() function. But I want to run the LeftIndicator() function instantly by stopping all running functions. Pls help me out.

Yes, we understand that, and the anwser is don't use delay(), use state machines and millis() for your sequencing of LEDs - check out the BlinkWithoutDelay example for instance.

If you use delay() everything else stops - which you don't want.

Explicit state variables will make everything possible, the state-machine approach pops everywhere there is interaction with the outside world you'll find.

I think that TaskMacros will help you a lot. All your LeftIndicator etc. functions become perfect tasks with little editing. E.g. replacing delay() by taskDelay() will make your functions non-blocking.

Try this to see if it does what you want:

const byte LeftLEDPin = 8; // PB0
const byte RightLEDPin = 9;  // PB1

const byte Button1Pin = 11; // PB3
const byte Button2Pin = 12; // PB4
int LastB1State = HIGH;
int LastB2State = HIGH;
unsigned long LastButtonChangeTime = 0;

volatile byte counter = 0;
byte OldCounter = 0;

bool myDelay(unsigned long milliseconds)
{
  unsigned long startTime = millis();
  while (millis() - startTime <= milliseconds)
  {
    if (counter != OldCounter)
      return true;
  }
  return false;
}

void setup()
{
  pinMode(LeftLEDPin, OUTPUT);
  pinMode(RightLEDPin, OUTPUT);

  pinMode(Button1Pin, INPUT_PULLUP);
  pinMode(Button2Pin, INPUT_PULLUP);

  // Enable Pin Change Interrupts on PB3 and PB4
  cli();
  PCICR |= (1 << PCIE0);
  PCMSK0 |= (1 << PCINT3) | (1 << PCINT4);
  sei();
}

void loop()
{
  OldCounter = counter;
  switch (OldCounter)
  {
    case 0: // No flashing
      digitalWrite(LeftLEDPin, LOW);
      digitalWrite(RightLEDPin, LOW);
      break;
      
    case 1: RightLedFlash(); break;
    case 2: LeftLedFlash(); break;
    case 3: Flasher1(); break;
    case 4: Flasher2(); break;
    case 5: PoliceStrobe(); break;
    case 6: LeftIndicator(); break;
    default: counter = 0;
  }
}

// Pin Change Interrupt on PB3 or PB4
ISR(PCINT0_vect)
{
  // Check Button1
  int b1 = digitalRead(Button1Pin);
  if (b1 != LastB1State && millis() - LastButtonChangeTime > 25)
  {
    // State Change Detected
    LastButtonChangeTime = millis();
    LastB1State = b1;

    if (b1 == LOW)
    {
      // Button just pressed
      counter++;
    }
  }

  // Check Button2
  int b2 = digitalRead(Button2Pin);
  if (b2 != LastB2State && millis() - LastButtonChangeTime > 25)
  {
    // State Change Detected
    LastButtonChangeTime = millis();
    LastB2State = b2;

    if (b2 == LOW)
    {
      // Button just pressed
      counter = 6;
    }
  }
}

void Hazard()
{
  digitalWrite(LeftLEDPin, HIGH);
  digitalWrite(RightLEDPin, HIGH);
  if (myDelay(500)) return;
  digitalWrite(LeftLEDPin, LOW);
  digitalWrite(RightLEDPin, LOW);
  if (myDelay(500)) return;
}

void Flasher1()
{
  LeftLedFlash();
  LeftLedFlash();
  LeftLedFlash();
  LeftLedFlash();
  if (myDelay(200)) return;
  RightLedFlash();
  RightLedFlash();
  RightLedFlash();
  RightLedFlash();
  if (myDelay(200)) return;

}

void Flasher2()
{
  digitalWrite(RightLEDPin, HIGH);
  if (myDelay(50)) return;
  digitalWrite(RightLEDPin, LOW);
  digitalWrite(LeftLEDPin, HIGH);
  if (myDelay(50)) return;
  digitalWrite(LeftLEDPin, LOW);
  if (myDelay(300)) return;
  digitalWrite(LeftLEDPin, HIGH);
  if (myDelay(50)) return;
  digitalWrite(LeftLEDPin, LOW);
  digitalWrite(RightLEDPin, HIGH);
  if (myDelay(50)) return;
  digitalWrite(RightLEDPin, LOW);
  if (myDelay(300)) return;
}
void LeftLedFlash()
{
  digitalWrite(LeftLEDPin, HIGH);
  if (myDelay(50)) return;
  digitalWrite(LeftLEDPin, LOW);
  if (myDelay(50)) return;

}
void RightLedFlash()
{
  digitalWrite(RightLEDPin, HIGH);
  if (myDelay(50)) return;
  digitalWrite(RightLEDPin, LOW);
  if (myDelay(50)) return;

}

void PoliceStrobe()
{
  for (int i = 0; i < 3; i++)
  {
    LeftLedFlash();
  }
  for (int i = 0; i < 3; i++)
  {
    RightLedFlash();
  }
}

void LeftIndicator()
{
  digitalWrite(LeftLEDPin, HIGH);
  if (myDelay(500)) return;
  digitalWrite(LeftLEDPin, LOW);
  if (myDelay(500)) return;
}

void RightIndicator()
{
  digitalWrite(RightLEDPin, HIGH);
  if (myDelay(500)) return;
  digitalWrite(RightLEDPin, LOW);
  if (myDelay(500)) return;
}

where to get the code of taskDelay.?? could u pls let me know?

thanks @Johnwasser for replay. Sorry I was in some other works and could not tried. Now i am trying the code that you have given myDelay.. With this function the circuits works but after some time the circuit halt and did not response anything... pls. reply

Hello
Post your sketch in code tags "</>" to be found in this editor.

#define leftLedOn PORTB |= (1 << PB0)
#define leftLedOff PORTB &= ~(1 << PB0)
#define rightLedOn PORTB |= (1 << PB1)
#define rightLedOff PORTB &= ~(1 << PB1)
uint8_t brightness = 0;    // how bright the LED is
uint8_t fadeAmount = 5;

bool PINB2State = LOW;
bool PINB3State = LOW;
bool PINB4State = LOW;
unsigned char LastButtonChangeTime = 0;

volatile byte counter = 0;
byte OldCounter = 0;


void setup()
{
  DDRB |= (1 << PB0) | (1 << PB1) ; //LEDs ARE CONNECTED TO PB0 AND PB1, GND IS COMMON
  DDRB &= ~((1 << PB2) | (1 << PB3) | (1 << PB4)); //INPUT BUTTON ON PB3,PB4& PB2
  PORTB |= (1 << PB2) | (1 << PB3) | (1 << PB4); //ACTIVATE INPUT_PULLUP

  // Enable Pin Change Interrupts on PB3 and PB4
  cli();
  GIMSK |= (1 << PCIE);
  PCMSK |= (1 << PCINT2) | (1 << PCINT3) | (1 << PCINT4);
  sei();
}

void loop()
{
  OldCounter = counter;
  switch (OldCounter)
  {
    case 1: // No flashing
      leftLedOff;
      rightLedOff;
      break;
    case 2: Flasher2(); break;
    case 3: Flasher3(); break;
    case 4: Flasher4(); break;
    case 5: Flasher5(); break;
    case 6: Flasher6(); break;
    case 7: Flasher7(); break;
    case 8: Flasher11(); break;
    case 9: Flasher8(); break;
    case 10: Flasher9(); break;
    case 11: Flasher10(); break;
    case 12: LeftIndicator; break;
    case 13: RightIndicator; break;
    default: Flasher1();
  }
}

// Pin Change Interrupt on PB3 or PB4
ISR(PCINT0_vect)
{
  //for PB2 button
  if (!(PINB & (1 << PINB2)) && !PINB2State && millis() - LastButtonChangeTime > 20 && counter != 11)
  {
    counter = 11;
  }
  else if (!(PINB & (1 << PINB2)) &&  counter != 13  && millis() - LastButtonChangeTime > 20 )
  {
    counter = 13;
  }

  //for PB3 button
  if (!(PINB & (1 << PINB3)) && !PINB3State && millis() - LastButtonChangeTime > 20 && counter != 12)
  {
    counter = 12;
  }
  else if (!(PINB & (1 << PINB3)) && counter != 13 && millis() - LastButtonChangeTime > 20 )
  {
    counter = 13;
  }
  
  //for PB4 button
  if (!(PINB & (1 << PINB4)) && !PINB4State && millis() - LastButtonChangeTime > 20)
  {
    counter++;
    if (counter > 10)counter = 1;
  }
}

void Flasher1() {
  analogWrite(PB0, brightness);
  analogWrite(PB1, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) {

    fadeAmount = -fadeAmount;
    if (brightness == 0)   delay(2000) ;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(50) ;
}
void Flasher2()
{
  leftLedOn;  rightLedOn;     delay(500) ;
  leftLedOff; rightLedOff;    delay(500) ;
}
void Flasher3()
{
  LeftLedFlash();   LeftLedFlash();   LeftLedFlash();      LeftLedFlash();    delay(200) ;
  RightLedFlash();  RightLedFlash();  RightLedFlash();     RightLedFlash();   delay(200) ;
}

void Flasher4()
{
  LeftLedFlash();  LeftLedFlash();    delay(1000) ;
  RightLedFlash(); RightLedFlash();   delay(1000) ;
}
void Flasher5()
{
  LeftLedFlash();     delay(80);
  LeftLedFlash();     delay(1000) ;
  RightLedFlash();  delay(80) ;
  RightLedFlash();  delay(1000) ;
}

void Flasher6()
{
  LeftLedFlash();      RightLedFlash();      delay(60) ;
  LeftLedFlash();      RightLedFlash();     delay(500) ;
}
void Flasher7()
{
  rightLedOn;  leftLedOn;  delay(50) ;
  rightLedOff; leftLedOff; delay(50) ;
  rightLedOn;  leftLedOn;  delay(50) ;
  rightLedOff; leftLedOff; delay(500) ;
}
void Flasher8()
{
  rightLedOn;      delay(50) ;
  rightLedOff;     leftLedOn;      delay(100) ;
  leftLedOff;      rightLedOn;     delay(50) ;
  rightLedOff;     leftLedOn;      delay(100) ;
  leftLedOff;      rightLedOn;     delay(50) ;
  rightLedOff;     delay(1500) ;
}
void Flasher9()
{
  for ( uint8_t i = 0; i < 3; i++)
  {
    leftLedOn;    delay(50) ;   leftLedOff;    delay(50) ;
  }
  for (uint8_t i = 0; i < 3; i++)
  {
    rightLedOn;   delay(50) ;   rightLedOff;    delay(50) ;
  }
}
void Flasher10()
{
  leftLedOn;    delay(50) ;    leftLedOff;
  rightLedOn;   delay(50) ;    rightLedOff;
  delay(2000) ;
}

void Flasher11()
{
  leftLedOn; rightLedOn;   delay(50) ;  leftLedOff;  rightLedOff;
  delay(3000) ;
}
void LeftLedFlash()
{
  leftLedOn;  delay(30) ;  leftLedOff;  delay(30) ;
}
void RightLedFlash()
{
  rightLedOn;  delay(30) ;
  rightLedOff; delay(30) ;
}
void LeftIndicator()
{
  rightLedOff;
  leftLedOn;  delay(500) ;
  leftLedOff; delay(500) ;
}
void RightIndicator()
{
  leftLedOff;
  rightLedOn;  delay(500) ;
  rightLedOff; delay(500) ;
}

See the Flasher1() function just fade in and fade out the leds. My problem is whenever I press the PB2 or PB3 or PB4 the led effect should change as per the counter in that sequence. But due to delay in the main loop the code run until the loop completed and then run the next counter. But I want to change it Instantly so i use ISR. But not get result. Otherwise i could have simply use code other than ISR to get the effect change.
Pls help me to get out my problem.

Hello
The usage of an interrupt will not help.
When the ISR is finshed you will stay inside the delay() function until the delay time is over.
General spoken there is no need for the interrupt bussiness. You may redesign your sketch using a botton handler, a time handler to prevent the usage of delay and a smart FSM.
I hope this will help.
Have a nice day and enjoy coding.

@johnwasser gave you a perfectly good working sketch in reply #8 that didn't use interrupts and doesn't use all the direct port manipulation, etc. so it a lot easier to read. Why have you gone back to your old, broken code?

Are you using the sketch exactly as I wrote it? If you have made ANY changes, please post the version you are testing.

@blh64 thanx for replay. I am bound to use direct port manipulation coz i am using attiny13 and its memory size 1kb. also it does not accept all arduino code like digitalread or write etc.

pls where to get about button handler and time handler.. ??

//Name:chandrasekhar//
//developed for putting this pcb to bike for indicator flashing//
//contact t_tuku@yahoo.com//

#define leftLedOn PORTB |= (1 << PB0)
#define leftLedOff PORTB &= ~(1 << PB0)
#define rightLedOn PORTB |= (1 << PB1)
#define rightLedOff PORTB &= ~(1 << PB1)
unsigned long LastButtonChangeTime = 0;
volatile byte counter = 0;
byte OldCounter = 0;

bool PINB2State = LOW;
bool PINB3State = LOW;
bool PINB4State = LOW;


void setup()
{

  DDRB |= (1 << PB0) | (1 << PB1) ; //LEDs ARE CONNECTED TO PB0 AND PB1, GND IS COMMON
  DDRB &= ~((1 << PB2) | (1 << PB3) | (1 << PB4)); //INPUT BUTTON ON PB3,PB4& PB2
  PORTB |= (1 << PB2) | (1 << PB3) | (1 << PB4); //ACTIVATE INPUT_PULLUP
  cli();
  PCICR |= (1 << PCIE0);
  PCMSK0 |= (1 << PCINT2) | (1 << PCINT3) | (1 << PCINT4);
  sei();
}

void loop() {
  OldCounter = counter;
  switch (OldCounter)
  {
    case 1:
      Flasher2();      break;
    case 2:
    //  Flasher1();      break;
    case 3:
      Flasher3();      break;
    case 4:
      Flasher4();      break;
    case 5:
      Flasher5();      break;
    case 6:
      Flasher6();      break;
    case 7:
      Flasher7();      break;
    case 8:
      Flasher8();      break;
    case 9:
      Flasher9();      break;
    case 10:
      Flasher10();     break;
    case 11:
      LeftIndicator(); break;
    case 12:
      RightIndicator(); break;
    case 13:
      leftLedOff;  rightLedOff;  break;
    default:
      Flasher11();     break;
  }

}

ISR(PCINT0_vect)
{
  //for PB2 button
  if (!(PINB & (1 << PINB2)) && !PINB2State && millis() - LastButtonChangeTime > 20 && counter != 11)
  {

    counter = 11;
  }
 else if (!(PINB & (1 << PINB2)) &&  counter != 13  && millis() - LastButtonChangeTime > 20 )
  {

    counter = 13;
  }





  //for PB3 button
  if (!(PINB & (1 << PINB3)) && !PINB3State && millis() - LastButtonChangeTime > 20 && counter != 12)
  {
    counter = 12;

  }
 else if (!(PINB & (1 << PINB3)) && counter != 13 && millis() - LastButtonChangeTime > 20 )
  {

    counter = 13;
  }


  //for PB4 button
  if (!(PINB & (1 << PINB4)) && !PINB4State && millis() - LastButtonChangeTime > 20)
  {
    counter++;
    if (counter > 10)counter = 1;
  }

}




void Flasher2()
{
  leftLedOn;  rightLedOn;     delay(500) ;
  leftLedOff; rightLedOff;    delay(500) ;
}
void Flasher3()
{
  LeftLedFlash();   LeftLedFlash();   LeftLedFlash();      LeftLedFlash();    delay(200) ;
  RightLedFlash();  RightLedFlash();  RightLedFlash();     RightLedFlash();   delay(200) ;
}

void Flasher4()
{
  LeftLedFlash();  LeftLedFlash();    delay(1000) ;
  RightLedFlash(); RightLedFlash();   delay(1000) ;
}
void Flasher5()
{
  LeftLedFlash();     delay(80) ;
  LeftLedFlash();     delay(1000) ;
  RightLedFlash();  delay(80) ;
  RightLedFlash();  delay(1000) ;
}

void Flasher6()
{
  LeftLedFlash();      RightLedFlash();      delay(60) ;
  LeftLedFlash();      RightLedFlash();     delay(500) ;
}
void Flasher7()
{
  rightLedOn;  leftLedOn;  delay(50) ;
  rightLedOff; leftLedOff; delay(50) ;
  rightLedOn;  leftLedOn;  delay(50) ;
  rightLedOff; leftLedOff; delay(500) ;
}
void Flasher8()
{
  rightLedOn;      delay(50) ;
  rightLedOff;     leftLedOn;      delay(100) ;
  leftLedOff;      rightLedOn;     delay(50);
  rightLedOff;     leftLedOn;      delay(100) ;
  leftLedOff;      rightLedOn;     delay(50) ;
  rightLedOff;     delay(1500) ;
}
void Flasher9()
{
  for (int i = 0; i < 3; i++)
  {
    leftLedOn;    delay(50) ;   leftLedOff;    delay(50) ;
  }
  for (int i = 0; i < 3; i++)
  {
    rightLedOn;   delay(50) ;   rightLedOff;    delay(50) ;
  }
}
void Flasher10()
{
  leftLedOn;    delay(50) ;    leftLedOff;
  rightLedOn;   delay(50) ;    rightLedOff;
  delay(2000) ;
}

void Flasher11()
{
  leftLedOn; rightLedOn;   delay(50) ;  leftLedOff;  rightLedOff;
  delay(3000) ;
}
void LeftLedFlash()
{
  leftLedOn;  delay(30) ;  leftLedOff;  delay(30) ;
}
void RightLedFlash()
{
  rightLedOn;  delay(30) ;
  rightLedOff; delay(30) ;
}
void LeftIndicator()
{
  rightLedOff;
  leftLedOn;  delay(500) ;
  leftLedOff; delay(500) ;
}
void RightIndicator()
{
  leftLedOff;
  rightLedOn;  delay(500) ;
  rightLedOff; delay(500) ;
}

this is the code.

Then buy a nano. They are cheap, small, and support all of the IDE.
Get that code working.
Understand how it works.
Translate it to the tiny13.

It will be a much more pleasant journey

1 Like

I have a nano. I am using it as ISP programmer. I know how to translate it to attiny13. But the problem is with delay function. How to overcome it, i dont know