Saltar al contenido

MacroBoard – Configuración

  • PROYECTO

Continuando con el proyecto del teclado mecánico que diseñé en la entrada MacroBoard – Diseño y Ensamble, usaré esta entrada para hablar sobre el proceso de programación y configuración del teclado y los macros.

Actualmente se pueden encontrar varios firmwares para los teclados mecánicos o los macropads, los más conocidos son QMK, ZMK y KMK. Estos firmwares suelen funcionar en controladores de 8 bits como los ATmega y de 32 bits como los ARM, además de estar basados en diferentes lenguajes de programación. Luego de revisar los procesos de instalación y configuración decidí usar KMK Firmware, que trabaja sobre CircuitPython lo que hace todo el proceso de configuración más sencillo. Conviene tener en cuenta que todas las tarjetas XIAO son compatibles en los pines, así que el MacroBoard podría usarse con cualquiera de las tarjetas XIAO que soporten CircuitPython (SAMD21, RP2040, nRF52840).

Para comenzar se debe instalar CircuitPython en el XIAO RP2040, el firmware se puede encontrar en la página de descargas de CircuitPython, el firmware de la tarjeta se puede encontrar buscando por ‘Seeed Studio XIAO RP2040’, en mi caso estaba disponible la versión 7.3.3.

Para cargar el firmware al controlador sólo es necesario mantener presionado el botón BOOT mientras se conecta el XIAO al computador, en ese momento el sistema operativo detecta una nueva unidad de almacenamiento llamada RPI-RP2, en esta unidad debemos pegar o arrastrar el archivo uf2 con el firmware de CircuitPython, la tarjeta se reinicia automáticamente y ahora debe aparecer una unidad llamada CIRCUITPY.

Después de instalar CircuitPython debemos ir al repositorio de KMK Firmware y descargar todo el repositorio como una carpeta comprimida. Después de descomprimir los archivos tenemos que copiar la carpeta kmk y el archivo boot.py en la unidad CIRCUITPY.

Ahora, usando un editor para Python como Thonny o Mu debemos crear un archivo code.py o main.py, y guardarlo en la unidad CIRCUITPY, el archivo debe quedar en la misma carpeta en donde pegamos el archivo boot.py del repositorio de KMK Firmware. En este archivo vamos a tener toda la configuración del mapeo de las teclas, las diferentes capas de operación e incluso las animaciones de los LEDs.

Para la configuración inicial tenemos que importar algunas librerías de CircuitPython y las librerías de KMK dependiendo de las funciones que vamos a asignar al teclado.

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

Luego creamos un objeto de la clase KMKKeyboard, este objeto representa la configuración lógica del teclado. Después de crear el objeto indicamos los pines del XIAO usados en las columnas y filas del teclado, así como la polaridad de los diodos ubicados en la matriz para evitar los ‘pulsos fantasmas’.

keyboard = KMKKeyboard()

# Basic matrix settings
keyboard.col_pins = (COL1, COL2, COL3)
keyboard.row_pins = (ROW1, ROW2, ROW3)
keyboard.diode_orientation = DiodeOrientation.COL2ROW

Después de la definición de los pines, debemos mapear la función para cada una de las teclas en el atributo keymap. La definición se debe hacer como una matriz, de acuerdo con la configuración física del teclado.

# 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),
    ]
]

También creamos un objeto EncoderHandler para manejar las acciones de la rotación del encoder y de la activación del botón del encoder. Al igual que con el objeto keyboard, en el encoder_handler también definimos los pines a los que está conectado el encoder y el mapeo de la rotación a la derecha, a la izquierda y la activación del botón.

# 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),),)

Para controlar los LEDs RGB, también creamos un objeto de la clase RGB en dónde definimos el pin o pines conectados a los LEDs WS2812, la cantidad de LEDs en el bus y otros parámetros como la máxima intensidad de brillo que pueden tener los LEDs o la velocidad de la animación. Luego este objeto se agrega como una extensión del objeto keyboard. Es importante tener en cuenta que para el control de los LEDs es necesario usar la librería NeoPixel de CircuitPython, sólo es necesario descargar el archivo neopixel.py y copiarlo en la unidad CIRCUITPY, en la misma carpeta donde está el archivo code.py.

# 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)

Es importante tener en cuenta la asignación y función de cada uno de los pines, al igual que su orden en las filas y columnas del teclado.

Para finalizar agregamos la condición para que el método go del objeto keyboard corra indefinidamente si el programa code.py es el programa principal en ejecución.

if __name__ == '__main__':
    keyboard.go()

También modifiqué el archivo boot.py para evitar que el teclado aparezca en el sistema operativo como una unidad de almacenamiento, como un puerto serial o como un dispositivo midi. También tiene la configuración que permite que el teclado se pueda usar antes de que el sistema operativo arranque. Estos cambios hacen que el teclado no se pueda configurar directamente con el editor de CircuitPython, así que para entrar en modo configuración y poder modificar el programa, solo es necesario mantener pulsado el botón del encoder mientras se conecta el teclado al computador, y luego editar los parámetros usando 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()

El firmware de KMK ofrece muchas funciones y vale la pena revisar toda la documentación para ver otras formas de configurar el teclado para aprovecharlo. Probé el teclado en Windows 10 y en macOS Big Sur, y todos los comandos funcionan sin problema. En el repositorio del proyecto se puede encontrar el código completo usando más funciones de KMK y con comentarios.

Los esquemas, modelos 3D, firmware y demás archivos del proyecto se pueden encontrar en el repositorio de GitHub.

GitHub: MacroBoard

Más información:
KMKfw
Getting Started with KMK
CircuitPython
Seeed XIAO RP2040
Seeed Studio XIAO RP2040 – Wiki

Si tienes alguna inquietud no dudes en comentar.

📢 Esta entrada participa en el Seeed Fusion DIY XIAO Mechanical Keyboard Contest y está patrocinada parcialmente por Seeed Studio.

Deja un comentario