Once you've finished setting up your RP2040 Prop-Maker Feather 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: Copyright (c) 2024 Liz Clark for Adafruit Industries
#
# SPDX-License-Identifier: MIT
import os
import board
import audiocore
import audiobusio
from digitalio import DigitalInOut, Direction
import displayio
import i2cdisplaybus
from adafruit_bitmap_font import bitmap_font
from adafruit_display_text import label
import adafruit_displayio_ssd1306
from adafruit_seesaw import seesaw, rotaryio
import vectorio
import keypad
#display setup
displayio.release_displays()
# enable external power pin
# provides power to the external components
external_power = DigitalInOut(board.EXTERNAL_POWER)
external_power.direction = Direction.OUTPUT
external_power.value = False
# rotary encoder
i2c = board.STEMMA_I2C()
seesaw = seesaw.Seesaw(i2c, addr=0x36)
encoder = rotaryio.IncrementalEncoder(seesaw)
last_position = 0
# oled
oled_reset = board.D9
display_bus = i2cdisplaybus.I2CDisplayBus(i2c, device_address=0x3D, reset=oled_reset)
WIDTH = 128
HEIGHT = 64
display = adafruit_displayio_ssd1306.SSD1306(display_bus, width=WIDTH, height=HEIGHT)
# trigger button
switch = keypad.Keys((board.EXTERNAL_BUTTON,), value_when_pressed=False, pull=True)
# audio!
wavs = []
wav_names = []
for filename in os.listdir('/wavs'):
if filename.lower().endswith('.wav') and not filename.startswith('.'):
wavs.append("/wavs/"+filename)
wav_names.append(filename.replace('.wav', ''))
audio = audiobusio.I2SOut(board.I2S_BIT_CLOCK, board.I2S_WORD_SELECT, board.I2S_DATA)
num_wavs = len(wavs)
wav_index = 0
# function to open and play the audio files
def open_audio(num):
n = wavs[num]
f = open(n, "rb")
w = audiocore.WaveFile(f)
return w
wave = open_audio(wav_index)
audio.play(wave)
# make the display context
splash = displayio.Group()
display.root_group = splash
palette = displayio.Palette(1)
palette[0] = 0xFFFFFF
rect = vectorio.Rectangle(pixel_shader=palette, width=display.width, height=23, x=6, y=21)
splash.append(rect)
font = bitmap_font.load_font("/Arial-14.bdf")
color = 0xFFFFFF
text_0 = wav_names[(wav_index - 1) % num_wavs]
text_area_top_left = label.Label(font, text=text_0, color=color)
text_area_top_left.anchor_point = (0.0, 0.0)
text_area_top_left.anchored_position = (6, 0)
splash.append(text_area_top_left)
text_1 = wav_names[wav_index]
text_area_middle_left = label.Label(font, text=text_1,color=0x000000)
text_area_middle_left.anchor_point = (0.0, 0.5)
text_area_middle_left.anchored_position = (6, display.height / 2)
splash.append(text_area_middle_left)
text_2 = wav_names[(wav_index+1) % num_wavs]
text_area_bottom_left = label.Label(font, text=text_2, color=color)
text_area_bottom_left.anchor_point = (0.0, 1.0)
text_area_bottom_left.anchored_position = (6, display.height)
splash.append(text_area_bottom_left)
while True:
event = switch.events.get()
position = encoder.position
if position != last_position:
if position > last_position:
wav_index = (wav_index + 1) % num_wavs
else:
wav_index = (wav_index - 1) % num_wavs
text_area_top_left.text = wav_names[(wav_index-1) % num_wavs]
text_area_middle_left.text = wav_names[wav_index]
text_area_bottom_left.text = wav_names[(wav_index+1) % num_wavs]
last_position = position
if event:
if event.pressed:
external_power.value = True
wave = open_audio(wav_index)
audio.play(wave)
if event.released:
external_power.value = False
Upload the Code and Libraries to the RP2040 Prop-Maker Feather
After downloading the Project Bundle, plug your RP2040 Prop-Maker Feather 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
- wavs folder
- code.py
- Arial-14.bdf
Your RP2040 Prop-Maker Feather CIRCUITPY drive should look like this after copying the lib folder, wav folder, .bdf font file and the code.py file.
How the CircuitPython Code Works
The code begins by instantiating the components and pins. The EXTERNAL_POWER pin is setup as an output. The rotary encoder and OLED display are instantiated over I2C and the EXTERNAL_BUTTON is setup as a keypad object.
# enable external power pin # provides power to the external components external_power = DigitalInOut(board.EXTERNAL_POWER) external_power.direction = Direction.OUTPUT external_power.value = False # rotary encoder i2c = board.STEMMA_I2C() seesaw = seesaw.Seesaw(i2c, addr=0x36) encoder = rotaryio.IncrementalEncoder(seesaw) last_position = 0 # oled oled_reset = board.D9 display_bus = i2cdisplaybus.I2CDisplayBus(i2c, device_address=0x3D, reset=oled_reset) WIDTH = 128 HEIGHT = 64 display = adafruit_displayio_ssd1306.SSD1306(display_bus, width=WIDTH, height=HEIGHT) # trigger button switch = keypad.Keys((board.EXTERNAL_BUTTON,), value_when_pressed=False, pull=True)
Audio
Any audio files that you have in the /wavs folder are added to the wavs and wav_names arrays. num_wavs holds the length of the wavs array. This means that you can change up the sound effects in your project without having to edit any of the code elements.
# audio!
wavs = []
wav_names = []
for filename in os.listdir('/wavs'):
if filename.lower().endswith('.wav') and not filename.startswith('.'):
wavs.append("/wavs/"+filename)
wav_names.append(filename.replace('.wav', ''))
audio = audiobusio.I2SOut(board.I2S_BIT_CLOCK, board.I2S_WORD_SELECT, board.I2S_DATA)
num_wavs = len(wavs)
wav_index = 0
# function to open and play the audio files
def open_audio(num):
n = wavs[num]
f = open(n, "rb")
w = audiocore.WaveFile(f)
return w
wave = open_audio(wav_index)
audio.play(wave)
Graphics
The OLED displays the sound effect names, which are stored in the wav_names array. There are three text elements used to show three names at a time. A vectorio rectangle "highlights" the center text element to select the sound effect.
# make the display context
splash = displayio.Group()
display.root_group = splash
palette = displayio.Palette(1)
palette[0] = 0xFFFFFF
rect = vectorio.Rectangle(pixel_shader=palette, width=display.width, height=23, x=6, y=21)
splash.append(rect)
font = bitmap_font.load_font("/Arial-14.bdf")
color = 0xFFFFFF
text_0 = wav_names[(wav_index - 1) % num_wavs]
text_area_top_left = label.Label(font, text=text_0, color=color)
text_area_top_left.anchor_point = (0.0, 0.0)
text_area_top_left.anchored_position = (6, 0)
splash.append(text_area_top_left)
text_1 = wav_names[wav_index]
text_area_middle_left = label.Label(font, text=text_1,color=0x000000)
text_area_middle_left.anchor_point = (0.0, 0.5)
text_area_middle_left.anchored_position = (6, display.height / 2)
splash.append(text_area_middle_left)
text_2 = wav_names[(wav_index+1) % num_wavs]
text_area_bottom_left = label.Label(font, text=text_2, color=color)
text_area_bottom_left.anchor_point = (0.0, 1.0)
text_area_bottom_left.anchored_position = (6, display.height)
splash.append(text_area_bottom_left)
The Loop
In the loop, the switch.events.get() is used to listen for any button input from the trigger button. position holds the value of the rotary encoder. When you rotate the encoder, the wav_index value increases or decreases. The wav_index determines the selected sound effect file and the highlighted sound effect name on the OLED.
event = switch.events.get()
position = encoder.position
if position != last_position:
if position > last_position:
wav_index = (wav_index + 1) % num_wavs
else:
wav_index = (wav_index - 1) % num_wavs
text_area_top_left.text = wav_names[(wav_index-1) % num_wavs]
text_area_middle_left.text = wav_names[wav_index]
text_area_bottom_left.text = wav_names[(wav_index+1) % num_wavs]
last_position = position
When the trigger button is pressed, the EXTERNAL_POWER pin value is True. This lights up the nOOd LED. The selected sound is opened and played thru the I2S amp. When the button is released, the EXTERNAL_POWER pin is False, turning off the nOOd and audio playback.
if event:
if event.pressed:
external_power.value = True
wave = open_audio(wav_index)
audio.play(wave)
if event.released:
external_power.value = False
Page last edited February 14, 2025
Text editor powered by tinymce.