Projects Arduino

Flux — Mechanical Macropad

A hot-swappable 12-key macropad with per-key RGB, an OLED layer display, dual rotary encoders, and QMK firmware on an RP2040 — custom PCB, printed case.

Shipped since Apr 2025 #mechanical-keyboard#rp2040#qmk#pcb-design
12
Keys
2
Rotary encoders
3
PCB revisions
1 ms
Scan rate

Flux exists because I kept reaching for the same fifteen shortcuts in Fusion 360 and my IDE, and because I had never designed a PCB before. A 12-key macropad is the ideal first board: small enough to fail cheaply, complex enough to be a real design — matrix wiring, addressable LEDs, an I2C display, USB routing.

The board

The PCB is a two-layer design in KiCad around a bare RP2040 rather than a Pi Pico module, mostly to force myself to deal with the hard parts: the 12 MHz crystal layout, the W25Q16 flash, USB differential pair routing, and the 3.3 V regulator. The 12 keys sit in a 4x3 matrix (4 rows, 3 columns, one diode per key), Kailh hot-swap sockets on the back, and SK6812 Mini-E LEDs shine through a cutout in each socket footprint. Two EC11 encoders and the SSD1306 OLED live on a raised top row.

Rev 1 had the hot-swap socket footprint mirrored — sockets mount on the bottom of the board, and I had drawn them from the top view. Rev 2 fixed that but put the USB shield ground on the wrong net. Rev 3 works. Three revisions at about $9 per batch of five boards was cheap tuition.

Matrix scanning and the OLED

Firmware is stock QMK with a custom keyboard definition. QMK handles debouncing and matrix scanning at a 1 ms rate; my code mostly lives in the OLED task, which renders the active layer, a WPM counter, and the current encoder mode:

bool oled_task_user(void) {
    oled_write_P(PSTR("Layer: "), false);
    switch (get_highest_layer(layer_state)) {
        case _BASE:  oled_write_ln_P(PSTR("BASE"), false); break;
        case _CAD:   oled_write_ln_P(PSTR("CAD"),  false); break;
        case _MEDIA: oled_write_ln_P(PSTR("MEDIA"), false); break;
    }
    return false;
}

The per-key RGB doubles as a layer indicator too — the CAD layer lights the view-control keys blue, which turned out to be more useful than the OLED for at-a-glance state.

What I’d do differently

Ghosting never showed up thanks to the diodes, but I initially scanned columns with a 10 µs settle delay that was too short for the long traces near the encoders, producing phantom presses on one column. Bumping the delay fixed it; routing the matrix more compactly would have been the real fix. Rev 4 will also add ESD protection on USB — the current board survives on luck.

Development timeline

  1. 2025-04

    Schematic and layout

    First KiCad board sent to JLCPCB after a week of datasheet reading.

  2. 2025-05

    Rev 1 arrives

    Booted, typed, and taught me two hard lessons about footprints.

  3. 2025-06

    Rev 3 + case

    Clean board, printed case with heat-set inserts, QMK merged into my fork.

  4. 2025-07

    Daily driver

    Living next to my keyboard running shortcut layers for CAD and the IDE.