Friday, 4 July 2025

My first keyboard PCB design - a diode-free 36 key ergonomic layout

My previous blog posts talked about diode-free keyboard designs using topology, and specifically using a partial Tutte-Coxeter graph for keyboards with 30~42 keys. As hinted at, I spent June making my own no-diode topology-based 36-key ergonomic keyboard PCB design using the Open Source tools Ergogen and KiCad. This is designed as an alternative PCB to fit the existing Gamma Omega keyboard's 3D printed case design (case design or modification can be a future project).

Front and back rendered images of 36-key PCB in black from JLCPCB website

 

Erogegen v4.1.0

This tool lets you describe an ergonomic keyboard layout and easily adjust the splay and stagger to suit your taste or hands - and can handle mirrored designs as easily as split designs. In this case I was starting from an existing split PCB design (two reversible 18-key boards) and turning it into a single larger mirrored 36-key board, but Flat Foot Fox'n blog post "Let's Design A Keyboard With Ergogen v4" series was incredibly helpful.

I changed the choc-switch footprint settings (the original design used reversible footprints) to single-sided, which is simpler. Mine will be hot-swapped, but the footprint makes it easy to allow attaching the switches either with hot-swap sockets (in the "North" orientation), or directly soldered (rotated 180 degrees in the "South" orientation - this would need changes to the original bottom case though). The direct solder sockets act as vias (conductive holes through the board) making adding the traces (electrical wiring) a little easier. This was an idea copied from the Old Man's "The End Game" keyboard PCB.

The existing case design assumed a particular USB-C variant of the Raspberry Pi Pico micro-controller, with a hole in the bottom plate to access the boot button (for re-flashing the firmware), so I have assumed the same. This now needs a matching hole in the PCB, and a cutout to give enough room for the USB-C socket.

The original two-PCB design only needed a header footprint for half the controller. With a full board we need a full micro-controller footprint. I used the proposed Raspberry Pi Pico footprint on this Ergogen pull request. I guess smaller controllers with support built into Ergogen are more popular, but the fact the larger RP Pico controllers expose at least 26 GPIO pins is precisely why I want to use them.

Currently Ergogen (as of v4.1.0) doesn't let you define silk-screen art (images, lines, circles, arcs), or even text. I spotted how the author of the Caldera keyboard added text using a custom Ergogen footprint. I took this one step further to define my own line-art as a Ergogen silk-screen footprint for the partial Tutte-Coxeter graph (since drawing this by hand in KiCad is very fiddly). This was generated in Python, but could in principle be done directly in JS with the same logic (some simple loops and geometry).

KiCad v9.0.2

The main output from running Ergogen v4.1.0 is a KiCad v8 PCB file, which the current version KiCad v9.0.2 can open fine. I then had to layout the wiring for my traces, and used Flat Foot Fox's blog post "Let's Design A Keyboard With Ergogen v4" finale which was incredibly helpful.

Screenshot of KiCad with the un-wired PCB from Ergogen loaded
Un-wired TC36k keyboard PCB from Ergogen opened in KiCad v9.0.2

The scanning-columns were assigned to the physical columns as in my previous blog post, and done on the underside (along with the hotswap sockets). This time I added some of the row-scanning traces here too. The rest are on the top side - and due to the stagger and small margin of the PCB where it hugs the top ring and middle finger keys, I could not run traces there - so the final pin assignment and wiring needed redoing.

For my traces I tried to follow the local key footprint orientation - which due to the splay between the columns for each finger meant a lot of rotation - and all to frequent discovery that the latest edits had left the traces on the other side out of place. I recommend stopping to run the board checks ("Design Rules Checker") and saving a separate new version frequently.  Sadly although the KiCad PCB file is plain text, it does not play nicely with version control - all those board rotations result in floating-point number noise.

This design only has a wiring matrix on the board, so the power and ground pins are unused. To satisfy the wiring net checks, I added traces to connect all the controllers ground pins to each other. Then, while I probably didn't need to, I used this example with a ground plane to add one anyway. This meant tweaking my trace placement in lots of places to leave enough space for a "ghost trace" from the automatically filled ground plane. I got the vast majority of the board covered on both sides without any extra vias.

Cropped screenshot of KiCad v9.0.2 on macOS showing my TC36k keyboard PCB
TC36k keyboard PCB in KiCad v9.0.2

