Arduino button interrupts is not working

Hello everyone,

The project is base on multiple led effects. We can switch the effects by pushing button. So i added an interrupts to the button. I written some code for it but its the interrups is not working.
This is the simulation on tinkercad. please help me to fixed the code.

CODE:

int LED[] = {12, 11, 10, 9, 8};

int     button_switch =                       2; // external interrupt pin
int 	counter = 0;
#define switched                            true // value if the button switch has been pressed
#define triggered                           true // controls interrupt handler
#define interrupt_trigger_type            CHANGE // interrupt triggered on a RISING input
#define debounce                   20 // time to wait in milli secs

volatile  bool interrupt_process_status = {
  !triggered                                     // start with no switch press pending, ie false (!triggered)
};
bool initialisation_complete =            false; // inhibit any interrupts until initialisation is complete
unsigned long previous[] = {0, 0};
const long interval[] = {100, 200};
//
// ISR for handling interrupt triggers arising from associated button switch
//
void button_interrupt_handler()
{
  if (initialisation_complete == true)
  { //  all variables are initialised so we are okay to continue to process this interrupt
    if (interrupt_process_status == !triggered) {
      // new interrupt so okay start a new button read process -
      // now need to wait for button release plus debounce period to elapse
      // this will be done in the button_read function
      if (digitalRead(button_switch) == HIGH) {
        // button pressed, so we can start the read on/off + debounce cycle wich will
        // be completed by the button_read() function.
        interrupt_process_status = triggered;  // keep this ISR 'quiet' until button read fully completed
      }
    }
  }
} // end of button_interrupt_handler

bool read_button() {
  int button_reading;
  // static variables because we need to retain old values between function calls
  static bool     switching_pending = false;
  static long int elapse_timer;
  if (interrupt_process_status == triggered) {
    Serial.print("Interrupt");
    // interrupt has been raised on this button so now need to complete
    // the button read process, ie wait until it has been released
    // and debounce time elapsed
    button_reading = digitalRead(button_switch);
    if (button_reading == HIGH) {
      // switch is pressed, so start/restart wait for button relealse, plus end of debounce process
      switching_pending = true;
      elapse_timer = millis(); // start elapse timing for debounce checking
    }
    if (switching_pending && button_reading == LOW) {
      // switch was pressed, now released, so check if debounce time elapsed
      if (millis() - elapse_timer >= debounce) {
        // dounce time elapsed, so switch press cycle complete
        switching_pending = false;             // reset for next button press interrupt cycle
        interrupt_process_status = !triggered; // reopen ISR for business now button on/off/debounce cycle complete
        return switched;                       // advise that switch has been pressed
      }
    }
  }
  return !switched; // either no press request or debounce period not elapsed
} // end of read_button function

void setup() {
  for (int i=0; i < 5;i++){
  pinMode(LED[i], OUTPUT);  
  }
  
  pinMode(button_switch, INPUT);
  attachInterrupt(digitalPinToInterrupt(button_switch),
                  button_interrupt_handler,
                  interrupt_trigger_type);
  initialisation_complete = true; // open interrupt processing for business
Serial.begin(9600);
} // end of setup function


void loop() {
  unsigned long currentMillis = 0;
  int i=0;
  if (read_button() == switched) {
    counter++;
    Serial.println(counter);
  } else {
    switch(counter){
  case 1:
    Serial.println("s1");
     
      while(i < 5){
        currentMillis = millis();
        if (currentMillis - previous[0] >= interval[0]) {
          Serial.println(currentMillis);
    previous[0] = currentMillis;  
  digitalWrite(LED[i], HIGH); 
          i++;
      }
  }
   i = 0;   
      while( i < 5){
        currentMillis = millis();
        if (currentMillis - previous[1] >= interval[1]) {
          Serial.println(currentMillis);
    previous[1] = currentMillis;  
  digitalWrite(LED[i], LOW); 
          i++;
      }
  }
    break;
  case 2:
      Serial.println("s2"); 
    break;
  case 3:
    Serial.println("s3");
    break;
  default:
    counter = 0;
  break;
  }

  }
}


if you want to debug how the interrupt works, first leave only the interrupt in the code, without all this mess with a functions with leds and millis. When the interrupt works - gradually add everything else.

2 Likes

Slow operating switches need only be scanned every 50ms.

Interrupts are meant for use with very fast events and almost never needed.

2 Likes

I have no idea why you think that this is related to Interfacing w/ Software on the Computer. Hence your topic has been moved to a more suitable location on the forum.

Thanks for using code tags in your first post :+1:

Using interrupts call for considerable knowledge and is not needed for checking buttons. It most often only create severe difficulties.

1 Like

A couple of compile warnings:

/Users/john/Documents/Arduino/sketch_oct09a/sketch_oct09a.ino: In function 'void loop()':
/Users/john/Documents/Arduino/sketch_oct09a/sketch_oct09a.ino:112:43: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
           if (currentMillis - previous[0] >= interval[0])
               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~
/Users/john/Documents/Arduino/sketch_oct09a/sketch_oct09a.ino:125:43: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
           if (currentMillis - previous[1] >= interval[1])
               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~

Try using 'unsigned' or 'unsigned long':
const long interval[] = {100, 200};

Also, this should be 'unsigned long int' because that is the type that millis() returns:
static long int elapse_timer;

1 Like

