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.
# SPDX-FileCopyrightText: 2022 john park for Adafruit Industries # SPDX-License-Identifier: MIT # Pico Four Step Switch Keypad Demo import time import board import keypad from digitalio import Direction, DigitalInOut board_led = DigitalInOut(board.LED) board_led.direction = Direction.OUTPUT board_led.value = True switch_pins = (board.GP6, board.GP7, board.GP8, board.GP9) keys = keypad.Keys(switch_pins, value_when_pressed=False, pull=True) led_pins = (board.GP2, board.GP3, board.GP4, board.GP5) leds = [] for led_pin in led_pins: tmp_led_pin = DigitalInOut(led_pin) tmp_led_pin.direction = Direction.OUTPUT tmp_led_pin.value = False leds.append(tmp_led_pin) def blink_led(led_num, pause, repeat): for __ in range(repeat * 2): leds[led_num].value = not leds[led_num].value time.sleep(pause) def blink_all_leds(pause, repeat): for __ in range(repeat * 2): for led in leds: led.value = not led.value time.sleep(pause) blink_all_leds(0.1, 4) mode_picked = False # state of mode selection mode_choice = 0 # MIDI mode, desk switcher mode, etc. modes = (0, 1, 2, 3) mode_names = ("MIDI", "DESK", "SELECTOR", "COPY-PASTE") print("Select the mode by pressing a button: MIDI, DESK, SELECTOR, or COPY-PASTE") while not mode_picked: # program waits for a mode to be picked key = keys.events.get() if key: if key.pressed: mode_choice = key.key_number print(mode_names[mode_choice], "mode") mode_picked = True if mode_choice == 0: # MIDI mode import usb_midi import adafruit_midi from adafruit_midi.control_change import ControlChange midi = adafruit_midi.MIDI( midi_in=usb_midi.ports[0], in_channel=0, midi_out=usb_midi.ports[1], out_channel=0 ) cc_num = [16, 17, 18, 19] cc_state = [False, False, False, False] else: # HID modes import usb_hid from adafruit_hid.keyboard import Keyboard from adafruit_hid.keycode import Keycode if mode_choice == 1: # Mac Desktop switcher mode kpd = Keyboard(usb_hid.devices) MODIFIER = Keycode.CONTROL KEYMAP = ( ("Desktop 1", [MODIFIER, Keycode.ONE]), ("Desktop 2", [MODIFIER, Keycode.TWO]), ("Desktop 3", [MODIFIER, Keycode.THREE]), ("Desktop 4", [MODIFIER, Keycode.FOUR]), ) if mode_choice == 2: # SELECTOR mode for game weapon slot, Wirecast, etc. kpd = Keyboard(usb_hid.devices) MODIFIER = Keycode.SHIFT KEYMAP = ( ("Selector 1", [MODIFIER, Keycode.ONE]), ("Selector 2", [MODIFIER, Keycode.TWO]), ("Selector 3", [MODIFIER, Keycode.THREE]), ("Selector 4", [MODIFIER, Keycode.FOUR]), ) if mode_choice == 3: # Copy/Paste mode kpd = Keyboard(usb_hid.devices) # Choose the correct modifier key for Windows or Mac. # MODIFIER = Keycode.CONTROL # For Windows MODIFIER = Keycode.COMMAND KEYMAP = ( ("Copy/Paste 1", [MODIFIER, Keycode.A]), # select all ("Copy/Paste 2", [MODIFIER, Keycode.X]), # cut ("Copy/Paste 3", [MODIFIER, Keycode.C]), # copy ("Copy/Paste 4", [MODIFIER, Keycode.V]), # paste ) blink_led(mode_choice, 0.1, 3) while True: key = keys.events.get() if key: if key.pressed: i = key.key_number print(i, "pressed") if mode_choice == 0: leds[i].value = not leds[i].value if cc_state[i] is False: midi.send(ControlChange(cc_num[i], 127)) cc_state[i] = True else: midi.send(ControlChange(cc_num[i], 0)) cc_state[i] = False else: print(KEYMAP[i][0]) kpd.send(*KEYMAP[i][1]) for switch_led in leds: # blank the LEDs first switch_led.value = False leds[i].value = True # light selected switch LED
Use It
On startup, the board waits for you to select a mode by pressing one of the four switches. From left-to-right the modes are "MIDI", "Desktop switcher", "Item selector", and "Copy-Paste".
- In MIDI mode pressing each key toggles a MIDI CC on and off (127 or 0). You can see this in action in the video at the top of the page
- Desktop switcher mode pick among four MacOS desk "Spaces". You can see a video of this mode demonstrated below.
- Selector mode pick four main items in many video games, particularly first-person shooters
- Copy-Paste mode invokes "select all", "cut", "copy", and "paste" shortcuts
How it Works
The code is doing a few basic tasks: checking for button presses, toggling the LEDs, and sending USB MIDI or USB HID messages.
To make the button reading simple, we use the adafruit_keypad library.
import time import board import keypad from digitalio import Direction, DigitalInOut
Switch Setup
The setup for multiple switches if very simple when using the keypad library. You create a variable name for the group of pins, list the pins, and then create a keypad object (in this case named keys
) that point to the switch pin list, set a value default, and choose a pull up or down resistor value.
switch_pins = (board.GP6, board.GP7, board.GP8, board.GP9) keys = keypad.Keys(switch_pins, value_when_pressed=False, pull=True)
LED Setup
The LEDs are set up as a list so they are easy to call later using a list and index, e.g. leds[2]
led_pins = (board.GP2, board.GP3, board.GP4, board.GP5) leds = [] for led_pin in led_pins: tmp_led_pin = DigitalInOut(led_pin) tmp_led_pin.direction = Direction.OUTPUT tmp_led_pin.value = False leds.append(tmp_led_pin)
Blink Functions
A couple of convenience functions are created to make it easy to blink one or all of the LEDs.
def blink_led(led_num, pause, repeat): for __ in range(repeat * 2): leds[led_num].value = not leds[led_num].value time.sleep(pause) def blink_all_leds(pause, repeat): for __ in range(repeat * 2): for led in leds: led.value = not led.value time.sleep(pause)
Mode Selection
At startup, the code will wait for the user to select one of four modes by clicking one of the step switches.
To do so, we have a mode_picked
state, a mode_choice
variable, and four possible modes.
Using a while not mode_picked:
loop, the program essentially checks for a button press before it will get out of the loop and move ahead.
mode_picked = False # state of mode selection mode_choice = 0 # MIDI mode, desk switcher mode, etc. modes = (0, 1, 2, 3) mode_names = ("MIDI", "DESK", "SELECTOR", "COPY-PASTE") print("Select the mode by pressing a button: MIDI, DESK, SELECTOR, or COPY-PASTE") while not mode_picked: # program waits for a mode to be picked key = keys.events.get() if key: if key.pressed: mode_choice = key.key_number print(mode_names[mode_choice], "mode") mode_picked = True
Modes
Once a mode is selected, additional libraries are imported relevant to the mode selection, as well as some other specific setup.
For mode 0, MIDI is set up, with a list of CC numbers to use.
if mode_choice == 0: # MIDI mode import usb_midi import adafruit_midi from adafruit_midi.control_change import ControlChange midi = adafruit_midi.MIDI( midi_in=usb_midi.ports[0], in_channel=0, midi_out=usb_midi.ports[1], out_channel=0 ) cc_num = [16, 17, 18, 19] cc_state = [False, False, False, False]
The other three modes import USB hid libraries.
else: # HID modes import usb_hid from adafruit_hid.keyboard import Keyboard from adafruit_hid.keycode import Keycode
if mode_choice == 1: # Mac Desktop switcher mode kpd = Keyboard(usb_hid.devices) MODIFIER = Keycode.CONTROL KEYMAP = ( ("Desktop 1", [MODIFIER, Keycode.ONE]), ("Desktop 2", [MODIFIER, Keycode.TWO]), ("Desktop 3", [MODIFIER, Keycode.THREE]), ("Desktop 4", [MODIFIER, Keycode.FOUR]), ) if mode_choice == 2: # SELECTOR mode for game weapon slot, Wirecast, etc. kpd = Keyboard(usb_hid.devices) MODIFIER = Keycode.SHIFT KEYMAP = ( ("Selector 1", [MODIFIER, Keycode.ONE]), ("Selector 2", [MODIFIER, Keycode.TWO]), ("Selector 3", [MODIFIER, Keycode.THREE]), ("Selector 4", [MODIFIER, Keycode.FOUR]), ) if mode_choice == 3: # Copy/Paste mode kpd = Keyboard(usb_hid.devices) # Choose the correct modifier key for Windows or Mac. # MODIFIER = Keycode.CONTROL # For Windows MODIFIER = Keycode.COMMAND KEYMAP = ( ("Copy/Paste 1", [MODIFIER, Keycode.A]), # select all ("Copy/Paste 2", [MODIFIER, Keycode.X]), # cut ("Copy/Paste 3", [MODIFIER, Keycode.C]), # copy ("Copy/Paste 4", [MODIFIER, Keycode.V]), # paste )
Main Loop
When the main loop of the program is running the step switches are checked using the keys.events.get() command.
When a key is pressed, that switch's LED lights up and the associated command is sent.
while True: key = keys.events.get() if key: if key.pressed: i = key.key_number print(i, "pressed") if mode_choice == 0: leds[i].value = not leds[i].value if cc_state[i] is False: midi.send(ControlChange(cc_num[i], 127)) cc_state[i] = True else: midi.send(ControlChange(cc_num[i], 0)) cc_state[i] = False else: print(KEYMAP[i][0]) kpd.send(*KEYMAP[i][1]) for switch_led in leds: # blank the LEDs first switch_led.value = False leds[i].value = True # light selected switch LED
Page last edited January 22, 2025
Text editor powered by tinymce.