Once you've finished setting up your QT Py RP2040 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 as a zipped folder.

# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries
# SPDX-License-Identifier: MIT

import time
import board
from digitalio import DigitalInOut, Direction, Pull
from adafruit_debouncer import Debouncer
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
from adafruit_hid.mouse import Mouse
from rainbowio import colorwheel
from adafruit_seesaw.seesaw import Seesaw
from adafruit_seesaw.analoginput import AnalogInput
from adafruit_seesaw import neopixel

# LED for button
led = DigitalInOut(board.A0)
led.direction = Direction.OUTPUT

#  button setup
key_pin = DigitalInOut(board.A1)
key_pin.direction = Direction.INPUT
key_pin.pull = Pull.UP
switch = Debouncer(key_pin)

# button to toot in the game (can be any key or a mouse click)
key_pressed = Keycode.SPACE

# keyboard object
time.sleep(1)  # Sleep for a bit to avoid a race condition on some systems
keyboard = Keyboard(usb_hid.devices)

#  mouse object
mouse = Mouse(usb_hid.devices)

# NeoSlider Setup
neoslider = Seesaw(board.STEMMA_I2C(), 0x30)
pot = AnalogInput(neoslider, 18)
pixels = neopixel.NeoPixel(neoslider, 14, 4, pixel_order=neopixel.GRB)

#  scale pot value to rainbow colors
def potentiometer_to_color(value):
    return value / 1023 * 255

#  last value of the potentiometer
last_value = 0
#  difference between last_value and current value
diff = 0
#  mouse movement sensitivity
#  increase value for faster movement, decrease for slower
mouse_sensitivity = 8

while True:
	#  read the slide pot's value (range of 0 to 1023)
    y = pot.value
	#  debouncer update
    switch.update()
    # colorwheel for neoslider neopixels
    pixels.fill(colorwheel(potentiometer_to_color(pot.value)))
	#  if button released
    if switch.rose:
		#  turn off button LED
        led.value = False
		#  release all keyboard keys
        keyboard.release_all()
	#  if button pressed
    if switch.fell:
		#  turn on button LED
        led.value = True
		#  press the space bar
        keyboard.press(key_pressed)
	#  if the current value of the pot is different from the last value
    if y != last_value:
		#  if the last value was bigger
        if last_value > y:
			#  find the difference
            diff = abs(last_value - y)
			#  divide by 10
            diff = diff / 10
			#  move cursor negative for range of difference
            for i in range(diff):
                mouse.move(y=-(mouse_sensitivity))
		#  if last value was smaller
        if last_value < y:
			#  find the difference
            diff = abs(last_value - y)
			#  divide by 10
            diff = diff / 10
			#  move cursor positive for range of difference
            for i in range(diff):
                mouse.move(y=mouse_sensitivity)
		#  reset last value
        last_value = y
	#  if value is 0
    if y == 0:
		#  slight movement
        mouse.move(y=-2)
	#  if value is 1023
    if y == 1023:
		#  slight movement
        mouse.move(y=2)

Upload the Code and Libraries to the QT Py RP2040

After downloading the Project Bundle, plug your QT Py RP2040 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 QT Py RP2040's CIRCUITPY drive. 

  • lib folder
  • code.py

Your QT Py RP2040 CIRCUITPY drive should look like this after copying the lib folder and the code.py file.

CIRCUITPY

How the CircuitPython Code Works

First, the arcade button and its LED are set up as an input and an output, respectively. The arcade button's pin is passed to Debouncer() to utilize the adafruit_debouncer library. Then, keyboard and mouse objects are set up with the usb_hid libraries. Finally, the neoslider is set up to work over I2C.

# LED for button
led = DigitalInOut(board.A0)
led.direction = Direction.OUTPUT

#  button setup
key_pin = DigitalInOut(board.A1)
key_pin.direction = Direction.INPUT
key_pin.pull = Pull.UP
switch = Debouncer(key_pin)
# button to toot in the game (can be any key or a mouse click)
key_pressed = Keycode.SPACE

