-1

I'm a beginner using Arduino with a Teensy 3.2 board and programming it as a usb keyboard. I have two 4 button membrane switches. Their button contacts are on pins 1-8, and the 9th pin holds a soldered together wire of both membrane switches' "ground" line or whatever it's true name is; the line that completes the circuit.

Basically when you press the buttons they are supposed to simply type "a, b, c..." respectively. I've been told I need to use a matrix for this.

I'm looking for an example of how to code a keyboard matrix that effectively supports a one row/9 column line (or vice versa?) I've been unable to find that solution online.

All I have so far is this code which, when the button on the second pin is pressed, sends tons of "AAAAAAAAAAAAAAAA" keystrokes.

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 the button is pressed
  if(digitalRead(2)==LOW){
    //Send an ASCII 'A', 
    Keyboard.write(65);
  }
}

Would anyone be able to help?

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
sylcat
  • 151
  • 1
  • 3
  • 18

1 Answers1

3

First of all, a 1-row keypad is NOT a matrix. Or better, technically it can be considered a matrix but... A matrix keypad is something like this:

matrix keypad schematic

You see? In order to scan this you have to

  1. Pull Row1 to ground, while leaving rows 2-4 floating
  2. Read the values of Col1-4. These are the values of switches 1-4
  3. Pull Row2 to ground, while leaving rows 1 and 3-4 floating
  4. Read the values of Col1-4. These are the values of switches 5-8

And so on, for all the rows

As for the other problem, you are printing an A when the button is held low. What you want to achieve is to print A only on the falling edge of the pin (ideally once per pressure), so

char currValue = digitalRead(2);
if((currValue==LOW) && (oldValue==HIGH))
{
    //Send an ASCII 'A', 
    Keyboard.write(65);
}
oldValue = currValue;

Of course you need to declare oldValue outside the loop function and initialize it to HIGH in the main.

With this code you won't receive tons of 'A's, but however you will see something like 5-10 'A's every time you press the button. Why? Because of the bouncing of the button. That's what debouncing techniques are for!

I suggest you to look at the class Bounce2 to get an easy to use class for your button. IF you prefer some code, I wrote this small code for another question:

#define CHECK_EVERY_MS 20
#define MIN_STABLE_VALS 5

unsigned long previousMillis;
char stableVals;
char buttonPressed;

...

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;
    }
}

In this case there is no need to check for the previous value, since the function already has a point reached only when the state changes.

If you have to use this for more buttons, however, you will have to duplicate the whole code (and also to use more stableVals variables). That's why I suggsted you to use the Bounce2 class (it does something like this but, since it is all wrapped inside a class, you won't need to bother about variables).

frarugi87
  • 2,826
  • 1
  • 20
  • 41
  • I'm used to using a keyboard mapper called easy AVR which creates a matrix for you. When I use code to try to setup button by button it never works right. Example, I used your 2nd set of code just now. I have at least 4 of the 5 membrane switch contacts attached to get one button to register and sometimes when I remove one (not from pin 2) the button I need to press to type the character even changes which makes nooo sense to me. Even trying to attach a single two prong momentary button to type a character doesn't work with this code like this at all: http://tinyurl.com/p5tmuz8 – sylcat Oct 29 '15 at 16:49
  • Sorry, I could not understand what is the problem. Now what I understood is that you are trying to emulate a keyboard (but I suggest you to change `Keyboard.write(65);` to `Serial.print('A');` to understand what is the real problem) and that, with a pushbutton attached to a pin, it does not work like you wanted. With my code it SHOULD (hopefully) work in such a way that when you press the button it sends just one A ignoring the bounces. What do you receive? – frarugi87 Oct 29 '15 at 17:13
  • I tried changing to serial, it displays nothing in both cases. I've tried many configurations but nothing displays. Here's the most common configuration I'musing if you want to see it on the breadboard visually. http://tinyurl.com/q5xzrja The legs of the buttons run through the bottom (so 4 prongs but only 2 real lines) I've tried ever inclusion and exclusion of these and nothing from pin two displays. I should note I'm using the void setup() from my code with your suggested code. (also a matrix would be best, using it like this takes up 2 pins for each button theoretically) – sylcat Oct 29 '15 at 20:29
  • You changed the pinMode and the digitalRead functions to read from pin 1, right? 'cause the button is on pin 1, i think ;) – frarugi87 Oct 29 '15 at 21:34
  • 1
    Sorry for the late reply. WOW I'm dumb :v Thanks! – sylcat Nov 02 '15 at 22:46