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. To get everything 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 board's CIRCUITPY drive, replacing any existing files or directories with the same names, and adding any new ones that are necessary. The CIRCUITPY drive appears when you plug the KB2040 into the computer via USB.
# SPDX-FileCopyrightText: 2023 Robert Dale Smith for Adafruit Industries
#
# SPDX-License-Identifier: MIT
# The Fisher-Price Kick and Play Piano Gym has five buttons that are
# active high. Pressed = 1, Released = 0. This code turns that into
# keyboard key press, key combos, and/or key press/combo macros.
import time
import board
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from digitalio import DigitalInOut, Direction, Pull
# Set up a keyboard device.
kbd = Keyboard(usb_hid.devices)
layout = KeyboardLayoutUS(kbd)
# Setup the buttons with internal pull-down resistors
buttons = []
for pin in [board.A0, board.A2, board.CLK, board.D2, board.D3]: # kb2040 pins
button = DigitalInOut(pin)
button.direction = Direction.INPUT
button.pull = Pull.DOWN
buttons.append(button)
# Each button corresponds to a key or key combination or a sequence of keys
keys = [
Keycode.A,
(Keycode.COMMAND, Keycode.TAB),
[
Keycode.UP_ARROW,
Keycode.ENTER
],
[
Keycode.END,
(Keycode.SHIFT, Keycode.HOME),
(Keycode.COMMAND, Keycode.C),
],
[
(Keycode.CONTROL, Keycode.A),
'Hello World',
Keycode.PERIOD
]
]
while True:
# check each button
for button, key in zip(buttons, keys):
if button.value: # button is pressed
if isinstance(key, tuple):
kbd.press(*key)
kbd.release_all()
elif isinstance(key, list):
for macro_key in key:
if isinstance(macro_key, str): # print a string
layout.write(macro_key)
elif isinstance(macro_key, tuple): # press combo keys
kbd.press(*macro_key)
kbd.release_all()
else: # press a single key
kbd.press(macro_key)
kbd.release_all()
time.sleep(0.1) # delay between keys
else: # press a single key
kbd.press(key)
kbd.release_all()
time.sleep(0.1) # debounce delay
time.sleep(0.1)
How It Works
The code uses the digitalio library to read the piano key button presses, then the adafruit_hid library is used to send USB keyboard commands.
Libraries
First, the necessary libraries and modules are imported.
import time import board import usb_hid from adafruit_hid.keycode import Keycode from adafruit_hid.keyboard import Keyboard from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS from digitalio import DigitalInOut, Direction, Pull
# Set up a keyboard device. kbd = Keyboard(usb_hid.devices) layout = KeyboardLayoutUS(kbd)
Digital In Out
We'll create an array named buttons. This array will store instances of the DigitalInOut class, each configured to correspond with one of the five KB2040 pins connected to the piano keys.
Each pin direction will be set to INPUT. The piano keys are active high. Meaning the voltage goes from 0 to 3.3v when a button is pressed and returns to 0 when released. So the default state of each pin is set to Pull.DOWN.
# Setup the buttons with internal pull-down resistors
buttons = []
for pin in [board.A0, board.A2, board.CLK, board.D2, board.D3]:
button = DigitalInOut(pin)
button.direction = Direction.INPUT
button.pull = Pull.DOWN
buttons.append(button)
Key Commands
The keys array contains five elements, one for each piano key button.
Each item can be either a single keyboard key press, a combination of simultaneously pressed keys, or a sequenced macro of individual or combo key presses.
This is where you can customize the individual piano keys' commands to fit your own needs.
For example:
-
Single - press a single key
- example:
Keycode.A
- example:
-
Combo - press a combination of keys simultaniously
- example:
(Keycode.COMMAND, Keycode.TAB)
- example:
-
Macro - press a sequence of single keys or combos one after the other
- example:
[ Keycode.UP_ARROW, Keycode.ENTER ]
- example:
-
Macro with a combo, a string, and a single key
- example:
[ (Keycode.CONTROL, Keycode.A), 'Hello Worl', Keycode.D ]
- example:
# Each button corresponds to a key or key combination or a sequence of keys
keys = [
Keycode.A, # single key
(Keycode.COMMAND, Keycode.TAB), # key combo
[
Keycode.UP_ARROW,
Keycode.ENTER
], # macro of single key presses
[
Keycode.END,
(Keycode.SHIFT, Keycode.HOME),
(Keycode.COMMAND, Keycode.C),
], # macro with single key and combo keys
[
(Keycode.CONTROL, Keycode.A),
'Hello World',
Keycode.PERIOD
] # macro with combo, string, and single
]
Main Loop
The main loop of the program first checks the button.value of each of the five buttons wired up to the GPIO pins of the KB2040.
Each button's corresponding keys array key is checked to see if it is either a tuple ( ), a list [ ], a single key Keycode., or a string of key characters 'Hello World'.
Tuples, values wrapped in parentheses ( ) will send simultaneous button combo presses. Lists, values wrapped in square brackets [ ] will send a macro sequence of individual or combo keys one after the other.
Keycode. values or strings wrapped in single quotes ' ' can be used for pressing one or more keys in sequence.
while True:
# check each button
for button, key in zip(buttons, keys):
if button.value: # button is pressed
if isinstance(key, tuple):
kbd.press(*key)
kbd.release_all()
elif isinstance(key, list):
for macro_key in key:
if isinstance(macro_key, str): # print a string
layout.write(macro_key)
elif isinstance(macro_key, tuple): # press combo keys
kbd.press(*macro_key)
kbd.release_all()
else: # press a single key
kbd.press(macro_key)
kbd.release_all()
time.sleep(0.1) # delay between keys
else: # press a single key
kbd.press(key)
kbd.release_all()
time.sleep(0.1) # debounce delay
time.sleep(0.1)
Page last edited January 22, 2025
Text editor powered by tinymce.