Overview
Make this portable soundboard that you can attach to any bike or scooter!
It’s got arcade buttons that playback and mix audio files, so you can honk your horn while playing an engine sound effect.
This project shows of CircuitPython’s audio mixing and looping abilities. The sound effects box plays a background loop of a motorcycle engine and the 3 arcade buttons can be pressed to mix in honking effects.
Powered by the Feather RP2040, this uses an I2S amplifier for outputting high quality audio with a mini speaker.
With CircuitPython, you can easily make audio projects using the built-in audio libraries.
With Audio Mixer, you can play multiple audio files together and output high quality audio over I2S.
With Native USB support, you can drag and drop wave and MP3 audio files like a USB flash drive.
The microcontroller and amplifier are secured to a 3D printed plate that slides into rails built into the case.
These panel mounted arcade buttons press fit and are easy to swap out thanks to the quick connect cables.
A 3D printed clip is secured to the enclosure and can be attached to the frame of any bike or scooter.
Page last edited March 08, 2024
Text editor powered by tinymce.
Circuit Diagram
The wiring diagram below provides a visual reference for connecting the components. It is not true to scale, it is just meant to be used as reference. This diagrams was created using the Fritzing software package.
Take a moment to review the components in the circuit diagram. This illustration is meant for referencing wired connections - the length of wire, position and size of components are not exact.
Wires are measured and cut to have enough slack to reach each component.
Silicone ribbon wire is used to make them easier to coil and manage each wire inside the tight enclosure space.
Page last edited March 08, 2024
Text editor powered by tinymce.
Install CircuitPython
CircuitPython is a derivative of MicroPython designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Simply copy and edit files on the CIRCUITPY drive to iterate.
CircuitPython Quickstart
Follow this step-by-step to quickly get CircuitPython running on your board.
Click the link above to download the latest CircuitPython UF2 file.
Save it wherever is convenient for you.
To enter the bootloader, hold down the BOOT/BOOTSEL button (highlighted in red above), and while continuing to hold it (don't let go!), press and release the reset button (highlighted in red or blue above). Continue to hold the BOOT/BOOTSEL button until the RPI-RP2 drive appears!
If the drive does not appear, release all the buttons, and then repeat the process above.
You can also start with your board unplugged from USB, press and hold the BOOTSEL button (highlighted in red above), continue to hold it while plugging it into USB, and wait for the drive to appear before releasing the button.
A lot of people end up using charge-only USB cables and it is very frustrating! Make sure you have a USB cable you know is good for data sync.
You will see a new disk drive appear called RPI-RP2.
Drag the adafruit_circuitpython_etc.uf2 file to RPI-RP2.
The RPI-RP2 drive will disappear and a new disk drive called CIRCUITPY will appear.
That's it, you're done! :)
Safe Mode
You want to edit your code.py or modify the files on your CIRCUITPY drive, but find that you can't. Perhaps your board has gotten into a state where CIRCUITPY is read-only. You may have turned off the CIRCUITPY drive altogether. Whatever the reason, safe mode can help.
Safe mode in CircuitPython does not run any user code on startup, and disables auto-reload. This means a few things. First, safe mode bypasses any code in boot.py (where you can set CIRCUITPY read-only or turn it off completely). Second, it does not run the code in code.py. And finally, it does not automatically soft-reload when data is written to the CIRCUITPY drive.
Therefore, whatever you may have done to put your board in a non-interactive state, safe mode gives you the opportunity to correct it without losing all of the data on the CIRCUITPY drive.
To enter safe mode when using CircuitPython, plug in your board or hit reset (highlighted in red above). Immediately after the board starts up or resets, it waits 1000ms. On some boards, the onboard status LED (highlighted in green above) will blink yellow during that time. If you press reset during that 1000ms, the board will start up in safe mode. It can be difficult to react to the yellow LED, so you may want to think of it simply as a slow double click of the reset button. (Remember, a fast double click of reset enters the bootloader.)
In Safe Mode
If you successfully enter safe mode on CircuitPython, the LED will intermittently blink yellow three times.
If you connect to the serial console, you'll find the following message.
Auto-reload is off. Running in safe mode! Not running saved code. CircuitPython is in safe mode because you pressed the reset button during boot. Press again to exit safe mode. Press any key to enter the REPL. Use CTRL-D to reload.
You can now edit the contents of the CIRCUITPY drive. Remember, your code will not run until you press the reset button, or unplug and plug in your board, to get out of safe mode.
Flash Resetting UF2
If your board ever gets into a really weird state and CIRCUITPY doesn't show up as a disk drive after installing CircuitPython, try loading this 'nuke' UF2 to RPI-RP2. which will do a 'deep clean' on your Flash Memory. You will lose all the files on the board, but at least you'll be able to revive it! After loading this UF2, follow the steps above to re-install CircuitPython.
Page last edited March 08, 2024
Text editor powered by tinymce.
Code
Once you've finished setting up your Feather 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 to your computer as a zipped folder.
# SPDX-FileCopyrightText: 2022 John Park for Adafruit Industries
# SPDX-License-Identifier: MIT
# Convert files to appropriate WAV format (mono, 22050 Hz, 16-bit signed)
import time
import board
import keypad
import audiocore
import audiomixer
import audiobusio
# wait a little bit so USB can stabilize and not glitch audio
time.sleep(3)
# list of (samples to play, mixer gain level)
wav_files = (
('wav/airhorn.wav', 1.0), #Honk sound 1
('wav/bike-horn.wav', 1.0), #Honk around 2
('wav/chime.wav', 1.0), #Honk sound 3
('wav/idle.wav', 1.0) #Looping Engine Sound Effect
)
# pins used by keyboard
KEY_PINS = (
board.D5, board.D6, board.D12
)
km = keypad.Keys( KEY_PINS, value_when_pressed=False, pull=True)
audio = audiobusio.I2SOut(board.TX, board.RX, board.D9)
mixer = audiomixer.Mixer(voice_count=len(wav_files), sample_rate=22050, channel_count=1,
bits_per_sample=16, samples_signed=True)
audio.play(mixer) # attach mixer to audio playback
for i in range(len(wav_files)): # start all samples at once for use w handle_mixer
wave = audiocore.WaveFile(open(wav_files[i][0],"rb"))
mixer.voice[i].play(wave, loop=True)
mixer.voice[i].level = 0
def handle_mixer(num, pressed):
voice = mixer.voice[num] # get mixer voice
if pressed:
voice.level = wav_files[num][1] # play at level in wav_file list
else: # released
voice.level = 0 # mute it
while True:
mixer.voice[3].level = 1 #Looping Engine Sound Effect
event = km.events.get()
if event:
if event.key_number < len(wav_files):
if event.pressed:
handle_mixer(event.key_number, True)
if event.released:
handle_mixer( event.key_number, False )
After downloading the Project Bundle, plug your Feather RP2040 into the computer's 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 Feather RP2040's CIRCUITPY drive.
- lib folder
- code.py
Your Feather RP2040 CIRCUITPY drive should look like this after copying the lib folder and the code.py file.
Page last edited March 08, 2024
Text editor powered by tinymce.
3D Printing
Parts List
STL files for 3D printing are oriented to print "as-is" on FDM style machines. Original design source files may be downloaded using the links below.
Slice with settings for PLA material.
The parts were sliced using CURA using the slice settings below.
- PLA filament 220c extruder
- 0.2 layer height
- 10% gyroid infill
- 60mm/s print speed
- 60c heated bed
NinjaFlex Bumper
- NinjaFlex 95A Filament (Cheetah)
- 230c extruder
- 0.4 initial Layer Height
- 0.42 Line Width
- 0.2 layer height
- 10% gyroid infill
- 60mm/s print speed
- 50c heated bed
- Retraction 4mm on Bowden Drives, .5mm on Direct Drive
Page last edited March 08, 2024
Text editor powered by tinymce.
Assembly
Attach Brackets
Brackets are fastened to the printed board plate with two M3x8mm screws.
An M3 threaded nut is press fitted into the end of the bracket.
The bracket is secure to handles with a M3x10mm screw.
Solder Ground Wires
Twist four quick connect wires together facing the same way, then twist one silicone wire from the other direction to produce a four-way splitter cable. Solder where these wires all meet, then cover the exposed solder joint with heat-shrink tubing.
Solder Feather to Amp
Follow the Circuit Diagram to connect the Feather board to the Amp.
The Feather and Amp mount to the 3d printed plate with M2.5x6mm screws.
Solder Button Wires
Remove the jack from the quick connects and solder directly to the pins on the Feather board.
Thread Wires
Bundle the ground and Button wires with pieces of heat shrink tubing. Pass each bundle through each button cutout.
Slide Bottom Plate
The bottom plate slides into rails built-into the case.
Connect Buttons
Align the contacts on the arcade buttons to face the same direction. Connect each quick connect to the contacts on the arcade buttons.
Mount Buttons
The arcade buttons press fit into each cutout.
Battery Bumper
The 220mAh lips battery fits inside a bumper with the wire facing out the larger opening.
Mount Battery
The battery connects to the JST port on the Feather. The battery fits inside the case, on the opposite side of the arcade contacts.
Pushbutton Button
Connect the EN pin and the last ground wire to the contacts on the pushbutton. Carefully coil wires to fit inside the case.
Attach Lid
Unscrew the included threaded washer on the pushbutton. Press the pushbutton through the printed Lid part. Reattach the threaded washer to secure the pushbutton to the lid.
Align the lid part to the case to press fit into place.
Connect Speaker
Solder an input JST to the speaker wire to easily connect to the amp.
Mount Speaker
Coil excess speaker wire inside the case.
Place the speaker inside the cavity.
Grill
The grill press fits over the speaker cavity.
Page last edited March 08, 2024
Text editor powered by tinymce.