# keyboard object
time.sleep(1)  # Sleep for a bit to avoid a race condition on some systems
keyboard = Keyboard(usb_hid.devices)

#  mouse object
mouse = Mouse(usb_hid.devices)

# NeoSlider Setup
neoslider = Seesaw(board.STEMMA_I2C(), 0x30)
pot = AnalogInput(neoslider, 18)
pixels = neopixel.NeoPixel(neoslider, 14, 4, pixel_order=neopixel.GRB)

Rainbows and Variables

A function from the NeoSlider example code, potentiometer_to_color(), is created to map the potentiometer's values to color values. This has the NeoSlider's NeoPixels display a rainbow swirl effect when the slider is used.

Three variables are created before the loop. last_value will track the last read value from the potentiometer. diff will track the difference between the current reading from the potentiometer and last_value.

mouse_sensitivity is used for the cursor movement. You can adjust this value to move the cursor faster or slower depending on your trombone slide preferences.

#  scale pot value to rainbow colors
def potentiometer_to_color(value):
    return value / 1023 * 255

#  last value of the potentiometer
last_value = 0
#  difference between last_value and current value
diff = 0
#  mouse movement sensitivity
#  increase value for faster movement, decrease for slower
mouse_sensitivity = 8

Reading Inputs

In the loop, y reads the value of the potentiometer. switch.update() reads the arcade button's state. pixels.fill() changes the color of the NeoSlider's NeoPixels to the mapped color of the rainbow depending on the potentiometer's value.

#  read the slide pot's value (range of 0 to 1023)
    y = pot.value
	#  debouncer update
    switch.update()
    # colorwheel for neoslider neopixels
    pixels.fill(colorwheel(potentiometer_to_color(pot.value)))

The Toot

To toot the trombone in the game, you need to press any key on the keyboard or click the mouse. This project uses the arcade button to do this.

If the arcade button is pressed, the arcade button's LED lights up and a space bar keycode is pressed. The keycode will be active the entire time that the arcade button is held down. When the arcade button is released, the LED is turned off and the space bar keycode is released.

#  if button released
    if switch.rose:
		#  turn off button LED
        led.value = False
		#  release all keyboard keys
        keyboard.release_all()
	#  if button pressed
    if switch.fell:
		#  turn on button LED
        led.value = True
		#  press the space bar
        keyboard.press(key_pressed)

The Slide

The game changes the pitch of the trombone, imitating a trombone's slide, by moving the mouse cursor up and down on the screen. The NeoSlider is used to achieve this.

The current value of the potentiometer is compared to the last value. If the values don't match, then the cursor will move. If the last value was larger, then the cursor moves in a negative value. If the last value was smaller, then the cursor moves in a positive value.

diff is used to scale the cursor movement depending on the difference between the current potentiometer reading and the previous reading.

If the value of the potentiometer does not change, then the cursor does not move. This is important for the trombone playing in the game.

#  if the current value of the pot is different from the last value
    if y != last_value:
		#  if the last value was bigger
        if last_value > y:
			#  find the difference
            diff = abs(last_value - y)
			#  divide by 10
            diff = diff / 10
			#  move cursor negative for range of difference
            for i in range(diff):
                mouse.move(y=-(mouse_sensitivity))
		#  if last value was smaller
        if last_value < y:
			#  find the difference
            diff = abs(last_value - y)
			#  divide by 10
            diff = diff / 10
			#  move cursor positive for range of difference
            for i in range(diff):
                mouse.move(y=mouse_sensitivity)
		#  reset last value
        last_value = y
	#  if value is 0
    if y == 0:
		#  slight movement
        mouse.move(y=-2)
	#  if value is 1023
    if y == 1023:
		#  slight movement
        mouse.move(y=2)

This guide was first published on Sep 30, 2022. It was last updated on Mar 28, 2024.

This page (Code the Controller) was last updated on Mar 28, 2024.

Text editor powered by tinymce.