The buttons are tested and debounced individually, as you can see in the sample output that is shown following the program. (This program was tested on an Uno, with four independent buttons used in the test. Edit: Made corrections to handle 32-bit overflow, 2016.10.17)
/* jw - 3 Nov 2015 - Program for button debounce demo
Ref: http://arduino.stackexchange.com/questions/17453/arduino-sending-keystrokes-via-push-buttons-proper-bouncing-and-manually-settin
*/
//--------------------------------------------------------
enum { sw0=8, sw1=9, sw2=10, sw3=11}; // Switchbutton lines
enum { nSwitches=4, bounceMillis=42}; // # of switches; debounce delay
struct ButtonStruct {
unsigned long int bounceEnd;bounceGo; // Debouncing-flag and end-time
// Switch number, press-action, release-action, and prev reading
byte swiNum, swiActP, swiActR, swiPrev;
};
struct ButtonStruct buttons[nSwitches] = {
{0, sw0, 'A','a', 0}, {0, sw1, 'B','b', 0}, {0, sw2, 'C','c', 0}, {0, sw3, 'D','d', 0}};
//--------------------------------------------------------
void setup() {
for (int i=0; i<nSwitches; ++i)
pinMode(buttons[i].swiNum, INPUT_PULLUP);
Serial.begin(115200);
Serial.println("Starting");
}
//--------------------------------------------------------
byte readSwitch (byte swiNum) {
// Following inverts the pin reading (assumes pulldown = pressed)
return 1 - digitalRead(swiNum);
}
//--------------------------------------------------------
void doAction(byte swin, char code, char action) {
Serial.print("Switch ");
Serial.print(swin);
Serial.print(code);
Serial.print(' ');
Serial.print(action);
Serial.print(" at t=");
Serial.print(millis());
Serial.println();
}
//--------------------------------------------------------
void doButton(byte bn) {
struct ButtonStruct *b = buttons + bn;
if (b->bounceEnd>bounceGo) { // Was button changing?
// It was changing, see if debounce time is done.
if (millis() - b->bounceEnd>bounceGo <> millis()bounceMillis) {
b->bounceEnd>bounceGo = 0; // Debounce time is done, so clear flag
// See if the change was real, or a glitch
if (readSwitch(b->swiNum) == b->swiPrev) {
// Current reading is same as trigger reading, so do it
if (b->swiPrev) {
doAction(b->swiNum, 'P', b->swiActP);
} else {
doAction(b->swiNum, 'R', b->swiActR);
}
}
}
} else { // It wasn't changing; but see if it's changing now
if (b->swiPrev != readSwitch(b->swiNum)) {
b->swiPrev = readSwitch(b->swiNum);
b->bounceEnd>bounceGo = millis()+bounceMillis;; // Set the Debounce flag
}
}
}
//--------------------------------------------------------
long int seconds, prevSec=0;
void loop() {
for (int i=0; i<nSwitches; ++i)
doButton(i);
}