A few days ago, someone started a new topic thread on debouncing several push-buttons. I was very impressed with PieterP's response and class handling of the push-buttons. I deal with a lot of push-button interfaces and have been wanting to do something like this for myself for a long time to reduce overall coding. I am not as fluent in C++ but wish to adopt the concepts presented in the code presented. To this end, I've copied the code, modified the code slightly and present it here. My actual question(s) are presented as comments in the code.
class PushButton {
public:
PushButton(byte pin) : pin(pin) {}// Can someone explain what the ":" here means? what is pin(pin)? How does it work with the array buttons[]?
void begin() const {
// for (auto &button : buttons) I would like to move this bit of code from the setup loop to here, if possible.
// What does auto mean?
// What is the syntax &button : buttons?
// I find it difficult to Google for help with this. Most guides I've found on classes do not cover these advanced topics.
pinMode(pin, INPUT_PULLUP);
}
/*I have modified the actual debounce code. this is yet untested, but the goal is to return true on the initial HIGH to LOW transition but debounce
both transitions so if the button is held down for longer than the debounce interval and released, it doesn't trigger a second press from the noise...
I have also structured it with the flag to avoid constantly calling millis() as that stops interrupts each time it's called...*/
bool isPressed() {
bool b = false;
if (debounceFlag == 1) {
if (millis() >= debounceStopTime) debounceFlag = 0;
}
else if (debounceFlag == 0) {
int currentState = digitalRead(pin);
int stateChange = currentState - previousState;
if (stateChange == fallingEdge) {
debounceStopTime = millis() + DebounceInterval;
b = true;
debounceFlag = 1;
}
else if (stateChange == risingEdge) {
debounceStopTime = millis() + DebounceInterval;
b = false;
debounceFlag = 1;
}
else b = false;
previousState = currentState;
}
return b;
}
/* byte whichButton() I would like to create a member function that would check up to 8 buttons for isPressed() and map the returns to bits in a byte
and return the value, so code later could take action based on a combination of buttons pressed. I think if I had a better understanding of some of the
advanced concepts introduced here, I could figure out how to code this.
Do I refer to them as pin? Do I refer to them as buttons[i]?
I vaguely understand buttons is an external name and maybe pin is an internal name, but I am looking for a better explanation on the names presented.*/
const byte pin;// which pin is which? There is this pin, and there is a pass by value pin in the constructor. What does this pin do? If I change the name of this, where also must the name change?
private:
int previousState = HIGH;
byte debounceFlag = 0;
unsigned long debounceStopTime;
const static unsigned long DebounceInterval = 20UL;
const static int risingEdge = HIGH - LOW;
const static int fallingEdge = LOW - HIGH;
};
PushButton buttons[] = { 2, 3, 4 }; // Create PushButton objects on pins 2, 3 and 4
void setup() {
Serial.begin(9600);
for (auto &button : buttons) button.begin();
}
void loop() {
for (auto &button : buttons)
if (button.isPressed()) {// since the only reference to a button in the array is all buttons in the array, what would a call for isPressed() on a single button look like?
Serial.print("Button on pin #");
Serial.print(button.pin);
Serial.println(" pressed!");
}
}