How does a keyboard actually work? This question is still unanswered. The simplest and most expensive solution would be to treat every key on it’s own and provide a interrupting GPIO (General Purpose Input/Output) pin for every key. The approach usually taken by professional keyboards today is different and you only need none-interrupting GPIO pins one for each row and column of keys. And it basically works as follows:
- Switch all row pins to LOW.
- Take the first row and switch it to HIGH
- Read the state of the first column pin. If it is HIGH the key at row number one and column number one is pressed. Else it is not pressed. If the state of the key changed, compared to it’s previous state (from HIGH to LOW or from LOW to HIGH), the change is send to the computer. Remember the actual state.
- Proceed with step 3 for the next column pin until every column was read once.
- Set the row LOW. Proceed with step 2 for the next row pin until every row was set HIGH once.
- Start all over.
My first test program resembled this steps (also known as polling) quite closely, ignoring all those pitfalls I already read about. But first things first: actually build the keyboard matrix. I glued and soldered the key switches to the prepared stripes of stripboard. I made the rows by connecting the TriPads with solder. At the end of each row I connected differently colored wire that were long enough to reach to the top of the keyboard case where the Arduino would live. Six rows an each part of the keyboard and six pins on the Arduino. I connected the other end of each row with a 10K resistor to GND (pull-down). When I first encountered keyboard technology I was confused with all the fuzz around ghosting and key rollover. Basically it’s just marketing by the keyboard industry and boils down to a problem with the current flow, witch you can counter with diodes (they let the current flow in only one direction). So I decided to give every switch a diode (they are quite cheap, just a few cents each, so no big deal for the budget). Ghosting eliminated. I know a purist might argue that I still have a blocking problem because I’m using the standard Bluetooth HID protocol for communication, and that it is restricted regarding the number of keys (6 none-modifier keys) one can simultaneously press. Actually it is the same restriction as for every USB keyboard. Only PS2 allows unlimited concurrent keys. I thought about it and couldn’t imagine any situation where I would want to press more keys at a time. The first attempt for the hardware columns was to create them from the legs of those diodes. That approach was quite time consuming and fiddly. So after three diode columns I took a different approach. I dismantled a none-flexible three-core electric installation cable and used a copper strand for every column. I bend them so that the ends face downwards and drilled holes in the top and lowest stripboard stripe for the ends of each strand. I soldered them in place. From the strands I connected every switch with a diode. On each copper strand I soldered a uniquely colored wire reaching to the Arduino. The right hand part of the keyboard had eight columns on the left there are seven. I connected those to the Arduino. Before I show you how the actual Arduino code looks like just a few words about the key layout, which is a modified version of the usual NEO2 layout. As you can see I decided to move the “Enter”, “Backspace” and “Entf” (Remove) keys to the middle. The TypeMatrix keyboard inspired me in this regard. I also have two of them one on each side. So I can actuate “Enter” with my right as well as my left hand pointer. If you have looked closely to the finished keyboard you can see that in contrast to the conceptual layout all keys have the same size. It was impossible for me to stabilize longer keys without professional keycaps with clamps. The keycaps – their creation was the most labor intensive work – are the subject of a later post. For now I assumed I could simply use two key switches to make bigger keys. This plan didn’t work out. And it was not the only one. Here is a Github Gist with the keyboard-matrix-polling relevant parts of my Arduino program (written and compiled with the Arduino IDE). These are really only parts of the program for the left hand keyboard, some used functions. I omitted variable and constant declarations. So don’t expect this snippet to compile. For the right hand I defined the “Key” struct a little different so that it holds the actual key code, that has to be sent to the computer as well as the type of the key (e.g. normal key or modifier). I hope the code is somewhat self-explanatory. If not leave me comment.