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 KeeBoar board's CIRCUITPY drive, replacing any existing files or directories with the same names, and adding any new ones that are necessary.
Upload the Code and Libraries to the KB RP2040
After downloading the Project Bundle, plug your KB2040 into the computer USB port. 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 KB2040's CIRCUITPY drive.
- lib folder
- wavs folder
- code.py
# SPDX-FileCopyrightText: 2023 John Park for Adafruit Industries # # SPDX-License-Identifier: MIT import os import audiocore import board import audiobusio import audiomixer from digitalio import DigitalInOut, Pull from adafruit_debouncer import Button button_pins = ( board.D2, board.D3, board.D4, board.D5, board.D6, board.D7, board.D8, board.D9, board.D10, board.MOSI, board.MISO, board.SCK, ) buttons = [] # will hold list of Debouncer button objects for pin in button_pins: # set up each pin tmp_pin = DigitalInOut(pin) # defaults to input tmp_pin.pull = Pull.UP # turn on internal pull-down resistor buttons.append(Button(tmp_pin, value_when_pressed=False)) # get the filenames in aplha order from files in the 'wavs' directory sounds = [] for filename in sorted(os.listdir("/wavs")): filename = filename.lower() if filename.endswith(".wav") and not filename.startswith("."): sounds.append(filename) audio = audiobusio.I2SOut(bit_clock=board.A1, word_select=board.A2, data=board.A3) mixer = audiomixer.Mixer(voice_count=1, sample_rate=11025, channel_count=1, bits_per_sample=16, samples_signed=True) audio.play(mixer) mixer.voice[0].level = 0.5 def play_sound(sound_number): wave_file = open(("wavs/" + sounds[sound_number]), "rb") wave = audiocore.WaveFile(wave_file) mixer.voice[0].play(wave, loop=False) while True: for i in range(len(buttons)): buttons[i].update() if buttons[i].pressed: play_sound(i)
Make Your Own
Here's a great guide on prepping your own audio files for use on microcontrollers.
To convert your own .wav files, use audio software such as Audacity to save them with these settings:
- bits per sample: 16
- sample rate: 11kHz
- channels: mono
A great place to start is freesound.org. The sounds used in this project are:
https://freesound.org/s/86938/
https://freesound.org/s/125557/
https://freesound.org/s/200338/
https://freesound.org/s/339918/
https://freesound.org/s/353180/
https://freesound.org/s/405628/
https://freesound.org/s/417281/
https://freesound.org/s/434085/
https://freesound.org/s/523952/
https://freesound.org/s/612857/
https://freesound.org/s/619087/
https://freesound.org/s/633976/
How It Works
The code does two key things -- wait for button presses and play audio. Here's how it does it.
First, we import libraries, including os
for reading the file system, audiocore
, audiobusio
, and audiomixer
for audio playback/mixing, and digitalio
and adafruit_debouncer
for button input.
import os import audiocore import board import audiobusio import audiomixer from digitalio import DigitalInOut, Pull from adafruit_debouncer import Button
button_pins = ( board.D2, board.D3, board.D4, board.D5, board.D6, board.D7, board.D8, board.D9, board.D10, board.MOSI, board.MISO, board.SCK, ) buttons = [] # will hold list of Debouncer button objects for pin in button_pins: # set up each pin tmp_pin = DigitalInOut(pin) # defaults to input tmp_pin.pull = Pull.UP # turn on internal resistor buttons.append(Button(tmp_pin, value_when_pressed=False))
Sound Setup
The sounds list is created by alphabetically sorting the .wav files found in the wavs/ directory. This means you can place track numbers in front of your file names to assign them to the desired spot on the wheel.
Then, the audio
object is created to send digital audio over I2S to the amp. The mixer
object is created to play the chosen wav, and the audio mixer is set to play with a half-volume voice level of 0.5.
sounds = [] for filename in sorted(os.listdir("/wavs")): filename = filename.lower() if filename.endswith(".wav") and not filename.startswith("."): sounds.append(filename) audio = audiobusio.I2SOut(bit_clock=board.A1, word_select=board.A2, data=board.A3) mixer = audiomixer.Mixer(voice_count=1, sample_rate=11025, channel_count=1, bits_per_sample=16, samples_signed=True) audio.play(mixer) mixer.voice[0].level = 0.5
play_sound() Function
The play_sound()
function is defined to receive an integer number which it then uses to open the corresponding wav file and play it once.
def play_sound(sound_number): wave_file = open(("wavs/" + sounds[sound_number]), "rb") wave = audiocore.WaveFile(wave_file) mixer.voice[0].play(wave, loop=False)
Main Loop
The main loop of the program checks for button presses and when one is pressed it calls the play_sound()
function to play the sound.
while True: for i in range(len(buttons)): buttons[i].update() if buttons[i].pressed: play_sound(i)
Text editor powered by tinymce.