As a follow-up to the MacroBoard project I mentioned in the post MacroBoard – Design and Assembly, I will now explain the process of configuring and programming the keyboard and macros.
There are several well-known firmware options for DIY mechanical keyboards, including QMK, ZMK, and KMK. These firmwares run on 8-bit microcontrollers like the ATmega and 32-bit microcontrollers like the ARM. Most of the firmwares are written in C, C++, or Python. After considering the options and evaluating the installation and setup processes, I decided to use KMK Firmware. This firmware runs on CircuitPython, making it easy to set up and edit the code. It’s important to note that all XIAO boards are pin-compatible, so the MacroBoard can be used with any XIAO board that supports CircuitPython (such as the SAMD21, RP2040, or nRF52840).
To start, we flash CircuitPython’s firmware on the XIAO RP2040. The firmware can be found on CircuitPython‘s download page. I found the firmware for my board by searching for ‘Seeed Studio XIAO RP2040’, and the available version at the time was 7.3.3.
To flash the firmware, we simply press the BOOT button while connecting the XIAO board to the computer with a USB cable. The operating system will then detect a new mass storage unit called RPI-RP2. We copy the .uf2 firmware file to this storage unit, and after a few seconds the XIAO will restart and appear as a storage unit called CIRCUITPY.
Next, we go to KMK Firmware‘s GitHub repository and download it as a ZIP file. After decompressing the folder, we copy the
kmk folder and the
boot.py file into the CIRCUITPY unit.
Using a Python editor such as Thonny or Mu, we create a
main.py file and save it in the CIRCUITPY unit. The file must be located in the same folder where we pasted the
boot.py file from the KMK Firmware repository. In this file, we will configure the key mapping, operation layers, and LED animations.
Initially we import the libraries used by the keyboard, some libraries belong to CircuitPython, and others belong to the KMK firmware.
import board from kmk.kmk_keyboard import KMKKeyboard from kmk.keys import KC from kmk.scanners import DiodeOrientation from kmk.extensions.RGB import RGB, AnimationModes from kmk.extensions.media_keys import MediaKeys from kmk.modules.encoder import EncoderHandler
We create a
KMKKeyboard object, this object represents the keyboard’s logic configuration. Then we select the XIAO pins for columns and rows in the key matrix. We also select the diode polarity between the columns and rows to avoid ‘ghost pulses’.
keyboard = KMKKeyboard() # Basic matrix settings keyboard.col_pins = (COL1, COL2, COL3) keyboard.row_pins = (ROW1, ROW2, ROW3) keyboard.diode_orientation = DiodeOrientation.COL2ROW
Then we map the functions to each key using the
keymap attribute. The key mapping should be defined as a matrix following the physical arrangement of the keys on the keyboard.
# Keymap keyboard.keymap = [ [KC.LCTRL(KC.LSHIFT(KC.TAB)), KC.LCTRL(KC.M), KC.LCTRL(KC.TAB), KC.MEDIA_PREV_TRACK, KC.MEDIA_PLAY_PAUSE, KC.MEDIA_NEXT_TRACK, KC.LCTRL(KC.C), KC.LCTRL(KC.V), KC.LGUI(KC.SPACE), ] ]
As the MacroBoard includes a rotary encoder, we can create an
EncoderHandler object to assign the pin-out and the key mapping for the encoder. In the
encoder_handler we assign the actions for the right rotation, left rotation and button activation.
# Encoder settings encoder_handler = EncoderHandler() keyboard.modules.append(encoder_handler) encoder_handler.pins = ((ROTA, ROTB, PUSHBUTTON, False),) encoder_handler.map = (((KC.VOLD, KC.VOLU, KC.MUTE),),)
To control the RGB LEDs we create a
RGB object, in the object we define the pins used to control the addressable LEDs, the amount of LEDs used, and other parameters like brightness, animation or animation speed. Then the object is added to the
keyboard object. To control de RGB LEDs, we need CircuitPython’s NeoPixel library, after downloading the
neopixel.py file we copy it into the CIRCUITPY unit, in the same folder were the
# RGB LEDs settings rgb_ext = RGB( pixel_pin = NEOPIXEL, num_pixels = 9, val_limit = 50, val_default = 50, animation_speed = 1, animation_mode=AnimationModes.RAINBOW, refresh_rate = 30, ) keyboard.extensions.append(rgb_ext)
It’s important to remember the pin-out and the function of each pin, as well as remember the columns and rows order.
At the end we add the condition to run the
go method indefinitely if the program
code.py is running as the main program.
if __name__ == '__main__': keyboard.go()
I also modified the
boot.py file to avoid the XIAO enumeration as a mass storage device, as a virtual serial port or as a midi device when connected to the computer. Also added a parameter that allows the keyboard to be detected while the OS is starting. This kind of configuration implies that the keyboard can’t be configured directly when plugged to the computer using a CircuitPython editor, to enter the configuration mode or the development mode is necessary to keep pressed the encoder push button while the keyboard is being connected to the computer, after that the program and its parameters can be modified using Thonny o Mu.
# If the encoder push-button is held during boot, don't run the code which hides the storage and disables serial and midi button = digitalio.DigitalInOut(board.D0) button.direction = digitalio.Direction.INPUT button.pull = digitalio.Pull.UP if button.value: storage.disable_usb_drive() # Hides device storage usb_cdc.disable() # Disables serial comunication usb_midi.disable() # Disables midi usb_hid.enable(boot_device=1) # Enables keyboard before OS boot button.deinit()
The KMK firmware allow us to set up more functions, and the whole documentation is worth a look. I tested the keyboard on Windows 10 and on macOS Big Sur, and all the commands and functions work flawlessly. The complete configuration code can be found in the repository, and it has the commentaries to make clear each function.
The project files, including the schematic, 3D models, and firmware, can be found on the GitHub repository.
If you have any questions, feel free to ask.
📢 This post is an entry for the Seeed Fusion DIY XIAO Mechanical Keyboard Contest and is partially sponsored by Seeed Studio.