Building your own keyboard (from scratch)
Tags: keyboard, kicad, hardware, embedded
Published: 2020-08-22 20:10:54

***(Note: these posts are migrated from my previous [medium.com](https://medium.com/@monkeytypewritr) blog)***

Another interest of mine are computer keyboards. I’ve acquired this interest relatively recently, and have spent many hours since perusing /r/MechanicalKeyboards:

![/u/aaron6301](https://cdn-images-1.medium.com/max/3232/0*cWzjVYfIR7n15eCP.jpg)

![/u/[fathovercats](https://www.reddit.com/user/fathovercats)](https://cdn-images-1.medium.com/max/4000/0*Z60rW-ZVlnVxdpTm.jpg)

Aren’t these beautiful? They come in all sorts of colors, sizes, lights, layouts, switches, and **price**. And as a tool that I use everyday, it was easy for me to justify my purchases :)

At the high end, these keyboards are often custom designed and hand assembled: CNC’d aluminum plates, RGB underglow, custom PCB/firmware, etc.

![[http://www.gonskeyboardworks.com/](http://www.gonskeyboardworks.com/)](https://cdn-images-1.medium.com/max/2048/0*u1-ctn9r67hdTm1a.jpg)

## Building one?

As I found out from the /r/MechanicalKeyboard community, there are a lot of members who built their own, and has contributed a lot of their work back to the open source community; from hardware design (e.g. [GH60](https://github.com/komar007/gh60)) to software/firmware (e.g. [TMK](https://github.com/tmk/tmk_keyboard)/[QMK](https://github.com/qmk/qmk_firmware)).

Ever since building my [Lego BLE controller](https://medium.com/@monkeytypewritr/building-a-bluetooth-le-lego-controller-web-bluetooth-app-754a9993d511#.c3ocf1i4b), I’ve wanted to take on a more advanced project, and this seemed like the perfect one!

**Hardware**

A keyboard’s hardware is pretty simple: it’s just a bunch of buttons! The challenge lies in that a typical keyboard has about a 100 keys/buttons; most microcontrollers don’t have that many input pins, and it would be a waste to use them all simply to read buttons. The trick is to use a keyboard matrix (e.g. 5 rows x 15 columns) and quickly cycle through each row/column, allowing you to use *2n* pins only for a *n *x *n* matrix. You can read more about how that works in this excellent [article](http://blog.komar.be/how-to-make-a-keyboard-the-matrix/).

![Note the 5 way tactile switch I added. It functions as arrow keys or a mouse!](https://cdn-images-1.medium.com/max/2584/1*5apsaKutI0lc03KOat5LfQ.png)

For the microcontroller, I chose the popular atmega32u4. It’s got USB support and is also used in the Arduino Pro Micro. The firmware which we will be using later also supports it. The only work that needs to be done is to map our row and column buttons to the microcontroller’s GPIO pins:

![I took the Arduino Pro Micro schematic, removed the 5V regulator and Tx/RX LEDs, and mapped the GPIO pins](https://cdn-images-1.medium.com/max/2380/1*pKOXjWUAbqFnz5xGDpw2Hw.png)

Once we have our schematic, now begins the fun part of routing the PCB. In my previous project, I simply used the autoroute feature and let the algorithms do their job. In this design, there were simply too many connections to use that feature, and I wanted a nice clean design (and also throwing in some nice PCB artwork along the way).

![Top Layer: Red, Bottom Layer: Blue, Silkscreen: Yellow](https://cdn-images-1.medium.com/max/2570/0*l1CsNDzcEt1g3kfW.png)

I sent in this design to [Seeed studio](https://www.seeedstudio.com/fusion_pcb.html) and got it made; I chose a black PCB with white silkscreen. In 2 weeks they showed up:

![Nice and shiny :) Though I wished they had an option for a matte black PCB](https://cdn-images-1.medium.com/max/4000/0*6wQLYdQOYAlaZzvv.jpg)

**Software**

Luckily for me, there’s already a great open source keyboard firmware project out there, [TMK](https://github.com/tmk/tmk_keyboard)! It already supports a bunch of keyboards and has great documentation on how to customize and compile a build for your own design. The only thing I needed to do was to configure the GPIO pins to the right row and columns and define the [keymap](https://github.com/tmk/tmk_keyboard/blob/master/tmk_core/doc/keymap.md), for example:

```const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
        /* 0: Qwerty
         * ,-----------------------------------------------------------.
         * |Esc|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|  \|  `|
         * |-----------------------------------------------------------|
         * |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|Backs|
         * |-----------------------------------------------------------|
         * |Contro|  A|  S|  D|  F|  G|  H|  J|  K|  L|Fn1|  '|Enter   |
         * |-----------------------------------------------------------|
         * |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  .|  /|Shift |Fn0|
         * `-----------------------------------------------------------'
         *       |Gui|Alt  |Space                  |Alt  |Fn2|
         *       `-------------------------------------------'
         */
        KEYMAP(ESC, 1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   MINS,EQL, BSLS,GRV, \
               TAB, Q,   W,   E,   R,   T,   Y,   U,   I,   O,   P,   LBRC,RBRC,BSPC, \
               LCTL,A,   S,   D,   F,   G,   H,   J,   K,   L,   FN1, QUOT,ENT, \
               LSFT,Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, SLSH,RSFT,FN0, \
                    LGUI,LALT,          SPC,                RALT,FN2),```

## Putting it all together

![Piccolo for scale :)](https://cdn-images-1.medium.com/max/4000/0*kDurk8pS1JMGSqWK.jpg)

After soldering all of the components and compiling the firmware, I flashed the firmware onto the board over USB using dfu-programmer. To my surprise, everything worked on first try! Typing on it was a lot of fun (for about 2 minutes) and I was pretty happy with the results. Though I probably won’t be using this as my daily driver, I definitely learned a lot about PCB design and embedded development.

You can find all the software and hardware source on my GitHub [https://github.com/w4ilun/pocket-keyboard](https://github.com/w4ilun/pocket-keyboard)