Skip to the content
2 layers181.6 × 172.3 mmPMK Keyboard, the printed circuit board in 3D

PMK Keyboard

PumaFPV/PMK4

PMK - Full wireless split keyboard

Size
181.6 × 172.3 mm
Copper layers
2
Thickness
1.6 mm
Parts
151
Nets
165
Pads
1,140
Tracks, vias
2,416, 458
Pours
17
Routed
Yes
KiCad
KiCad 7 (file 20221018)
Created
7 Nov 2022
Updated
28 May 2026

Overview

PMK Keyboard is an open-source printed circuit board by PumaFPV, from the PumaFPV/PMK repository on GitHub, published under the MIT licence. It is a 2-layer board of 181.6 × 172.3 mm with 151 parts on 165 nets, routed with 2,416 tracks and 458 vias.

It is built around the ESP32-S2FH4, SN74HC165PWRG3 and MIC5528-3.3YMT-T5, with the SKRPABE010, 2450AT18A100E and USB4510-03-1-A among its other parts. Its parts include 43 diodes, 42 switches, 23 capacitors, 18 resistors and 9 ICs. It belongs with the keyboards and input boards and the ESP32 boards of this library.

Main components

6

README

README.md

Puma Mechanical Keyboard

PMK - a full wireless HID ecosystem for split keyboards and other fun devices

The goal is to make a suit of wireless devices such as "smart keyboard" (combined mouse and keyboard), gamepad, LEDs, knobs, display, etc
The first step is to make a wireless split keyboard, and then we will see later...

Currently, you can connect up to 8 (software limited) devices per dongle, each of them having up to 8 (software limited) layers. Layers only affect keyboards and LED.

Dongle

The dongle is "master" ESP32S2/S3, appears as HID (keyboard, mouse and joystick) and as Mass Storage device Class with config files inside. Maybe also store password manager later...

As the dongle is the master of PMK, it hosts the config files for each devices. Here is the expected file organisation:

text
	|--deviceName1  
	|  |- deviceName1.json  
	|  |--keyboard  
	|  |  |- kb-l1.json  
	|  |  |- kb-l2.json  
	|  |--led  
	|  |  |- led-l1.json  
	|  |  |- led-l2.json  
	|--deviceName2  
	|  |- deviceName2.json  
	|  |--keyboard  
	|  |  |- kb-l1.json  
	|  |  |- kb-l2.json  

Exemple file structure can be found here

For more details about devices configurations / capabilities check the Protocol chapter.

Keyboard config file - HID codes

Check out the PMK HID keyboard keycodes.md for more information on which code corresponds to which key.

Devices

Can run on any espressif chip that can run ESP-NOW. (I will later add support for nRF52 chips for lower power consumption, but it will be incompatible with ESP32 hardware) The plan is to run the simplest firmware on all devices and being able to configure them via their corresponding .json files on the master dongle. Each device should be configurable via UART (set device ID, set dongle MAC address, and read device MAC address). See sample device code for example. (Needs an update)

Keyboard

For example a keyboard would send pressed keys number "0x04, 0xA1", which the dongle then reads in the .json as coordinates for returning desired key "a,b", if special key is pressed (volume up, brighntess control...) then do the appropriate consummer control action. Keys are read with 74HC165 shift registers so theoratically you could have A LOT of keys per keyboard. Current limitation is the max value of keyID which is 255, so there could be a maximum of 255 keys per keyboard (+8 layers...). For more information about the hardawre, check the hardware section. A casing is being designed, it is 3D printable. As foam grid is put inside for better sound (I think it is better?). It support module on the thumb side (Circle trackpad and 3D mouse). Both modules have been tested and work. See Space mouse section for more info.

Mouse

Mouse can send x,y movement, wheel, pan scrolling and mouse buttons (left, middle, right, forward, backward). Each button is encoded as a bit in the "key" byte of the packet. No configuration needed on the dongle appart from the DPI setting. I plan on retro fitting a wired Logitech G300 with PMK so that it frees up a USB port + becomes wireless. It will be a great first POC. I also have a M330 laying around. It might also end up as a PMK mouse.

