Reputation: 151
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? 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;
}
}
--------- CODE EDIT 1
#include <Bounce2.h>
// Instantiate a Bounce object
Bounce debouncer[8];
bool prevValues[8];
// Keyboard values for btn 1 2 3 4 5 6 7 8
char keyboardValues[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'};
void setup() {
// First setup all the pins as input with pullup
pinMode(BUTTON_PIN_1,INPUT_PULLUP);
pinMode(BUTTON_PIN_2,INPUT_PULLUP);
pinMode(BUTTON_PIN_3,INPUT_PULLUP);
pinMode(BUTTON_PIN_4,INPUT_PULLUP);
pinMode(BUTTON_PIN_5,INPUT_PULLUP);
pinMode(BUTTON_PIN_6,INPUT_PULLUP);
pinMode(BUTTON_PIN_7,INPUT_PULLUP);
pinMode(BUTTON_PIN_8,INPUT_PULLUP);
// Setup Bounce instance - First attach them to the debouncer
debouncer[0].attach(BUTTON_PIN_1);
debouncer[1].attach(BUTTON_PIN_2);
debouncer[2].attach(BUTTON_PIN_3);
debouncer[3].attach(BUTTON_PIN_4);
debouncer[4].attach(BUTTON_PIN_5);
debouncer[5].attach(BUTTON_PIN_6);
debouncer[6].attach(BUTTON_PIN_7);
debouncer[7].attach(BUTTON_PIN_8);
Keyboard.begin();
// Then set the interval (e.g. 10 ms)
unsigned char i;
for (i = 0; i < 8; i++)
prevValues[i] = 0;
}
void loop() {
// Update the Bounce instances
unsigned char i;
for (i = 0; i < 8; i++)
debouncer[i].update();
bool debounced_btn_1 = debouncer[0].read();
bool debounced_btn_2 = debouncer[1].read();
bool debounced_btn_3 = debouncer[2].read();
bool debounced_btn_4 = debouncer[3].read();
bool debounced_btn_5 = debouncer[4].read();
bool debounced_btn_6 = debouncer[5].read();
bool debounced_btn_7 = debouncer[6].read();
bool debounced_btn_8 = debouncer[7].read();
for (i = 0; i < 8; i++)
{
bool currVal = debouncer[i].read();
if ((!currVal) && (prevValues[i]))
{ // If now it is pressed (value = 0) and it wasn't before (prevvalue = 1)
Keyboard.write(keyboardValues[i]);
}
}
}
Upvotes: 0
Views: 1358
Reputation: 2880
As I already suggested you, this solution works well if you have to use just one button. If you need more buttons, you shall duplicate this code for every button.
An alternative is to check directly the port value (8 bits at once). I think this is the best solution for performances, but it's not very readable.
The bounce2 solution is the best, in my opinion. You just have to
Bounce2
library and properly install itFor instance you can use an array to store all the bouncers. Example with 8 pins:
#include <Bounce2.h>
// Instantiate a Bounce object
Bounce debouncer[8];
void setup() {
// First setup all the pins as input with pullup
pinMode(BUTTON_PIN_1,INPUT_PULLUP);
pinMode(BUTTON_PIN_2,INPUT_PULLUP);
...
// After setting up the button, setup the Bounce instance
// First attach them to the debouncer
debouncer[0].attach(BUTTON_PIN_1);
debouncer[1].attach(BUTTON_PIN_2);
...
// Then set the interval (e.g. 10 ms)
unsigned char i;
for (i = 0; i < 8; i++)
debouncer[i].interval(10);
// other initializations
...
}
void loop() {
// Update the Bounce instances
unsigned char i;
for (i = 0; i < 8; i++)
debouncer[i].update();
// From now on you can access the debounced
// values directly from the array, for instance
bool debounced_btn_1 = debouncer[0].read();
bool debounced_btn_8 = debouncer[7].read();
...
}
In your case, since you want to send a keyboard command, you can store all the values in an array (which can be modified, of course) and then send them when needed; you should also remember the last state to send the value just at the button pressing...
bool prevValues[8];
// Keyboard values for btn 1 2 3 4 5 6 7 8
char keyboardValues[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'};
void setup() {
// Pins initializations
...
for (i = 0; i < 8; i++)
prevValues[i] = 0;
}
void loop() {
// Update the Bounce instances
...
for (i = 0; i < 8; i++)
{
bool currVal = debouncer[i].read();
if ((!currVal) && (prevValues[i]))
{ // If now it is pressed (value = 0) and it wasn't before (prevvalue = 1)
Keyboard.write(keyboardValues[i]);
}
}
...
}
Upvotes: 1