Deco Two-Key Feather Macro Pad

By Adafruit Industries

Courtesy of Adafruit

Guide by John Park

Overview

Minimal mechanical macropads are fun and useful. Perfect for playing rhythm games (Osu!), media controls, mic/camera muting, and more. You can customize the Deco Keypad to press any key or key-combo, as well as pick your favorite colors for the under-lit NeoPixels.

Build your own using the NeoKey FeatherWing, two mechanical keyswitches with keycaps, and the CircuitPython-capable Feather of your choice.

keypad_1

 

The Art Deco-inspired, 3D printed case has ports for USB, STEMMA QT cable, and the reset button. Add rubber bumper feet for a nice, stable macropad experience!

case_2

Parts

Feather

You can use pretty much any CircuitPython-capable Feather for this project.

NOTE: The code for this project sends keystrokes over a USB cable, not Bluetooth Low Energy. That's entirely possible if you'd like to adjust the code accordingly, just not the goal of this particular project.

Any Feather that can run CircuitPython will be totally fine for this project:

CircuitPython for Feather nRF52840

CircuitPython is a derivative of MicroPython designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Simply copy and edit files on the CIRCUITPY drive to iterate.

The following instructions will show you how to install CircuitPython. If you've already installed CircuitPython but are looking to update it or reinstall it, the same steps work for that as well!

Set up CircuitPython Quick Start!

Follow this quick step-by-step for super-fast Python power :)

Download the latest version of CircuitPython for this board via CircuitPython.org

Click the link above to download the latest UF2 file.

Download and save it to your desktop (or wherever is handy).

download_3

Plug your Feather nRF52840 into your computer using a known-good USB cable.

A lot of people end up using charge-only USB cables and it is very frustrating! So, make sure you have a USB cable you know is good for data sync.

Double-click the Reset button next to the USB connector on your board, and you will see the NeoPixel RGB LED turn green (identified by the arrow in the image). If it turns red, check the USB cable, try another USB port, etc. Note: The little red LED next to the USB connector will pulse red. That's ok!

If double-clicking doesn't work the first time, try again. Sometimes it can take a few tries to get the rhythm right!

feather_4

You will see a new disk drive appear called FTHR840BOOT.

Drag the adafruit_circuitpython_etc.uf2 file to FTHR840BOOT.

file_5

file_6

The LED will flash. Then, the FTHR840BOOT drive will disappear and a new disk drive called CIRCUITPY will appear.

That's it, you're done! :)

drive_7

Code the Deco Keypad

Text Editor

Adafruit recommends using the Mu editor for editing your CircuitPython code. You can get more info in this guide.

Alternatively, you can use any text editor that saves simple text files.

Download the Project Bundle

Your project will use a specific set of CircuitPython libraries and the code.py file. In order to get the libraries, you need, click on the Download Project Bundle link below, and uncompress the .zip file.

Drag the contents of the uncompressed bundle directory onto your Feather board's CIRCUITPY drive, replacing any existing files or directories with the same names, and adding any new ones that are necessary.

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: Copyright (c) 2021 John Park for Adafruit
#
# SPDX-License-Identifier: MIT
# Deco Keypad


import time
import board
from digitalio import DigitalInOut, Pull
from adafruit_debouncer import Debouncer
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from adafruit_hid.keycode import Keycode
import neopixel

print("- Deco Keypad -")
time.sleep(1) # Sleep for a bit to avoid a race condition on some systems

# ----- Keymap ----- #
# change as needed, e.g. capital A (Keycode.SHIFT, Keycode.A)
switch_a_output = Keycode.Z
switch_b_output = Keycode.X

# ----- Keyboard setup ----- #
keyboard = Keyboard(usb_hid.devices)
keyboard_layout = KeyboardLayoutUS(keyboard) # We're in the US :)

# ----- Key setup ----- #
switch_a_in = DigitalInOut(board.D5)
switch_b_in = DigitalInOut(board.D6)
switch_a_in.pull = Pull.UP
switch_b_in.pull = Pull.UP
switch_a = Debouncer(switch_a_in)
switch_b = Debouncer(switch_b_in)

# ----- NeoPixel setup ----- #
MAGENTA = 0xFF00FF
CYAN = 0x0088DD
WHITE = 0xCCCCCC
BLACK = 0x000000

pixel_pin = board.D9
pixels = neopixel.NeoPixel(pixel_pin, 2, brightness=1.0)
pixels.fill(BLACK)
time.sleep(0.3)
pixels.fill(WHITE)
time.sleep(0.3)
pixels.fill(BLACK)
time.sleep(0.3)
pixels[0] = MAGENTA
pixels[1] = CYAN


while True:
switch_a.update() # Debouncer checks for changes in switch state
switch_b.update()

if switch_a.fell:
keyboard.press(switch_a_output)
pixels[0] = WHITE
if switch_a.rose:
keyboard.release(switch_a_output)
pixels[0] = MAGENTA

if switch_b.fell:
keyboard.press(switch_b_output)
pixels[1] = WHITE
if switch_b.rose:
keyboard.release(switch_b_output)
pixels[1] = CYAN

View on GitHub

Custom Key Mapping

To adjust the key mapping of the keys, look for this section of the code:

Download File 

Copy Code
#  ----- Keymap -----  #
# change as needed, e.g. capital A (Keycode.SHIFT, Keycode.A)
switch_a_output = Keycode.Z
switch_b_output = Keycode.X

switch_a is the keyswitch closer to the USB port. You can use single keystrokes, or multi-key combos as shown in the comment.