Gamepad

Gamepad can send 2 analog joysticks, 2 analog triggers, dpad buttons, and 32 additionnal buttons. No additionnal configuration needed on the dongle. I current upgraded an old thrustmaster sim set (FCS & WCS) from 1992 with PMK. They used to have an ADB port, but now both are fully wireless and appear as one gamepad on the computer. The update is a bit crude as it was first though as a POC for trying out the gamepad feature. But since it works fine, I kept it this way.

LED

(For release 1.2.0) Hopefully processing key press and led function on dongle and send data to device is fast enough, otherwise I will have to run led function on keyboard. (TODO) Buildin keyboard functions: all kb, breath, swipe wave (single color or rainbow), key wave, single key... (TODO / Partially implemented...) Uses the WS2812 kind of LED IC.

Knob

Knobs are in absolute position going from 0 to 255. Could be used for Deej (now only used for deej).

For encoder knobs, this is handled on the device, so it can enumerate as a keyboard pressing one key for clockwise and another for counterclockwise rotation. But it could also be treated as an absolute position depending on the device software.

Space mouse

The software is mostly inspired from Magellan and from reports analysed from a 3DConnexion Space mouse with hid-tool. The current electronics and plastics hardware are from OS3M mouse and it works well. The software still needs some adjustements for calibration. Note: If standard VIK connector is needed, PCB has to be flipped. No special hardware modifications are needed.

Protocols

ESP-NOW - Device to Dongle

This is the packet sent via ESP-NOW. Packet structure is:

Byte123-16
DescriptionDeviceIDPacketIDPayload

The goal of this packet strucure is that the dongle knows who is sending data and what kind of data to expect from the payload. The deviceID is mostly used for keyboards and mouse to use the corresponding config files.

the payload's goal is to send data as simple as possible, e.g. keyboard sends key IDs pressed (max 8 at a time) and then the dongle processes the key ID depending on the json configuration

Packet IDPacket typePacket informationNumber of bytesExample packetExample description
0x00TelemetrySend battery voltage, temperature, mac address, errors...15dID 00 battery temperature address[6] err err err err err
0x01Keyboard1 byte = 1 key ID8dID 01 A2 34 DB 32 21 4F 00 006 keys are pressed
0x02Mousemove x, move y, wheel, pan, mouse clicks7dID 02 xx yy ww pp kkmove x relative, move y relative, move w relative, move p relative, kk key press
0x03Gamepad2 joysticks, 2 analog triggers, 9 directions d pad, 32 buttons12dID 03 xx yy zz rz rx ry hh bb bb bb bb bb
0x04LEDChoose pre defined function, and R, G and B8dID 04 func ledNumberStart ledNumberEnd Red Green Blue
0x05Knob / Rotary encoder / potentiometereach byte is a pot value, max 8 pot per MCU10dID 05 FF 00 FF 00 FF 00 FF 004 pots are at max, 4 are at min
0x06ActuatorChoose command type (torque, speed, position)5dID 06 01
0x07Displaysend image to display using wifi for faster refresh rate? or store on local mem6dID 07 imgNumber x y brightnessDisplay img number n at coordinates x,y and brightness b. Might change later
0x08Serialsend up to 8 bytes of data10dID 08 aa bb cc dd ee ff gg hhSending 8 bytes of data
0x09SpaceMousesend 3 bytes for translation (x, y, z) and 3 bytes for rotation (x, y, z), signed intergers6dID 7F 00 00 FF 00 00Positive translation on x and negative rotation on x

Serial config - Dongle to PC

