2

I need an answer fast.I want to make a keyboard class to handle a few buttons attached to my arduino. I want to use interrupts.The problem is I have to use the same interrupt function for all my buttons(it would beimpractical to create a routine for each button).So inside the routine I must know at least what pin fired the interrupt. How can I solve this?(I belive it can be solved by changing some registers but that would be too complicated).PS:there are only two buttons(pins 2 and 3 are enough)

Edit: Isn't possible to create/call an interrupt routine inside a class? (I know that the routine actually doesn't exist initially because the object of the class type wasn't created). Can this be done?

class Keyboard{
  private:
    struct btn{
      boolean pressed;
      uint32_t pressTime;
    };
    btn button1;

  public:
    void int_handler(){

    }
    Keyboard(){
      attachInterrupt(digitalPinToInterrupt(2),this->int_handler,RISING);
      attachInterrupt(digitalPinToInterrupt(3),this->int_handler,RISING);
    }
};
1
  • 1
    Keyboard::int_handler() must be static. Commented Apr 12, 2017 at 21:08

2 Answers 2

4

You only have two external interrupts on the Uno, so a simple solution would be to call an "intermediate" routine, which remembers the button number. eg.

  attachInterrupt(digitalPinToInterrupt(2),this->int_handler2,RISING);
  attachInterrupt(digitalPinToInterrupt(3),this->int_handler3,RISING);

Those two functions could then call your main function passing down 2 or 3 depending on which one was called.

eg.

void int_handler2 ()
  {
  int_handler (2);
  }

void int_handler3 ()
  {
  int_handler (3);
  }

If you have more switches than that you can use pin-change interrupts. The typical way of detecting which one fired is to see which bits are different this time, compared to last time.

See my page about interrupts.

1
  • Yes.I believe I'm gonna use the same old-functions to handle the interrupts.Thanks for the link! Commented Apr 12, 2017 at 21:32
1

I solved this in a more..compressed way. I already store the state of the buttons(pushed down or up-that is if they set their connected pin to 0 or 1).So I can have a single routine called by the microcontroller and then inside it decide what pin changed states(clever):

#define btn1Pin 2
#define btn2Pin 3

class Timer{
  //....
};
uint32_t Timer::start_time;
class KeyboardBtn{
  private:
    const static byte clicksDelay=255;
    struct btn{
      byte state=1;   //(0-keyDown / 1-keyUp) 2-Click 
      byte pin;
      Timer clickLapse;
    };
    volatile static btn buttons[2];

  public:  
    KeyboardBtn(){
      buttons[0].pin=btn1Pin;
      buttons[1].pin=btn2Pin;
      attachInterrupt(digitalPinToInterrupt(btn1Pin),keyPress,CHANGE );
      attachInterrupt(digitalPinToInterrupt(btn2Pin),keyPress,CHANGE );
    }
    static void keyPress(){
      //digitalRead ==1 then button up
      for(int i=0;i<2;i++){
        if(bitRead(buttons[i].state,0)==digitalRead(buttons[i].pin)) continue;
        //i is the switched button
      }
    }
    byte stateChanged(byte key){
      //code
    }
};
volatile KeyboardBtn::btn KeyboardBtn::buttons[2];

KeyboardBtn btn;
void setup() {
  pinMode(btn1Pin,INPUT_PULLUP);
  pinMode(btn2Pin,INPUT_PULLUP);
}

void loop(){
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.