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)
Text editor powered by tinymce.