64-Key Prototyping Keyboard Matrix for Arduino
Introduction: 64-Key Prototyping Keyboard Matrix for Arduino
1/30/21 Update: I have completely rewritten the code for this keyboard. See the new "Update" step at the bottom.
I am currently working on a project that will have an integrated keyboard, which presented a problem: how do I include a keyboard in the development board prototype? I can't use a USB keyboard or an existing Arduino-based keyboard, because the keyboard in the actual project is connected directly to the microcontroller that handles all of the other functions. So I designed this basic PCB-based 64-key prototyping keyboard matrix.
This PCB does not contain any ICs (integrated circuits). The rows and columns of the keyboard matrix are connected directly to the pin headers so that the keyboard can be connected to an Arduino or any other microcontroller. It is perfect for prototyping your projects that will include an integrated keyboard.
I have included detailed, heavily-commented code to make this work with any Arduino-compatible development board that has an enough I/O pins available—11 pins are required. The keyboard has 64 keys, including modifiers for shift, caps, ctrl, alt, fn, and "special." There are also six additional keys that can be used for whatever you like. Every single key's functions can be defined individually, including each key's function when a modifier is active. In my opinion, this is significantly more useful than existing keyboard code that severely limits your ability to customize key behavior.
The code provided will print text to Serial. This can easily be changed if you want the text to go somewhere else.
A Note Regarding Program Size:
The code that I provide is pretty large, because it doesn't utilize any existing libraries whatsoever. I wrote this code completely from scratch in order to enable the customizability that I required. On an Arduino UNO, this will use 9100 bytes (28%) of program storage space and global variables use 394 bytes (19%) of dynamic memory.
My code could probably be more efficient and there libraries and sketches for keyboards are certainly smaller, but this is the only way I could devise to provide complete flexibility over every key with every modifier. It also takes into account real-world keyboard usage. For example, with my code pressing the Shift key while Caps Lock is enabled will result in a lowercase letter as it should. 1003
By default, holding down the FN key while pressing ESC won't do anything. But that behavior is completely customizable, so you can change it however you like.
Supplies
* The custom PCB
* 6x6x5mm tactile momentary push buttons (x64)
* 1N4148 switching diodes (x64)
* 1x8 pin headers, female or male (x2)
* 74HC595 shift register
* Jumper wires
* Breadboard
* Arduino Uno or any Arduino-compatible microcontroller development board
Step 1: How a Keyboard Matrix Works
Why is a keyboard matrix necessary?
This keyboard has 64 keys. If you were to connect each and every one of those buttons to your development board directly, you would need 64 I/O pins. That is a lot of pins and more than most development boards have available. To get that down to a far more reasonable number we can use a keyboard matrix, which only requires a number of pins equal to the square root (rounded up) of the number of keys.
A keyboard matrix is setup so every key switch in a row is connected and every key switch in a column is connected. When we want to see which keys are pressed, we "activate" the first row and then check each column. If a particular column is active, we know that the key in that column and row 1 has been pressed. We then deactivate row 1 and activate row 2, then check all of the columns again. After all of the rows have been activated, we simply start back over at the first row.
How we scan the keyboard matrix:
Because we're working with a microcontroller, "activate" means setting that row to either LOW or HIGH. In this case, we are setting the row to LOW because we are using the microcontroller's built-in pullup resistors on our column input pins. Without either a pullup or pulldown resistor, an input pin will react unpredictably as a result of interface, which will register false button presses.
The ATmega328P microcontroller used in the Arduino UNO does not have any built-in pulldown resistors, only pullup resistors. So we're using those. The pullup resistors connect each input pin to 5V, ensuring that they always read HIGH until a button is pressed.
All of the rows are also normally set to HIGH, which prevents the column pins from connecting to the row pins whether a button has been pressed or not. 1003