The dongle supports a few serial commands, they only consist of a string, no CR/LF should be send or the command won't be recongnised. (The received command is hashed into a number then switched cased to the correct function) Here is the list of supported commands:

  • h / help : display available commands
  • info : display all info
  • macaddress / getmacaddress : display dongle MAC address
  • version : display build date and version
  • power : display RF Tx power
  • cpu : display cpu info
  • format : format file system
  • restart / reboot : restart the dongle
  • deej : toggle on / off deej
  • config / load: Reload configuration files
  • l0 / l1 / l2... : Force the current layer to... If one keybind moves to new layer it will be ignored use l-1 command to reset force layer
  • l-1 : disable forced layer
  • debug1 / debug2... : Toggle debug output. Different kind of debug available

Serial config - Device to PC

Before being able to communicate with the dongle, the device has to know the dongle MAC address, and must own a deviceID. You will also need to know the device MAC address to give it to the dongle. Here is the list of supported commands:

  • h / help : returns available commands
  • info : display all info
  • macaddress / getmacaddress : returns device MAC address
  • setdonglemacaddress : update dongle MAC address, be sure to send values in HEX mode
  • getdonglemacaddress : returns the current dongle MAC address
  • setdeviceid : update deviceID to new value
  • getdeviceid : returns currently set devi
  • version : returns build date and version
  • power : returns RF Tx power
  • cpu : returns CPU info
  • setcpufreq : set new CPU frequency
  • restart : restart the dongle
  • scan : Scan for side module presence
  • debug1 / debug2... : Toggle debug output. Different kind of debug available

Hardware

The dongle

Dongle is still HW00 (first rev), it needs 3 small patches to work properly. A HW01 is designed but hasn't been ordered yet. The ESP32S2 has some limitations, so a ESP32S3 dongle is being made too here.

Even a nRF52 dongle might be made... Who knows?

The keyboard

As of today the keyboard is at the HW02 stage, and uses the sofle layout (which I do like). It uses 29 hot swappable Kailh Choc switches + one rotary encoder. The MCU is a PSoM module (homemade SoM) with an ESP32S2 inside. The SoM allows for quick swap of different MCU to try out different feature. Today the ESP32S2 is used for the ease of software developpement. Its power consumption is bad I am aware. But at least software works. Here is the changelog.

HW revchange list
HW00Based on moonlander layout, integrated ESP32, used as a proof of concept, didn't like the layout in the end
HW01Based on Sofle, PSoM connector (swappable uC for futur proofing), added rotary encoder, way better layout in my opinion. Added side connector option for trackpad or space mouse
HW02Still soffle, added support for kailh choc V2 (failed), moved the rotary encoder up, added debouncing for rotary encoder, fixed the side module connector, moved test point to accessible location, updated PSoM pinout for better compatibility
HW03 (WIP)Still soffle, fixed the silkscreen, Added slot for dongle, fixed V2 footprint, magnetic pogo module?

More info on Notion

Edit the PCBs

If you want to make your own keyboard, or visualize current dongle, keyboard or other devices you will need KiCAD 8 and Component_lib which is my own components library. It can be found in its own repo, information on own to install it can be found there.

Building

