Skip to content

Commit 112bea3

Browse files
Final_Website_Page (#1420)
* Added custom Rust keyboard template * Added KiCad svg and fixed the github link * Removed the useless file * Updated the svg * Updated the svg size * finalized documentation * fixed svg naming * final commit * Added hardware images * Revert "Added hardware images" This reverts commit 4946d7b. * Added the hardware photos * Final Website Version * Fixed the hardware3 size
1 parent ef5dd42 commit 112bea3

3 files changed

Lines changed: 143 additions & 46 deletions

File tree

59 KB
Loading
Lines changed: 142 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Custom Handwired Rust-BLE Keyboard
2-
A fully custom, 3D-printed, Bluetooth split mechanical keyboard built without a PCB.
2+
3+
A fully custom, 3D-printed, Bluetooth split mechanical keyboard built without a PCB, running Rust firmware on nRF52840 microcontrollers.
34

45
:::info
56

@@ -12,87 +13,183 @@ A fully custom, 3D-printed, Bluetooth split mechanical keyboard built without a
1213

1314
## Description
1415

15-
This project is a custom-built, wireless split mechanical keyboard based on the ergonomic Corne physical layout. To maximize hardware complexity and avoid prebuilt kits, the keyboard uses no PCB; instead, the switch matrix is entirely handwired. The core of the project is writing a custom embedded Rust firmware from scratch using the embassy-rs framework to handle matrix scanning, key debouncing, and Bluetooth Low Energy (BLE) communication.
16+
This project is a custom-built, wireless split mechanical keyboard based on the ergonomic **Corne** layout (4 rows × 6 columns per half, plus a 3-key thumb row on each side). There is no PCB: every switch is handwired into a diode matrix and mounted in a 3D-printed plate!
17+
18+
Each half uses a **SuperMini nRF52840** (Adafruit nRF52 Bootloader, UF2 drag-and-drop flashing). The firmware is written in **Rust** and built on the **RMK 0.8** framework with a **dual-binary BLE split** architecture: the left half acts as the **central** (USB/BLE to the PC, full keymap), and the right half acts as the **peripheral** (scans its matrix and sends coordinates over Bluetooth). Configuration lives in `keyboard.toml` (pins, matrix map, three layers).
19+
20+
The original plan was to implement matrix scanning, debouncing, and a BLE HID keyboard stack manually with **embassy-rs** and Nordic’s softdevice bindings. After roughly a week of attempts where the nRF52840 radio/HID path never came together reliably, the project moved to **RMK**, which still uses Embassy and modern Rust async patterns under the hood but provides a proven split-BLE and keymap pipeline.
1621

1722
## Motivation
1823

19-
I chose this project to gain deep, hands-on experience with both bare-metal electronics and modern embedded software. On the hardware side, handwiring the diode matrix forces a complete understanding of how electrical grids operate. On the software side, writing the firmware in Rust provides the opportunity to learn embassy-rs for asynchronous embedded programming and to understand how to implement a BLE HID (Human Interface Device) stack from the ground up. Also I want to some watch movies in the summer on my tv and I need a keyboard to type on the internet so that the search is way faster.
24+
I chose this project to get real experience on both sides of a custom keyboard: bare-metal wiring and modern embedded Rust.
25+
26+
On the **hardware** side, handwiring forces you to understand rows, columns, diodes, ghosting, and how few GPIO pins can serve many keys. On the **software** side, I wanted to learn how a keyboard actually becomes a BLE HID device not just flash someone else’s binary.
27+
28+
A practical goal too: a compact wireless keyboard for the TV/PC so searching and typing away from the desk is faster than a remote.
29+
30+
## Architecture
2031

21-
## Architecture
32+
### Hardware
2233

23-
- The system architecture consists of a custom electrical matrix and an asynchronous Rust software stack.
34+
- **Layout**: Split Corne — 21 keys per half (18 in the main 3×6 grid + 3 thumb keys).
35+
- **Matrix**: 4×6 per half; **1N4148 diodes** (column → row) to prevent ghosting.
36+
- **Controllers**: Two **SuperMini nRF52840** boards (nice!nano v2–class clones).
37+
- **Power**: **3.7 V LiPo** per half with a slide power switch.
38+
- **Structure**: 3D-printed switch plate and case; **24 AWG** solid wire for row/column buses.
2439

25-
- The Hardware Matrix: 42 mechanical switches are handwired into a matrix of Rows and Columns. Diodes are soldered to each switch to prevent electrical "ghosting" when multiple keys are pressed.
40+
### Firmware (final)
2641

27-
- The Microcontroller: An NRF52840 development board acts as the central brain, connected to the matrix rows and columns via its GPIO pins. It is powered by a 3.7V LiPo battery.
42+
| Role | Binary | UF2 output | Responsibility |
43+
|------|--------|------------|----------------|
44+
| Left half | `central` | `NEW_LEFT.uf2` | BLE central, matrix scan (cols 0–5), USB/BLE HID to host, full keymap |
45+
| Right half | `peripheral` | `peripheral.uf2` | BLE peripheral, matrix scan (cols 6–11 via `col_offset = 6`), sends `(row, col)` to central |
2846

29-
- The Rust Firmware: The software utilizes embassy-rs for async execution. A polling task continuously scans the GPIO matrix to detect state changes.
47+
**Pin map (both halves, local wiring)** — inner column toward the split, outer toward the pinky:
3048

31-
- Bluetooth Communication: Using the nrf-softdevice crate, the microcontroller advertises itself as a BLE Keyboard and transmits the processed keystroke data over the air to a host computer.
49+
| Row | MCU pin |
50+
|-----|---------|
51+
| Row 1 (top) | P0_31 |
52+
| Row 2 | P0_29 |
53+
| Row 3 | P0_02 |
54+
| Row 4 (thumb) | P1_15 |
55+
56+
| Col | MCU pin |
57+
|-----|---------|
58+
| Col 1 (inner) | P1_06 |
59+
| Col 2 | P1_04 |
60+
| Col 3 | P0_11 |
61+
| Col 4 | P1_00 |
62+
| Col 5 | P0_24 |
63+
| Col 6 (outer) | P0_22 |
64+
65+
**Keymap (3 layers)** — defined in `keyboard.toml`:
66+
67+
- **Layer 0**: QWERTY Corne base; left thumb `MO(1)` (symbols), right thumb `MO(2)` (nav/F-keys/BT).
68+
- **Layer 1**: Numbers and symbols (`\` `~` `!``[]` `{}`, etc.).
69+
- **Layer 2**: F-keys, arrows, paging, BLE profile/clear (`User1` / `User2` / `User5`), and modifier combos (`WM(...)`) for shortcuts.
70+
71+
**Build & flash**
72+
73+
```text
74+
cargo build --release --bin central → NEW_LEFT.uf2 (left only)
75+
cargo build --release --bin peripheral → peripheral.uf2 (right only)
76+
cargo make uf2 → both UF2 files
77+
```
78+
79+
Family ID for UF2: `0xada52840` (Adafruit nRF52). Flash memory layout reserves the bootloader region (`FLASH` from `0x1000`).
80+
81+
### Software path (what actually happened)
82+
83+
1. **Week ~1 (failed path)**: Custom `embassy-nrf` + softdevice/BLE HID experiments—matrix ideas worked in isolation, but getting a stable BLE keyboard device on the nRF52840 did not, despite many rebuild/flash cycles.
84+
2. **Final path**: **RMK 0.8.2** with `rmk_central` / `rmk_peripheral` macros, `keyboard.toml`, and **Vial-compatible** storage. Minimal application code (`central.rs`, `peripheral.rs`); complexity moved into configuration and build tooling.
3285

3386
## Log
3487

35-
<!-- write your progress here every week -->
88+
<!-- Progress log (~3-day intervals). Hardware and bring-up took the majority of the project time. -->
3689

37-
### Week 5 - 11 May
90+
### 5–8 May
3891

39-
Finalized component research and ordered all necessary hardware (microcontrollers, switches, batteries, keycaps) -> Waiting for their delievery.
92+
Finalized the Corne layout choice and BOM. Ordered SuperMini nRF52840 boards, Gateron Milky Yellow switches, 1N4148 diodes, LiPo cells, wire, keycaps, and power switches. Started the 3D model/plate while waiting on shipping.
4093

41-
### Week 12 - 18 May
94+
### 9–11 May
4295

43-
So far, I've 3D printed the baseplate for the switches to snap into. I went with a hand-wired matrix setup, including diodes for reliable input. I've also soldered a power switch and a battery, which I tested with a multimeter. I connected the columns and one of the rows to the microcontroller just to check the continuity. This is all for the first half of the build; I plan to wrap up the other half later this week.
96+
Parts still in transit. Read nRF52840 docs, Embassy book chapters, and split-keyboard matrix guides. Sketched row/column routing on paper so the handwire would not be guesswork later.
4497

45-
### Week 19 - 25 May
98+
### 12–15 May
4699

47-
## Hardware
100+
Printed the switch plate and case pieces. Began the **left half** handwire: diode orientation (column → row), column buses along the inner edge, first row soldered. Multimeter continuity checks after every few keys—caught one reversed diode early.
48101

49-
The hardware relies on a 3D-printed chassis to hold the switches, eliminating the need for a PCB. The logic is handled by NRF52840 chips due to their low power consumption and excellent Bluetooth capabilities.
102+
### 16–18 May
50103

51-
![KiCad](hardware1.webp)
104+
Finished the left matrix and installed the LiPo + slide switch. Smoke test: power only, then tweezers on row/column pins. Connected one row and one column to the SuperMini to confirm a single intersection could be detected. **Right half not started yet**—wanted one working grid first.
52105

53-
![KiCad](hardware2.webp)
106+
### 19–21 May
54107

55-
### Schematics
108+
Completed **right half** wiring using the same pinout as the left (per-half local row/col numbering). Set up the Rust toolchain (Windows + WSL), `thumbv7em-none-eabihf` target, `flip-link`, and `cargo-binutils`. First flashes used a single-binary approach; behavior was inconsistent on the split.
56109

57-
![KiCad](project_comp.svg)
110+
### 22–24 May
58111

59-
### Bill of Materials
112+
**Hardest software stretch:** tried to implement the keyboard **without RMK**—Embassy executor, GPIO matrix scan, debouncing, and BLE HID using Nordic stack crates (`nrf-softdevice` / related paths). Spent about **a week** here: device would compile and flash, but BLE advertising/HID reports never behaved like a real keyboard on the host. nRF52840 + softdevice + HID from scratch was a wall; pivoted to **RMK** as a maintained framework that already solves split BLE and keymaps.
60113

61-
<!-- Fill out this table with all the hardware components that you might need.
114+
### 25–27 May
62115

63-
The format is
64-
```
65-
| [Device](link://to/device) | This is used ... | [price](link://to/store) |
116+
Regenerated the project around **RMK 0.8** dual binaries (`central` / `peripheral`). Configured `keyboard.toml` (matrix pins, `matrix_map`, BLE addresses). **Left controller** refused to take new firmware for a while (old image kept running); later fixed with proper UF2 flash and `clear_storage`. Right half flashed as `peripheral.uf2` and paired over BLE. Hit Windows path length limits during builds moved/cloned the repo to a shorter path.
66117

67-
```
118+
### 28 May
68119

69-
-->
120+
Left matrix still typed garbage: all keys repeating one character, then a scrambled QWERTY-like grid. Root causes: (1) **stale keymap in flash** (RMK Vial storage overriding `keyboard.toml`), (2) **wiring** not matching the assumed column order. Rewired to the documented pin table; `clear_storage = true` once to prove `keyboard.toml` was live (`Esc` / `Q` test grid). Confirmed **Corne Split** BLE name and stable per-key output.
70121

71-
| Device | Usage | Price |
72-
|--------|--------|-------|
73-
| [SuperMini NRF52840](https://shorturl.at/LceaZ) | The microcontroller | [45 RON](https://shorturl.at/Ukoo9) |
74-
| [Liter Energy 120mAh 3.7V LiPo (401230)](https://shorturl.at/YeYWx) | Power supply | [100 RON](https://shorturl.at/ZWF5S) |
75-
| [Gateron Milky Yellow Pro](https://shorturl.at/b2qIj) | Mechanical linear keyboard switches | [125 RON](https://www.gateron.co/products/gateron-ks-3-milky-pro-switch-set) |
76-
| [1N4148 High-speed Diodes](https://www.vishay.com/docs/81857/1n4148.pdf) | Prevents "ghosting" in the keyboard matrix | [16 RON](https://rb.gy/56u5x7) |
77-
| [24AWG Solid Core Copper Wire](https://www.optimusdigital.ro/en/kits/11950-plusivo-silicone-wire-kit-24awg-6-colors-9m-each-0721248989734.html) | Routing the rows and columns | [24 RON](https://www.aliexpress.com/item/1005010758626132.html?spm=a2g0o.order_list.order_list_main.17.b1b61802RMNohO) |
78-
| [PBT XDA Blank 1U Keycaps](https://ymdkey.com/products/ymdk-black-white-orange-red-gray-blue-beige-xda-1u-keycaps) | The physical key profiles | [58 RON](https://www.aliexpress.com/item/1005010588479682.html?spm=a2g0o.order_list.order_list_main.11.b1b61802RMNohO) |
79-
| [SS12F15VG4 4MM Slide Switches](https://leeselectronic.com/qc/product/31191-slide-switch-chassis-mount-on-on-spdt-1a-125vac.html) | Physical power toggle for the batteries | [36 RON](https://www.aliexpress.com/item/1005010262474497.html?spm=a2g0o.order_list.order_list_main.25.531a1802SqISZa) |
122+
### 29 May
123+
124+
Removed `clear_storage` (kept `clear_layout` while iterating). Implemented full **3-layer Corne keymap** (base, symbols `MO(1)`, nav/F-keys/BT `MO(2)`). Rebuilt `NEW_LEFT.uf2`; left + right halves work together over BLE. **Project functionally complete.**
125+
126+
## Hardware
127+
128+
The hardware relies on a 3D-printed chassis to hold the switches, eliminating the need for a PCB. Logic is handled by nRF52840 SuperMini boards for low power and BLE.
129+
130+
![Handwired build](hardware1.webp)
80131

132+
![Handwired build detail](hardware2.webp)
81133

134+
![Completed keyboard](hardware3.webp)
135+
136+
### Schematics
137+
138+
![Wiring overview](project_comp.svg)
139+
140+
### Bill of Materials
141+
142+
| Device | Usage | Price |
143+
|--------|--------|-------|
144+
| [SuperMini NRF52840](https://shorturl.at/LceaZ) | Microcontroller (one per half) | [45 RON](https://shorturl.at/Ukoo9) |
145+
| [Liter Energy 120mAh 3.7V LiPo (401230)](https://shorturl.at/YeYWx) | Power supply (per half) | [100 RON](https://shorturl.at/ZWF5S) |
146+
| [Gateron Milky Yellow Pro](https://shorturl.at/b2qIj) | Linear switches | [125 RON](https://www.gateron.co/products/gateron-ks-3-milky-pro-switch-set) |
147+
| [1N4148 diodes](https://www.vishay.com/docs/81857/1n4148.pdf) | Anti-ghosting in the matrix | [16 RON](https://rb.gy/56u5x7) |
148+
| [24AWG solid core wire](https://www.optimusdigital.ro/en/kits/11950-plusivo-silicone-wire-kit-24awg-6-colors-9m-each-0721248989734.html) | Row/column harness | [24 RON](https://www.aliexpress.com/item/1005010758626132.html) |
149+
| [PBT XDA 1U keycaps](https://ymdkey.com/products/ymdk-black-white-orange-red-gray-blue-beige-xda-1u-keycaps) | Keycaps | [58 RON](https://www.aliexpress.com/item/1005010588479682.html) |
150+
| [SS12F15 slide switches](https://leeselectronic.com/qc/product/31191-slide-switch-chassis-mount-on-on-spdt-1a-125vac.html) | Battery power switch | [36 RON](https://www.aliexpress.com/item/1005010262474497.html) |
82151

83152
## Software
84153

154+
### Libraries used (final firmware)
155+
85156
| Library | Description | Usage |
86157
|---------|-------------|-------|
87-
| [embassy-rs](https://github.com/embassy-rs/embassy) | Async embedded framework for Rust | The core framework used to run asynchronous tasks (like matrix scanning and Bluetooth handling) without blocking the CPU |
88-
| [embassy-nrf](https://crates.io/crates/embassy-nrf) | Hardware Abstraction Layer (HAL) | Used to safely interact with the NRF52840's physical GPIO pins and timers |
89-
| [nrf-softdevice](https://github.com/embassy-rs/nrf-softdevice) | Rust bindings for Nordic's Bluetooth stack | Used to configure the BLE radio and implement the HID protocol to talk to the PC |
90-
| [defmt](https://github.com/knurling-rs/defmt) | Highly efficient logging framework | Used for debugging the matrix scanning logic over a USB connection |
158+
| [RMK](https://github.com/haobogu/rmk) 0.8 | Rust keyboard firmware framework | Split BLE, keymap, debounce, HID to host; `rmk_central` / `rmk_peripheral` |
159+
| [embassy-rs](https://github.com/embassy-rs/embassy) | Async embedded runtime | Used internally by RMK (GPIO, timers, USB) |
160+
| [embassy-nrf](https://crates.io/crates/embassy-nrf) | nRF52840 HAL | Pin/matrix drivers for SuperMini |
161+
| [nrf-sdc](https://github.com/alexmoon/nrf-sdc) | SoftDevice Controller (Rust) | BLE stack integration for nRF52840 |
162+
| [defmt](https://github.com/knurling-rs/defmt) | Embedded logging | Debug over RTT during development |
163+
164+
### Attempted stack (not used in final build)
165+
166+
| Library | Why it was tried |
167+
|---------|------------------|
168+
| nrf-softdevice (Embassy) | Direct BLE peripheral + HID from scratch |
169+
| Custom HID report code | Pair with hand-rolled matrix scanner |
170+
171+
After ~one week without a reliable BLE keyboard on hardware, these were abandoned in favor of RMK’s proven split and Vial/storage support.
172+
173+
### Repository layout (firmware)
174+
175+
| File | Purpose |
176+
|------|---------|
177+
| `keyboard.toml` | Pins, split BLE addresses, matrix map, layers |
178+
| `src/central.rs` | Left half — BLE central entry point |
179+
| `src/peripheral.rs` | Right half — BLE peripheral entry point |
180+
| `Makefile.toml` | `cargo make uf2` — builds both `.uf2` images |
181+
| `memory.x` | Linker layout for Adafruit bootloader |
182+
| `vial.json` | Vial GUI matrix definition (optional tuning) |
91183

92184
## Links
93185

94-
<!-- Add a few links that inspired you and that you think you will use for your project -->
186+
1. [RMK documentation](https://rmk.rs/docs/)
187+
2. [Embassy book](https://book.embassy.dev/)
188+
3. [Rust Embedded Book](https://docs.rust-embedded.org/book/)
189+
4. [nRF52840 product specification](https://docs.nordicsemi.com/bundle/ps_nrf52840/page/keyfeatures_html5.html)
190+
5. [Corne layout reference](https://github.com/foostan/crkbd) — physical key arrangement inspiration
191+
6. [Adafruit nRF52 Bootloader](https://github.com/adafruit/Adafruit_nRF52_Bootloader) — UF2 flashing on SuperMini
192+
193+
## Status
95194

96-
1. [Embassy-rs Documentation](https://embassy.dev/)
97-
2. [Rust Embedded Book](https://docs.rust-embedded.org/book/)
98-
3. [NRF52840 Product Specification](https://docs.nordicsemi.com/bundle/ps_nrf52840/page/keyfeatures_html5.html)
195+
**Complete.** Both halves type over BLE with a three-layer Corne keymap. Future tweaks are `keyboard.toml` edits + reflash `NEW_LEFT.uf2` on the central only; the peripheral only needs a reflash if matrix pins or BLE pairing metadata change.

website/versioned_docs/version-fils_en/project/2026/eduard.constantin05/project_comp.svg

Lines changed: 1 addition & 1 deletion
Loading

0 commit comments

Comments
 (0)