Closed codinghusi closed 4 years ago
Hi, The problem is that the EventHandler
is stored in the ButtonConfig
class. By default, both button1
and button2
point to the same, default SystemButtonConfig
. The second call to setEventHandler()
clobbers the first setEventHandler()
. For multiple buttons, you have 2 options.
Option 1: Two ButtonConfigs
Create multiple ButtonConfigs, as shown in examples/TunerButtons:
#include <AceButton.h>
using namespace ace_button;
ButtonConfig config1;
AceButton button1(&config1);
ButtonConfig config2;
AceButton button2(&config2);
void button1Handler(AceButton* button, uint8_t eventType, uint8_t buttonState) {
Serial.println("button1");
}
void button2Handler(AceButton* button, uint8_t eventType, uint8_t buttonState) {
Serial.println("button2");
}
void setup() {
Serial.begin(9600);
pinMode(6, INPUT_PULLUP);
pinMode(7, INPUT_PULLUP);
config1.setEventHandler(button1Handler);
config2.setEventHandler(button2Handler);
button1.init(6);
button2.init(7);
}
void loop() {
button1.check();
button2.check();
}
Option 2: One ButtonConfig using getPin() to Discriminate
Use the AceButton::getPin()
method to discriminate between the two buttons.
#include <AceButton.h>
using namespace ace_button;
AceButton button1(6);
AceButton button2(7);
void button1Handler(AceButton* button, uint8_t eventType, uint8_t buttonState) {
Serial.println("button1");
}
void button2Handler(AceButton* button, uint8_t eventType, uint8_t buttonState) {
Serial.println("button2");
}
void buttonHandler(AceButton* button, uint8_t eventType, uint8_t buttonState) {
switch (button->getPin()) {
case 6:
button1Handler(button, eventType, buttonState);
break;
case 7:
button2Handler(button, eventType, buttonState);
break;
}
}
void setup() {
Serial.begin(9600);
pinMode(6, INPUT_PULLUP);
pinMode(7, INPUT_PULLUP);
ButtonConfig* config = ButtonConfig::getSystemButtonConfig();
config->setEventHandler(buttonHandler);
}
void loop() {
button1.check();
button2.check();
}
I tried to explain this in https://github.com/bxparks/AceButton#multiple-buttons, but you are not the first person to get confused by this. I will update the README.md with better explanation and examples.
Okay thanks!
I ran into this problem as well, I couldn't get bxparks' option 1 to work. His second option worked like a charm for me though. Here is a clean example for 3 buttons:
#include <AceButton.h>
using namespace ace_button;
const int BUTTON_1_PIN = 7;
const int BUTTON_2_PIN = 5;
const int BUTTON_3_PIN = 6;
AceButton button1(BUTTON_1_PIN);
AceButton button2(BUTTON_2_PIN);
AceButton button3(BUTTON_3_PIN);
void buttonHandler(AceButton*, uint8_t, uint8_t);
void setup() {
Serial.begin(9600);
pinMode(BUTTON_1_PIN, INPUT_PULLUP);
pinMode(BUTTON_2_PIN, INPUT_PULLUP);
pinMode(BUTTON_3_PIN, INPUT_PULLUP);
ButtonConfig* buttonConfig = ButtonConfig::getSystemButtonConfig();
buttonConfig->setEventHandler(buttonHandler);
}
void loop() {
button1.check();
button2.check();
button3.check();
}
void buttonHandler(AceButton* button , uint8_t eventType, uint8_t /* buttonState */) {
switch (eventType) {
case AceButton::kEventPressed:
switch (button->getPin()) {
case BUTTON_1_PIN:
Serial.println("Button 1");
break;
case BUTTON_2_PIN:
Serial.println("Button 2");
break;
case BUTTON_3_PIN:
Serial.println("Button 3");
break;
}
break;
}
}
@T-vK: Good job, your posted example is exactly how it should look. But I'm surprised to hear that Option 1 didn't work. It's possible that I made a typo in my post, but the example code in examples/TunerButtons (https://github.com/bxparks/AceButton/tree/develop/examples/TunerButtons) should work.
I think it would be useful to have a minimal multi-button example in this library because the TunerButtons example seems rather complex. What do you think?
In the latest release, v1.6, I added 2 more examples:
Love it!
I tested a bit around with this and figured out that I can't use more buttons than one? The following code will print "button2" if I press button1 or button2. It doesn't matter.