This whole project is built using PlatformIO on VS Code / VS Codium. (If using VS Codium note that the marketplace for extensions doesn't really work, you will need to download cpp and platformIO .vsix extension files from https://marketplace.visualstudio.com/vscode)

Once this is installed you can clone PMK's repo git clone https://github.com/PumaFPV/PMK and open whichever code you want to build / modify: PMK/Software/PMK_keyboard with platformIO "Open project".

Once project is opened and loaded (might take a few minutes for the first time) (it needs internet connection to download library and toolchain) you can compile with ctrl + shift + B or ctrl + shift + U to compile and upload, or use the bottom ribbon (make sure to select the correct workspace before compiling and uploading).

Parts

151
QtyValueFootprintReferences
40YF923_2020_WS2812_LEDComponent_lib:YF923_2020_WS2812_LED_DUALSIDED601, D602, D603, D604, D605, D606, D607, D608, D609, D610, D611, D612, D613, D614, D615, D616 +24
39SW_PushComponent_lib:Kailh_socket_PG1350_reversibleSW502, SW503, SW504, SW505, SW506, SW507, SW508, SW509, SW510, SW511, SW512, SW513, SW514, SW515, SW516, SW517 +23
9100nCapacitor_SMD:C_0402_1005MetricC403, C404, C405, C408, C411, C412, C414, C415, C416
5EXB-2HV103JVComponent_lib:EXB2HV_1RN501, RN502, RN503, RN504, RN505
5SN74HC165PWRComponent_lib:SOP65P640X120-16NU501, U502, U503, U504, U505
42u2Capacitor_SMD:C_0603_1608MetricC301, C302, C303, C304
4nuResistor_SMD:R_0201_0603MetricR405, R406, R407, R408
3LEDComponent_lib:LED_0402_1005Metric_DUALSIDED201, D202, D401
210kResistor_SMD:R_0201_0603MetricR403, R404
215pCapacitor_SMD:C_0201_0603MetricC401, C402
21k5Resistor_SMD:R_0402_1005MetricR205, R206
21uCapacitor_SMD:C_0402_1005MetricC410, C413
24u7Capacitor_SMD:C_0603_1608MetricC201, C203
25.1kResistor_SMD:R_0201_0603MetricR101, R102
2CCapacitor_SMD:C_0201_0603MetricC406, C407
2LOGOComponent_lib:puma_logo_14mmG***, G***
2MIC5528-3.3YMT-T5Component_lib:SON40P120X120X60-7N-DU301, U302
2SKRPABE010Component_lib:SKRPABE010S401, S402
10Resistor_SMD:R_0201_0603MetricR401
10Resistor_SMD:R_0402_1005MetricR201
10kResistor_SMD:R_0201_0603MetricR301
1100kResistor_SMD:R_0402_1005MetricR207
110uCapacitor_SMD:C_0603_1608MetricC409
11k1Resistor_SMD:R_0402_1005MetricR204
11uCapacitor_SMD:C_0603_1608MetricC202
12450AT18A100EComponent_lib:ANTC3216X140NANT401
12kResistor_SMD:R_0402_1005MetricR402
136k5Resistor_SMD:R_0402_1005MetricR202
1590Resistor_SMD:R_0402_1005MetricR203
1BQ24075RGTRComponent_lib:QFN50P300X300X100-17N-DU201
1Battery_CellComponent_lib:BatteryHolder_Keystone_1042_1x18650_DUALSIDEBT101
1Conn_01x03_SocketConnector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_VerticalJ402
1Conn_01x08_FemaleConnector_PinHeader_1.27mm:PinHeader_1x08_P1.27mm_VerticalJ401
1Crystal_GND24_SmallComponent_lib:Crystal_SMD_2016-4Pin_2.0x1.6mmY601
1ESP32-S2FH4Component_lib:QFN40P700X700X90-57N-DU401
1LInductor_SMD:L_0201_0603MetricL401
1LOGOComponent_lib:pmk-v1-noFN_180mmG***
1SW_PushComponent_lib:SKRPABE010SW501
1TestPointTestPoint:TestPoint_Pad_D1.0mmTP201
1USB4510-03-1-AComponent_lib:USB4510031AJ101

More from PumaFPV/PMK

7
  • 2 layers145 × 111.8 mmPMK Keyboard HW01, the printed circuit board in 3D

    PMK Keyboard HW01

    PumaFPV/PMK

    PMK - Full wireless split keyboard

    88 parts4MIT
  • 4 layers10.4 × 15.4 mmPMK Dongle HW01, the printed circuit board in 3D

    PMK Dongle HW01

    PumaFPV/PMK

    PMK - Full wireless split keyboard

    37 parts4MIT
  • 2 layers61.3 × 60.8 mmPMK SpaceMouse 01, the printed circuit board in 3D

    PMK SpaceMouse 01

    PumaFPV/PMK

    PMK - Full wireless split keyboard

    37 parts4MIT
  • 4 layers10.4 × 18.3 mmPMK Dongle, the printed circuit board in 3D

    PMK Dongle

    PumaFPV/PMK

    PMK - Full wireless split keyboard

    32 parts4MIT
  • 4 layers10.4 × 15.4 mmPMK Dongle S3 HW00, the printed circuit board in 3D

    PMK Dongle S3 HW00

    PumaFPV/PMK

    PMK - Full wireless split keyboard

    27 parts4MIT

Similar boards

  • 6 layers26.3 × 27.6 mmESP S2 SoM HW00, the printed circuit board in 3D

    ESP S2 SoM HW00

    PumaFPV/PSoM

    PSoM, either Pico System On Module, or Puma System On Module for those who prefer

    58 parts1MIT
  • 4 layers130 × 40 mmPumaTX MB HW00, the printed circuit board in 3D

    PumaTX MB HW00

    PumaFPV/PumaTX

    DIY FPV Remote controller based on the one from the mavic

    121 parts4MIT
  • 4 layers233.4 × 147.3 mmOpenPLC Hardware, the printed circuit board in 3D

    OpenPLC Hardware

    gasiepgodoy/Open-Source-PLC

    Open Source Programmable Logic Controller (Hardware and Software). Based on the Master of Science in Electrical Engineering of João Vitor Rocha Santana

    494 parts2
  • 4 layers65 × 100 mmMacropad, the printed circuit board in 3D

    Macropad

    mcskny/wireless-he-macropad

    A wireless, 12-key Hall-effect macropad built around a custom PCB, an ESP32-C6 sender, an ESP32-S3 USB receiver, and a native macOS companion app.

    165 partsGPL-3.0
  • 4 layers10.5 × 26.7 mmESP32-IoT Board ChipAnt, the printed circuit board in 3D

    ESP32-IoT Board ChipAnt

    ollieelliot/ESP32-IoT-Board

    Challenging myself to make a tiny IoT device. Currently 22.8 mm in diameter, ~45 components, 2.4 Ghz chip antenna, microphone, temperature sensor, ESP32-C3 and LiPo charger circuit.

    51 parts1
  • 4 layers40 × 55 mmCopterCat cm4, the printed circuit board in 3D

    CopterCat cm4

    matveylapin/CopterCat_cm4

    Полётный контроллер для стандарта FMU-v6u. Обычно на дронах для программирования устанавливают полётный контроллер, одноплатный компьютер и иногда arduino.

    164 parts3Apache-2.0
  • 2 layers30 × 14 mmEsp32s2-uart, the printed circuit board in 3D

    Esp32s2-uart

    TDA-2030/esp32s2-usb-uart

    USB to UART by ESP32-S2

    51 parts3Apache-2.0
  • 4 layers288 × 135.4 mmKeyboard v2, the printed circuit board in 3D

    Keyboard v2

    ben5049/Keyboard

    Features: - Wireless - 900mAh battery - Bluetooth (nRF52) - ZMK - 4 Port USB hub - BLDC Knob for haptic feedback - Kailh Choc V1 switches

    344 parts1Apache-2.0

Questions

How big is the PMK Keyboard PCB?

It measures 181.6 × 172.3 mm and has 2 copper layers, 1.6 mm thick.

What parts does the PMK Keyboard use?

151 parts, built around the ESP32-S2FH4, SN74HC165PWRG3, MIC5528-3.3YMT-T5 and SKRPABE010. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the PMK Keyboard KiCad files?

From the PumaFPV/PMK repository on GitHub, at the commit this page was made from: the board is Hardware/PMK_Keyboard/PMK_Keyboard_HW00/PMK_Keyboard.kicad_pcb and its schematic Hardware/PMK_Dongle/PMK_Dongle_C_nRF_HW00/PMK_Dongle_C_nRF_HW00.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the PMK Keyboard design in my own project?

Its repository publishes it under the MIT licence: you may reuse it on that licence's terms (keep the author's notice, and for a copyleft licence share your changes alike).