For more info on using USB HID keycodes, check out this documentation.

How It Works

Libraries

The code first imports libraries to help out with a number of tasks, including time, board for pin definitions, digitalio and adafruit_debouncer to simplify key press and release detection, usb_hid and adafruit_hid.keyboard, plus neopixel.

Download File 

Copy Code
import time
import board
from digitalio import DigitalInOut, Pull
from adafruit_debouncer import Debouncer
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from adafruit_hid.keycode import Keycode
import neopixel

Keyboard Setup

This section sets the keymapping, keyboard setup, and pin setup with digitalio and debouncer.

Download File 

Copy Code
switch_a_output = Keycode.Z
switch_b_output = Keycode.X

# ----- Keyboard setup ----- #
keyboard = Keyboard(usb_hid.devices)
keyboard_layout = KeyboardLayoutUS(keyboard) # We're in the US :)

# ----- Key setup ----- #
switch_a_in = DigitalInOut(board.D5)
switch_b_in = DigitalInOut(board.D6)
switch_a_in.pull = Pull.UP
switch_b_in.pull = Pull.UP
switch_a = Debouncer(switch_a_in)
switch_b = Debouncer(switch_b_in)

NeoPixels

You'll create some color definitions and set up the two on-board NeoPixels next. Once they're set up, you'll give them a little startup blink, so you know when the board has been reset.

Download File

Copy Code
# ----- NeoPixel setup ----- #
MAGENTA = 0xFF00FF
CYAN = 0x0088DD
WHITE = 0xCCCCCC
BLACK = 0x000000

pixel_pin = board.D9
pixels = neopixel.NeoPixel(pixel_pin, 2, brightness=1.0)
pixels.fill(BLACK)
time.sleep(0.3)
pixels.fill(WHITE)
time.sleep(0.3)
pixels.fill(BLACK)
time.sleep(0.3)
pixels[0] = MAGENTA
pixels[1] = CYAN

Main Loop

The main code loop uses the debouncer to check both switches.

When either switch is pressed, the debouncer notices that it fell (voltage goes from high to low since we're using the built-in pull up resistor on each digital pin). Then, the keyboard.press() command sends the keyboard output for the associated key, and sets the NeoPixel to white.

When the debouncer registers that it rose, this means the key has been released, and the keyboard.release() command is sent for that keycode. The NeoPixel color returns to its default for that key.

Download File

Copy Code
switch_a.update()  # Debouncer checks for changes in switch state
switch_b.update()

if switch_a.fell:
keyboard.press(switch_a_output)
pixels[0] = WHITE
if switch_a.rose:
keyboard.release(switch_a_output)
pixels[0] = MAGENTA

if switch_b.fell:
keyboard.press(switch_b_output)
pixels[1] = WHITE
if switch_b.rose:
keyboard.release(switch_b_output)
pixels[1] = CYAN

Build the Deco Keypad

Assembly

Feather Headers

First, you'll prepare your Feather by soldering on the header sockets. This guide has details on soldering Feather headers.

headers_8

headers_9

FeatherWing Pins

Next, solder on the headers to the FeatherWing. This guide section show how to solder plain headers.

Be sure to double-check the orientation before soldering. The FeatherWing will insert into the Feather with the flat side of the 'Wing exposed on top.

wings_10

wings_11

both_12

Press the 'Wing into the Feather as shown.

press_14

press_13

Case and Base

The case is designed to hold the keyswitches securely (just like the switch plate of a typical mechanical keyboard) while protecting the electronics and looking stylish.

There are openings in the case for USB port, STEMMA QT, if you have plans for expansion over I2C, and the reset button.

The base snaps onto the bottom and give you some surface area to stick on some rubber bumper feet to prevent sliding.

You can print the model files linked below on a 3D printer or have them printed through a service.

Deco Keypad 3D model files

deco_15

deco_16

Fit Feather in Case

Align the Feather's USB port with the larger opening on the case, then push the stacked FeatherWing/Feather through the bottom of the case. It should be a fairly snug fit.

case_17

case_18

Keyswitches

Insert the keyswitches from the top of the case into the FeatherWing -- be careful to align the pins of the keyswitches with the sockets of the FeatherWing to avoid bending the delicate legs.

You should push the keyswitches in firmly to make a solid connection with the sockets by squeezing up on the Feather/FeatherWing and down on the keyswitches.

Once the keyswitches are in place, place the case on your work surface and push down on both keyswitches to click them into the case's integrated switchplate.

keyswitch_19

keyswitch_20

keyswitch_21

keyswitch_22

Base of Case

"All that she wants is another keyswitch..." (Oh, wait, that's Ace of Base.)

Fit the base onto the bottom of the case.

To prevent sliding, put rubber bumper feet onto the base.

base_23

base_24

base_25

Keycaps

Press your keycaps onto the keyswitch stems. You can use any MX compatible keycaps you like -- both translucent and windowed keycaps work particularly well for seeing the NeoPixel under-lighting.

keycaps_26

keycaps_27

keycaps_28

Now, you're ready to play some Osu! or other one or two-button rhythm game!

Or, you can use the Deco Keypad for a keyboard shortcut, such as copy/paste, volume -/+, and more.

button_29

 

Key Parts and Components

Add all Digi-Key Parts to Cart
  • 1528-4979-ND
  • 1528-4955-ND
  • 1528-4956-ND
  • 1528-2828-ND
  • 1528-2648-ND
  • 1528-2126-ND
  • 1528-4884-ND
  • 1528-1560-ND
  • 1528-5044-ND