For the final steps I actually copy-and-pasted the traces from a working copy to a fresh clean output from Ergogen. This just left the fairly easy challenge of dropping it all in the right place - and fine tuning a couple of traces which ended up ever so slightly too close to a hole etc.

QMK Firmware

This is a wired USB keyboard, so QMK was the natural firmware to try - although complicated by ongoing changes to how the main repository is organized. Most custom keyboard designs are seemingly created in forks of the main QMK firmware repository. I looked at this but couldn't get all the dependencies installed on macOS.  Instead, I'm using their QMK Userspace approach with GitHub Actions to build the firmware (with a preparation_command trick as this is a custom keyboard). All that was the hard bit.

The actual core of my partial Tutte-Coxeter 36 key firmware is very simple - one keyboard.json file listing the 13 GPIO pins for my scanning columns, the 13 GPIO pins for the scanning rows, and the 36 keys as positions in the sparse 13 by 13 scanning matrix following the existing LAYOUT_split_3x5_3 ordering (shown here as Qwerty with L1, L2, L3, R3, R2, and R1 for the thumbs):


GP11GP10GP3GP4GP7GP26GP27GP28GP15GP21GP19GP20GP16
GP12Z




J





GP8QS








;
GP9
XC









GP1

DR




O


GP6


VG







GP2
W

TY






GP22




HM




R3
GP0

E


UI




GP13



B

KL2



GP14A






L1L


GP18




N


.R2

GP17






,

R1/
GP5


F






PL3

In hindsight I should have tried harder to have Q top left, as by convention the key at that matrix position is used in QMK for reset on startup. 

Making a Vial compatible firmware was also fairly easy - I wanted this as Vial makes tinkering with a layout without re-flashing really easy. And I managed to build Miyoku QMK firmware for my keyboard too, since I followed the LAYOUT_split_3x5_3 community standard.

Assembly Production Files

I decided fairly early on that I would try JLC PLC to fabricate my PCB (minimum order of five), and also solder on all of the hotswap sockets with their assembly service. That would leave me with just the controller daughter board to solder in before adding the switches and case (which JLC PCL can 3D print for me too).

PCB fabrication needs Gerber format files which are easily exported from KiCad. For assembly you also need a "Bill of Materials" (BOM) table with part numbers (fairly easy here with just 36 of the hotswap sockets), and a Component Placement List (CPL), also known as a Centroid, Pick and place, or position file. That lists the exact position for each part, including the rotation - not something to attempt manually!

I installed Benny Megidish's JLCPLC Fabrication Toolkit which does all that (currently version 5.1.0), but needs the part numbers first. For that, I installed Bouni's Kicad JLCPBC Tools plugin (currently version 2025.04.02), and clicked the icon in KiCad. This found three different "components" from the footprints on the board:

  • RPi_Pico_SMD_TH - The Raspberry Pi Pico controller, not asking for this in the assembly, so turn off BOM and POS for this.
  • mounting_hole_plated - The case screw points, again turn off BOM and POS as nothing to assemble here
  • switch_choc_v1_v2 - The low-profile choc switch footprints - these must have BOM and POS ticked. Double click and search for part number CPG135001S30, which gave two Kailh options - neither in stock:
    • LCSC part C9900009224, significantly cheaper: Pre-order Items Pricing, Estimated unit price: $0.0006 - I wanted to pick this, but it shows as unavailable with only consignment was offered (i.e. buy elsewhere and send it to JLCPLC). 
    • LCSC part C5333465, much more expensive, one in stock: Pre-order Items Pricing, Estimated unit price: $0.1029 - I could pre-order this, but a working day later, bad news: "We are sorry to inform you that the below parts are out of stock and unable to get quotation".

So, no assembly with the hotswap sockets. Nor were any choc-switches in stock or available to pre-order (since they can alternatively be directly soldered with this design, and could be used with the assembly service).

Back in KiCad, I saved the hot swap part assignments anyway. And then clicked the JLCPLC Fabrication Toolkit icon, left the defaults, and clicked generate. That made a production/ sub-folder with five files (and a sub-folder of backup PCB files):

  • gamma-omega-tc36k_v1.0.0.zip - the Gerber files to fabricate my PCB, including drill files
  • bom.csv - the Bill of Materials (BOM)
  • positions.csv - the Component Placement List (CPL)
  • designators.csv - list of footprint identifiers used
  • netlist.ipc - IPC netlist file

