Once you've finished setting up your RP2040 QT Py with CircuitPython, you can access the code and necessary libraries by downloading the Project Bundle.
To do this, click on the Download Project Bundle button in the window below. It will download to your computer as a zipped folder.
# SPDX-FileCopyrightText: 2024 Liz Clark for Adafruit Industries
#
# SPDX-License-Identifier: MIT
import board
import usb_hid
import neopixel
from rainbowio import colorwheel
from adafruit_debouncer import Button
from adafruit_seesaw import seesaw, rotaryio, digitalio
from adafruit_hid.consumer_control import ConsumerControl
from adafruit_hid.consumer_control_code import ConsumerControlCode
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
enc_inc = ConsumerControlCode.VOLUME_INCREMENT
enc_dec = ConsumerControlCode.VOLUME_DECREMENT
one_press = ConsumerControlCode.PLAY_PAUSE
two_press = ConsumerControlCode.SCAN_NEXT_TRACK
three_press = [Keycode.LEFT_CONTROL, Keycode.UP_ARROW]
long_press = ConsumerControlCode.MUTE
cc = ConsumerControl(usb_hid.devices)
kbd = Keyboard(usb_hid.devices)
pixel_pin = board.A1
num_pixels = 18
pixels = neopixel.NeoPixel(pixel_pin, num_pixels,
brightness=.5, auto_write=True)
hue = 0
pixels.fill(colorwheel(hue))
i2c = board.STEMMA_I2C()
seesaw = seesaw.Seesaw(i2c, 0x36)
seesaw.pin_mode(24, seesaw.INPUT_PULLUP)
ss_pin = digitalio.DigitalIO(seesaw, 24)
button = Button(ss_pin, long_duration_ms=600)
encoder = rotaryio.IncrementalEncoder(seesaw)
last_position = 0
while True:
position = -encoder.position
button.update()
if position != last_position:
if position > last_position:
cc.send(enc_dec)
hue = hue - 7
if hue <= 0:
hue = hue + 256
else:
cc.send(enc_inc)
hue = hue + 7
if hue >= 256:
hue = hue - 256
pixels.fill(colorwheel(hue))
last_position = position
if button.short_count == 1:
cc.send(one_press)
if button.short_count == 2:
cc.send(two_press)
if button.short_count == 3:
kbd.press(*three_press)
kbd.release_all()
if button.long_press:
cc.send(long_press)
Upload the Code and Libraries to the RP2040 QT Py
After downloading the Project Bundle, plug your RP2040 QT Py into the computer's USB port with a known good USB data+power cable. You should see a new flash drive appear in the computer's File Explorer or Finder (depending on your operating system) called CIRCUITPY. Unzip the folder and copy the following items to the Feather's CIRCUITPY drive:
- lib folder
- code.py
Your RP2040 QT Py CIRCUITPY drive should look like this after copying the lib folderĀ and the code.py file.
How the CircuitPython Code Works
At the top of the code are variables for the keycodes that are sent by the media dial. You can update these keycodes if you want the media dial to do different things. By default, turn the encoder increases or decreases volume, one short press sends play/pause, two short presses sends next track, three short presses sends the mission control keyboard short for MacOS and a long press mutes your speaker volume.
enc_inc = ConsumerControlCode.VOLUME_INCREMENT enc_dec = ConsumerControlCode.VOLUME_DECREMENT one_press = ConsumerControlCode.PLAY_PAUSE two_press = ConsumerControlCode.SCAN_NEXT_TRACK three_press = [Keycode.LEFT_CONTROL, Keycode.UP_ARROW] long_press = ConsumerControlCode.MUTE
HID, NeoPixels and seesaw
The Keyboard USB HID device is instantiated, followed by the NeoPixels and seesaw rotary encoder.
cc = ConsumerControl(usb_hid.devices)
kbd = Keyboard(usb_hid.devices)
pixel_pin = board.A1
num_pixels = 18
pixels = neopixel.NeoPixel(pixel_pin, num_pixels,
brightness=.5, auto_write=True)
hue = 0
pixels.fill(colorwheel(hue))
i2c = board.STEMMA_I2C()
seesaw = seesaw.Seesaw(i2c, 0x36)
seesaw.pin_mode(24, seesaw.INPUT_PULLUP)
ss_pin = digitalio.DigitalIO(seesaw, 24)
button = Button(ss_pin, long_duration_ms=600)
encoder = rotaryio.IncrementalEncoder(seesaw)
last_position = 0
The Loop
In the loop, the rotary encoder and its switch are monitored for inputs. If the encoder is turned, then the volume is increased or decreased. The NeoPixels will cycle through the colorwheel colors.
if position != last_position: if position > last_position: cc.send(enc_dec) hue = hue - 7 if hue <= 0: hue = hue + 256 else: cc.send(enc_inc) hue = hue + 7 if hue >= 256: hue = hue - 256 pixels.fill(colorwheel(hue)) last_position = position
The switch on the encoder is defined as a adafruit_debouncer Button object, allowing you to define a long press duration and count short presses. When the defined presses are detected in the loop, the associated keycodes are sent.Ā
if button.short_count == 1: cc.send(one_press) if button.short_count == 2: cc.send(two_press) if button.short_count == 3: kbd.press(*three_press) kbd.release_all() if button.long_press: cc.send(long_press)
List of USB HID Keycodes
A list of available keyboard characters and consumer controls are listed in the documentation linked below. Function keys and modifiers can be used to create custom keyboard shortcuts.
Page last edited January 22, 2025
Text editor powered by tinymce.