Search code examples
matrixarduinocustom-keyboardteensy

Arduino keypad matrix example? ( teensyduino )


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?


Solution

  • 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).