I think we just need the first three to order an assembled board at JLCPCB, but just the Gerbers ZIP file for the board alone. The PCB production files are in the repository.

PCB Fabrication

I logged into JCLPLC, and uploaded gamma-omega-tc36k_v1.0.0.zip - this was correctly recognized as a 2-layer board, about 23.3cm by 11.1cm. I look the defaults except the black finish (with white silk-screen art), lead free HASL finish, and removed the order number from the board - cropped screenshot at the top of the post.

I tried toggling assembly on, defaults except I ticked "Confirm Parts Placement". Clicked next, uploaded the BOM and positions CSV files, but then was stuck on the parts shortfall. So no assembly service for me (see above).

The five boards were only USD $16.50. I opted for the cheaper slower shipping, and added the 3D printed Gamma Omega keyboard case in SLA resin, and KLP Lamé Choc Saddle keycaps too:

My JLCPCB order total to the UK:

Merchandise Total: $49.46
Shipping Charge: $12.24
Customs duties & taxes: $12.34
Order Total: $74.04

I'm waiting on the PCB confirmation email, and still need to order a set of choc v1 switches, hot-swap sockets, and controller(s).

Friday, 30 May 2025

Mechanical keyboard wiring using the Tutte-Coxeter graph

Following my post on Topology meets Keyboard Design, I spent a few days exploring small less symmetric graphs, trying to find something in the region of 30~42 edges, 20~29 vertices, and as good a girth as possible (especially to have better rollover for the modifier & layer keys) for use in an ergonomic keyboard design. Then I realised as a starting point we can just use part of the 30 vertex Tutte-Coxeter graph, and get 6-key rollover automatically.

30 vertex Tutte-Coxeter graph 28/30 vertices in Tutte-Coxeter graph 26/30 vertices in Tutte-Coxeter graph
All 30 vertices in Tutte-Coxeter graph28 of 30 vertices in Tutte-Coxeter graph26 of 30 vertices in Tutte-Coxeter graph

Friday, 23 May 2025

Topology meets custom keyboard circuit design

Lately I've been reading about ergonomic keyboards, including DIY, spilt keyboards, and custom layouts. I'm currently learning to touch type my own variant of the inverted Hands Down Promethium layout on a pre-assembled Corne spilt keyboard (and on my laptop). I'd like more pinkie stagger, so perhaps I'll design and build my own keyboard - but I don't like soldering, so am drawn to the diode free designs.

The microcontrollers used in most DIY keyboard designs have at least 17 pins available to connect to keyboard switches. In the simplest designs each pin is connected directly to one key switch, which in a split design is enough for a 34 key layout. But what happens if you want more keys than your available GPIO pins, and you don't want to add diodes? Enter topology and the Heawood Graph, 14 vertices (GPIO pins) and 21 edges (key switches).

Heawood graph, 14 vertices & 21 edges, chain of 6 highlighted

Sunday, 1 February 2015

Ikea ZAISU - Floor chairs for our kotatsu

A year ago I setup a DIY kotatsu using an Ikea LACK coffee table, but never got a proper futon-mat, nor any Japanese style floor chairs to go with it: 座椅子 (ざいす, or zaisu). I'd been seriously pondering importing zaisu chairs when I stumbled on a blog comment suggesting using the top half of an Ikea swivel chair.

So I went back to the Edinburgh Ikea and attempted to check all their chairs to see which (if any) might be used without legs as a simple zaisu. I came home with a pair of Ikea VÅGSBERG swivel chair shells (and nearly bought the Ikea JULES junior desk chair shell as well - a little small for me), and a new thick rug.

Ikea kotatsu & zaisu: LACK coffee table with Metro heater, VÅGSBERG chairs,
ALMSTED rug,  Euro-King size MYSA STRÅ duvet with LYCKOAX cover

Saturday, 6 September 2014

Curious Rover Tracks at Space Expo 2014

This week I enjoyed visiting the Space Expo 2014 "The Great Challenge of NASA/JAXA" which is being held 19 July to 23 September at Makuhari Messe (幕張メッセ) in Chiba, Japan.

1/10 size Saturn V model at Space Expo 2014Space Expo 2014 exhibit floor, with hanging ISS model
Lunokhod ("Moonwalker") modelCuriosity Rover model at Space Expo 2014