This is polled debounce routine to scan a bunch of switches. The rate of calling the scan routine determines the amount of debounce time.
There's a data structure associated with each input, that you refer to anywhere in the program to see if the input state is true or false.
It includes edge detection and logic so you can quickly determine if your program needs to do anything different after a scan, if the logical input has changed.
// hardware assignments for inputs, give the Arduino input pin number for physical connection
#define LeftInputPin 10
#define anotherInputPin 11
#define RightInputPin 7
// build a data structure for logical inputs
// assign handy names for positions in an array
#define totalInputs 3 // number of inputs (array size of the button structure)
#define LeftInput 0 // a given name for the input and its position in the array, starts at zero
#define anotherInput 1 // etc.
#define RightInput 2 // the highest position is N-1 (numInputs minus one)
// all the bits and pieces of an input to track
struct button {
byte pinNum;
int rawInput;
bool currentState;
bool edgeDetect;
};
// declare an array of buttons
// must initialize this array by zeroing the raw buffers, and clearing the boolean flags
button myButtons[totalInputs] = {
{ LeftInputPin, 0, false, false }, // an input is addressed as myButtons[LeftInput]
{ anotherInputPin, 0, false, false },
{ RightInputPin, 0, false, false }
};
boolean scanInput (int k)
// shift and fold the current pin value into its buffer as the least significant bit of raw input.
// sets the logical (debounced) state of the input and edge detection, and return the edge as boolean
// Note1: check for edgeDetect before calling scanInput again, because edges are transient -- lasting only one call
// Note2: this is the only place in the program allowed to read the physical pin value, everywhere else in the
// program only reference the data structure "currentState" to get logical debounced state of the input
{
switch ( myButtons[k].rawInput = (myButtons[k].rawInput << 1) | digitalRead(myButtons[k].pinNum)) {
case -1: // buffer is all ones (input is solidly HIGH)
myButtons[k].edgeDetect = ! myButtons[k].currentState;
myButtons[k].currentState = true;
break;
case 0: // buffer is all zeros (input is solidly LOW)
myButtons[k].edgeDetect = myButtons[k].currentState;
myButtons[k].currentState = false;
break;
} // case: all other rawInput values are "noisy" mixtures not sufficiently stable to declare a new steady state, so previous state is retained
return myButtons[k].edgeDetect;
}
void setup() {
for (int j = 0; j < totalInputs; j++) {
pinMode(myButtons[j].pinNum, INPUT); // no pullup is intentional to get random input from floating pins, just touch pins for demo
}
Serial.begin(57600);
}
void loop() {
for (int j = 0; j < totalInputs; j++) {
if (scanInput(j)) { // execute the following only when an low going or high going edge was detected (change of state)
Serial.print(myButtons[j].pinNum);
if (myButtons[j].currentState) Serial.println("+ON+") ;
else Serial.println("-OFF-");
}
delay(1);
// this delay, if wanted, sets the minimum amount of time to declare an input fully debounced
// in this example, buffer length (int is 16 bits) times this delay = 16ms
// so 16ms of unchanging input pin value will set the logical input state to match
// (10ms of bounce time for a typical switch is good enough and still seems instantly responsive to pressing the button)
}
}