How To: Split Keyboard met RP2040 en KMK
Laatst bijwerkt op zaterdag 12 november 2022.
In mijn vorige blogpost heb ik uitgelegd hoe ik mijn macropad heb gemaakt. In die post hintte ik dat een split keyboard wil maken, specifiek de Redox v1, maar dat heb ik niet gedaan. Ik heb niet een split keyboard gemaakt, ik heb er ondertussen al 2 gemaakt.
De eerste versie van mijn keyboard kon niet los van elkaar gemaakt worden. De rijen en kolommen zijn direct aan elkaar gesoldeerd met 12 kabels die buiten de case om gaan, zoals je kan zien op de foto hieronder. Ik heb hiervoor gekozen omdat de documentatie om een RP2040-based microcontroller, zoals de Raspberry Pi Pico, te gebruiken als een split keyboard extreem onduidelijk was. Voor de eerste versie was het vooral belangrijk dat ik snel op een toetsenbord kon typen en kon wennen aan de nieuwe layout.
Bill of Materials
Om alles te maken heb ik gebruik gemaakt van de Laser cutter van de Maakplek en mijn 3d printer. Als je alleen een 3d printer hebt, kan je de gelinkte modellen gebruiken die ik als “Case” heb toegevoegd, en eerlijk, ik zou het aanraden om de bovenste plaat ook te printen. Met een laser kan je niet de indents maken die nodig zijn voor de Choc switches om goed vast te pakken, waardoor sommige keys nogal los zitten.
Components | Price |
---|---|
70x switches | €34,21 |
70x diodes | €5,- /100 |
2x Jackplug TRRS mount | €8,90 |
TRRS cable | €5,95 |
24 AWG single-core and stranded wires | €5ish |
2x RP2040 based microcontrollers | €9,00 |
Legended MBK Choc Low Profile Keycaps (alpha) | €29,85 |
Legended MBK Choc Low Profile Keycaps (mods) | €31,94 |
Case | ¯\( ツ )/¯ |
Threaded Inserts set - 10x M3, 4x M5 | |
Total | €129,85 |
Wiring Diagram
Een van de belangrijkste redenen waarom ik deze post schrijf, is dat ik veel te veel moeite had om uit te vinden hoe je de 2 microcontrollers met elkaar moest verbinden. Wat nog frustrerender was, was dat mijn eigen blogpost over mijn macropad steeds als eerste kwam in searches voor “split keyboard pi pico” omdat ik in de intro het had over split keyboards bouwen (#SufferingFromSuccess). In ieder geval dus ook voor Future Sander, om een Raspberry Pi Pico of andere RP2040-based microcontrollers met elkaar te laten praten via UART, verbind je een GND pin, de 3V3 pin (voor stroom), een TX0 pin (in dit geval GP0, voor de transfer) en een RX0 pin (GP1, voor het ontvangen van data) naar dezelfde pins op de andere controller.
In de schema’s heb ik steeds maar 1 kant verbonden om het duidelijker te maken, maar hou er rekening mee dat je voor beide kanten zowel de rijen als de kolommen moet verbinden met de microcontroller.
Voor de rijen had ik geen zin meer om de isolatie exact te knippen, dus heb ik gewoon de draadjes van de diodes aan elkaar gesoldeerd. Dit heeft om eerlijk te zijn veel minder problemen gegeven dan ik had gedacht, en maakte het verbinden van de rijen naar de microcontroller veel makkelijker, en misschien zelfs stabieler.
Met het verbinden van de rechter Pi Pico heb ik de rijen verkeerd om verbonden. Gelukkig is dit makkelijk in de firmware te fixen door de rijen achterstevoren te defineren, maar daardoor is de firmware die ik run wel iets anders dan degene die ik hieronder heb gedeeld.
Firmware
De code is het makkelijkste onderdeel van het project. De documentatie hoe je KMK gebruikt is fantastisch, waardoor het vooral copy-paste werk is. Omdat deze post niet onnodig lang te maken, skip ik het installatie proces van CircuitPython en KMK. Wil je hier meer over weten, kijk dan in de Getting Started guide van KMK
Wat belangrijk is, is dat de microcontrollers een speciale naam nodig hebben. De Pico die de linkerkant aanstuurt, moet eindigen met de letter “L”, bijvoorbeeld “REDOXL”. De rechter Pico moet een naam hebben die eindigt op een “R”, dus “REDOXR”. Ook mag de naam niet langer dan 11 karakters lang zijn. Weet je niet hoe? Adafruit heeft een post waar ze uitleggen hoe je een CircuitPython Drive renamed.
In de firmware hieronder moet nog wel een aanpassing gemaakt worden. Wanneer je de firmware voor de rechterkant upload, moet je split_side=SpliSide.LEFT
vervangen voor split_side=SplitSide.RIGHT
.
# main.py
print("Starting")
import board
from kmk.kmk_keyboard import KMKKeyboard
from kmk.keys import KC
from kmk.scanners import DiodeOrientation
from kmk.modules.split import Split, SplitType, SplitSide
from kmk.modules.layers import Layers
from kmk.extensions.RGB import RGB, AnimationModes
keyboard = KMKKeyboard()
keyboard.modules.append(Layers())
# Using drive names (REDOXL, REDOXR) to recognize sides; use split_side arg if you're not doing it
split = Split(split_type=SplitType.UART, split_side=SplitSide.LEFT, data_pin=board.GP0, data_pin2=board.GP1, use_pio=True, uart_flip = True)
#split = Split(split_type=SplitType.UART, split_side=SplitSide.RIGHT, data_pin=board.GP0, data_pin2=board.GP1, use_pio=True, uart_flip = True)
keyboard.modules.append(split)
keyboard.row_pins = (board.GP20, board.GP19, board.GP18, board.GP17, board.GP16)
keyboard.col_pins = (board.GP12, board.GP11, board.GP10, board.GP9, board.GP8, board.GP7, board.GP6)
keyboard.diode_orientation = DiodeOrientation.COL2ROW
# Cleaner key names
_______ = KC.TRNS
XXXXXXX = KC.NO
FnKey = KC.MO(1)
keyboard.keymap = [
# Base Layer
[
# COL GP28 COL GP27 COL GP26 COL GP22 COL GP21 COL GP20 COL GP19 <> COL GP18 COL GP17 COL GP16 COL GP14 COL GP13 COL GP12 COL GP11
KC.ESCAPE, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.EQUAL, KC.MO(1), KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.MO(2),\
KC.MEH, KC.Q, KC.W, KC.E, KC.R, KC.T, KC.LBRACKET, KC.RBRACKET, KC.Y, KC.U, KC.I, KC.O, KC.P, KC.MINUS,\
KC.TAB, KC.A, KC.S, KC.D, KC.F, KC.G, XXXXXXX, XXXXXXX, KC.H, KC.J, KC.K, KC.L, KC.SCOLON, KC.QUOTE,\
KC.LSHIFT, KC.Z, KC.X, KC.C, KC.V, KC.B, KC.LALT, KC.MO(2), KC.N, KC.M, KC.COMMA, KC.DOT, KC.SLASH, KC.RSHIFT,\
KC.LGUI, KC.GRV, KC.BSLASH, KC.LALT, KC.LCTRL, KC.SPACE, KC.MO(1), KC.ENTER, KC.BSPACE, KC.MO(2), KC.LEFT, KC.RIGHT, KC.UP, KC.DOWN,\
],
# M1 Layer
[
# COL GP28 COL GP27 COL GP26 COL GP22 COL GP21 COL GP20 COL GP19 <> COL GP18 COL GP17 COL GP16 COL GP15 COL GP14 COL GP13 COL GP12
_______, KC.F1, KC.F2, KC.F3, KC.F4, KC.F5, KC.F6, _______, KC.F7, KC.F8, KC.F9, KC.F10, KC.F11, KC.F12, \
_______, KC.EXLM, KC.AT, KC.HASH, KC.DOLLAR, KC.PERCENT, _______, _______, _______, KC.LALT(KC.LEFT), KC.UP, KC.LALT(KC.RIGHT), _______, _______, \
_______, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, XXXXXXX, XXXXXXX, _______, KC.LEFT, KC.DOWN, KC.RIGHT, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
],
# M2 Layer
[
# COL GP28 COL GP27 COL GP26 COL GP22 COL GP21 COL GP20 COL GP19 <> COL GP18 COL GP17 COL GP16 COL GP15 COL GP14 COL GP13 COL GP12
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN, _______, \
_______, _______, _______, _______, _______, _______, XXXXXXX, XXXXXXX, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
],
]
if __name__ == '__main__':
keyboard.go()
Finishing Touches
Op dit moment moet je een werkend toetsenbord hebben. Aan toetsenborden valt eindeloos te tweaken, zo kan je bijvoorbeeld het toetsenbord in een comfortabelere houding zetten met tenting (de bouten). Of bij twijfel, gooi het vol met RGB-strips. Dat allemaal ga ik niet behandelen in deze how-to guide, maar Google is je beste vriend!