I have a simple set of 8 push buttons wired to a Teensy 3.2 board (which uses Arduino via Teensyduino plugin). The 8 buttons are on pins 1-8 and their common ground line (one line soldered to each of them) is on the GND pin. I have code to get any one button working that works. It's currently set to make pressing the second button type "A."
I'd like to make push buttons 1 through 8 type out A,B,C...etc respectively as you press them. I've been told of two problems with my setup, the first being that copying the code for every button is a bad way to go about it and second that it's subject to bouncing issues (creates a keystroke once every 5 presses or so.) I'd also like to set this up so in the future I can write a 3rd party app that configures the keys based on the user's preference.
Adding those needs up I'm not sure where to go next. I'm beginner enough that I'm not sure how to properly incorporate the bounce class or if that's the right way to go given the needs.
Is a matrix the way to go or is there an elegant way to manual set each button and compensate for bounce? I'd really appreciate a small example if anyone has done this. Thanks~ Current code follows:
#define CHECK_EVERY_MS 20
#define MIN_STABLE_VALS 5
unsigned long previousMillis;
char stableVals;
char buttonPressed;
void setup() {
// make pin 2 an input and turn on the
// pullup resistor so it goes high unless
// connected to ground:
pinMode(2, INPUT_PULLUP);
Keyboard.begin();
}
void loop() {
if ((millis() - previousMillis) > CHECK_EVERY_MS)
{
previousMillis += CHECK_EVERY_MS;
if (digitalRead(2) != buttonPressed)
{
stableVals++;
if (stableVals >= MIN_STABLE_VALS)
{
buttonPressed = !buttonPressed;
stableVals = 0;
if (buttonPressed)
{
//Send an ASCII 'A',
Keyboard.write(65);
}
}
}
else
stableVals = 0;
}
}
------- Edit: WORKING CODE FOLLOWS
/* 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=3, sw1=4, sw2=5, sw3=6, sw4=7, sw5=8, sw6=9, sw7=10}; // Switchbutton lines
enum { nSwitches=8, bounceMillis=42}; // # of switches; debounce delay
struct ButtonStruct {
unsigned long int bounceEnd; // 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'},
{0, sw1, 'B'},
{0, sw2, 'C'},
{0, sw3, 'D'},
{0, sw4, 'E'},
{0, sw5, 'F'},
{0, sw6, 'G'},
{0, sw7, 'H'}};
//--------------------------------------------------------
void setup() {
for (int i=0; i<nSwitches; ++i)
pinMode(buttons[i].swiNum, INPUT_PULLUP);
Keyboard.begin();
}
//--------------------------------------------------------
byte readSwitch (byte swiNum) {
// Following inverts the pin reading (assumes pulldown = pressed)
return 1 - digitalRead(swiNum);
}
//--------------------------------------------------------
void doAction(byte swin, char code, char action) {
Keyboard.write(action);
}
//--------------------------------------------------------
void doButton(byte bn) {
struct ButtonStruct *b = buttons + bn;
if (b->bounceEnd) { // Was button changing?
// It was changing, see if debounce time is done.
if (b->bounceEnd < millis()) {
b->bounceEnd = 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 = millis()+bounceMillis; // Set the Debounce flag
}
}
}
//--------------------------------------------------------
long int seconds, prevSec=0;
void loop() {
for (int i=0; i<nSwitches; ++i)
doButton(i);
}