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);
}
};
2 Answers 2
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.
-
Yes.I believe I'm gonna use the same old-functions to handle the interrupts.Thanks for the link!sergiu reznicencu– sergiu reznicencu04/12/2017 21:32:01Commented Apr 12, 2017 at 21:32
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(){
}
Keyboard::int_handler()
must bestatic
.