Thanks for your reply. :slight_smile:

I tried the interrupt code and it working but when I added the while loop in it I written some led effect code. So when I press the button, the effect is not changing.

I don't know why the interrupt is not working.

Thanks for your reply. :slight_smile:

I used interrupt here because later I will add multiple led effects, but the problem is when I run the code the led effect kept running in a loop. I'm not able to switch the mode that's why, I decided to add interrupts. So whenever the interrupt happens, the effect stop and changes to a different effect. This is what I'm trying to do.

I don't know why the interrupt is not working.

With this while loop your interrupt is completely useless:

Your code do not check the button until the loop finished.

If you want to change effect before it finished - you have to check interrupt state inside the loop

1 Like

Thanks for your reply. :slight_smile:

I tried it but its not working. whenever I press the push button the effect is not changing. IDK what is the problem.

Can you please help me with that IDK where should I add the interrupt state.

try

while ((i<5) && (switched != read_button()))
1 Like
  • Tell us what you think this is doing:
volatile  bool interrupt_process_status = {
  !triggered                                     // start with no switch press pending, ie false (!triggered)
};
  • Confirm you are only using simple LEDs and you are using this circuit ?

2022-10-19_0-31-49

Here is something you can play with:


// https://forum.arduino.cc/t/arduino-button-interrupts-is-not-working/1043406

//********************************************^************************************************
// Version    YY/MM/DD    Description
// 1.00       22/10/19    Running sketch
//
//

#define CLOSED                        HIGH
#define OPENED                        LOW

#define LEDon                         HIGH
#define LEDoff                        LOW

const byte heartbeatLED             = 13;

const byte LED[]                    = {12, 11, 10, 9, 8}; //Pin---[220R]---[A>|K]---GND

const byte button_switch            = 2;                  //5V---[Switch]---Pin---[10k]---GND

byte index                          = 0;
byte lastButton_switchState;

unsigned long heartbeatTime;
unsigned long switchTime;
unsigned long commonTime;
unsigned long interval0             = 100ul;
unsigned long interval1             = 200ul;

//State Machine states
enum States {State0, State1, State2, State3, State4};
//States mState = State0;

int  counter                        = State0;

//********************************************^************************************************
void setup()
{
  Serial.begin(9600);

  pinMode(heartbeatLED, OUTPUT);

  for (int i = 0; i < 5; i++)
  {
    pinMode(LED[i], OUTPUT);
  }

  pinMode(button_switch, INPUT);

} // end of setup function


//********************************************^************************************************
void loop()
{
  //*************************************                          h e a r t b e a t   T I M E R
  //to see if the sketch is blocking,
  //toggle the heartbeat LED every 500ms
  if (millis() - heartbeatTime >= 500)
  {
    //restart the TIMER
    heartbeatTime = millis();

    //toggle the LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
  }

  //*************************************                          s w i t c h   T I M E R
  //is it time to check the switches ? every 50ms
  if (millis() - switchTime >= 1)
  {
    //restart the TIMER
    switchTime = millis();

    //go and check the switches
    checkSwitches();
  }

  //*************************************
  //check our State Machine
  checkMachine();


  //*************************************
  //other non blocking code goes here
  //*************************************

} //END of   loop()


//********************************************^************************************************
void checkMachine()
{
  switch (counter)
  {
    //**********************
    case State0:
      {
        //do nothing
      }
      break;

    //**********************
    case State1:
      if (millis() - commonTime >= interval0)
      {
        digitalWrite(LED[index], LEDon);

        //restart the TIMER
        commonTime = millis();

        index++;

        //have all the LEDs been dealt with ?
        if (index > 4)
        {
          index = 0;
        }
      }
      break;

    //**********************
    case State2:
      {
        if (millis() - commonTime >= interval1)
        {
          digitalWrite(LED[index], LEDoff);

          //restart the TIMER
          commonTime = millis();

          index++;

          //have all the LEDs been dealt with ?
          if (index > 4)
          {
            index = 0;
          }
        }
      }
      break;

    //**********************
    case State3:
      {

      }
      break;

    //**********************
    case State4:
      {

      }
      break;

  } //END   switch/case

} //END of   checkMachine()


//********************************************^************************************************
void checkSwitches()
{
  //*********************************************                    b u t t o n _ s w i t c h
  //button_switch code
  byte currentState = digitalRead(button_switch);

  //**********************
  //was there a change in state ?
  if (lastButton_switchState != currentState)
  {
    //update to the new state
    lastButton_switchState = currentState;

    //**********************
    //is the switch closed ?
    if (currentState == CLOSED)
    {
      //next animation
      counter++;

      //are we finished ?
      if (counter > State2)            // <-----<<<<  match the number of animations
      {
        //back to the beginning
        counter = State0;
      }

      Serial.println(counter);

      //point to the first LED
      index = 0;

      //restart the TIMER
      commonTime = millis();

    }

  } //END of  button_switch code

} //END of   checkSwitches()


//********************************************^************************************************
1 Like

Thank you so much :heart_eyes: . Its worked but there is one more problem occur which I aready fixed it.

When you want to say thanks for somebody in the forum - you can use likes.
And if your problem is solved - mark most useful comment as "Solution"

Thank you so much all of you. :heart_eyes:

BTW @b707 I got it.

Thank you for the code. :heart_eyes:

Notice that interrupts were not needed!

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