Install CircuitPython
The Adafruit Feather M4 ships with CircuitPython but lets go ahead and update it to the latest version. It's super easy with the circuitpython.org website, just click the link below to launch the page. There you can choose to install stable release or beta.
Quick Start
- Connect board to computer via a known good USB data cable and double press the reset button.
- Download the CircuitPython UF2 and upload to the FEATHERBOOT drive.
- Open CIRCUITPY drive and upload the required libraries (listed below) and code.py
Adafruit Circuit Python Libraries
Download the CircuitPython library bundle and unzip the folder. Create a new folder in the CIRCUITPY drive and name it "lib". The following libraries are required to run the code properly. Double check to ensure all of the files and folders are inside the lib folder on the CIRCUITPY drive.
- adafruit_bus_device (directory)
- adafruit_lis3dh.mpy
- adafruit_neotrellis (directory)
- adafruit_rgbled.py
- adafruit_seesaw
- neopixel.mpy
- simpleio.mpy
Mu Python Editor
Check out Mu, it's a simple Python editor that works with Adafruit CircuitPython hardware. It's written in Python and works on Windows, MacOS, Linux and Raspberry Pi. The serial console is built right in so you get immediate feedback from your board's serial output!
# SPDX-FileCopyrightText: 2019 Anne Barela for Adafruit Industries
#
# SPDX-License-Identifier: MIT
# NeoTrellis Soundbox Remix - CircuitPython
# Noe and Pedro Ruiz, code by Anne Barela
# for Adafruit Industries, MIT License
import time
import os
import random
import board
from board import SCL, SDA
import digitalio
import busio
import audioio
import audiocore
import adafruit_rgbled
from adafruit_neotrellis.neotrellis import NeoTrellis
import adafruit_lis3dh
# Color definitions
OFF = (0, 0, 0)
RED = (25, 0, 0)
YELLOW = (25, 15, 0)
GREEN = (0, 25, 0)
CYAN = (0, 25, 25)
BLUE = (0, 0, 25)
PURPLE = (18, 0, 25)
WHITE = (127, 127, 127)
# Create the i2c object for the trellis
# If you get an error, your PropMaker Shield needs to be snappped on
i2c_bus = busio.I2C(SCL, SDA)
# Create the trellis
trellis = NeoTrellis(i2c_bus)
print("NeoTrellis created")
# Enable PWR Pin to enable NeoPixels, audio amplifier and RGB LED
# See https://learn.adafruit.com/adafruit-prop-maker-featherwing/pinouts
enable = digitalio.DigitalInOut(board.D10)
enable.direction = digitalio.Direction.OUTPUT
enable.value = True
# Set up RGB for switch RGB LED
RED_LED = board.D11
GREEN_LED = board.D12
BLUE_LED = board.D13
led = adafruit_rgbled.RGBLED(RED_LED, GREEN_LED, BLUE_LED)
led.color = GREEN
# Enable button use on PropMaker Wing Switch input
push_switch = digitalio.DigitalInOut(board.D9)
push_switch.switch_to_input(pull=digitalio.Pull.UP)
# Set up Accelerometer on I2C bus
int1 = digitalio.DigitalInOut(board.D5)
accel = adafruit_lis3dh.LIS3DH_I2C(i2c_bus, int1=int1)
# See https://circuitpython.readthedocs.io/projects/lis3dh/en/
# latest/api.html for adjusting settings for the accelerometer
accel.range = adafruit_lis3dh.RANGE_4_G
# accel.set_tap(1, 80) # Single tap, second value is sensitivity
# Set up playing audio on A0 and interruptable playing
myaudio = audioio.AudioOut(board.A0)
audio_file = None
def play_file(audio_filename):
global audio_file # pylint: disable=global-statement
if myaudio.playing:
myaudio.stop()
if audio_file:
audio_file.close()
audio_file = open("/sounds/"+audio_filename, "rb")
wav = audiocore.WaveFile(audio_file)
print("Playing "+audio_filename+".")
myaudio.play(wav)
# Process wav files in the flash drive sounds directory
wavefiles = [file for file in os.listdir("/sounds/")
if (file.endswith(".wav") and not file.startswith("._"))]
if len(wavefiles) < 1:
print("No wav files found in sounds directory")
else:
print("Audio files found: ", wavefiles)
PUSH_COLOR = GREEN
ANIM_COLOR = WHITE
COLORS = ["RED", "YELLOW", "GREEN", "CYAN", "BLUE", "PURPLE", "WHITE"]
COLOR_TUPLES = [RED, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE]
buttons = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
button_colors = [OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF,
OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF]
shuffled_colors = list(button_colors)
Shuffled = False
# Time to process the filenames using the special file name syntax
# Currently nn-color-name.wav where nn = 2 digit number 0 to 15
# color is lower or upper case color name from above and
# name can be anything. BUT these all must be separated by a "-"
# Example 02-blue-firetruck.wav is valid. Note leading 0 for 0 to 9
wavnames = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""]
shuffled_names = list(wavnames) # Duplicate list, wavnames is our reference
shuffled = False
for soundfile in wavefiles:
print("Processing "+soundfile)
pos = int(soundfile[0:2])
if pos >= 0 and pos < 16: # Valid filenames start with 00 to 15
wavnames[pos] = soundfile # Store soundfile in proper index
shuffled_names[pos] = soundfile
skip = soundfile[3:].find('-') + 3
user_color = soundfile[3:skip].upper() # Detect file color
print("For file "+soundfile+", color is "+user_color+".")
file_color = COLOR_TUPLES[COLORS.index(user_color)]
button_colors[pos] = file_color
shuffled_colors[pos] = file_color
else:
print("Filenames must start with a number from 00 to 15 - "+soundfile)
# this will be called when button events are received
def blink(event):
# turn the LED on when a rising edge is detected
if event.edge == NeoTrellis.EDGE_RISING: # Trellis button pushed
print("Button "+str(event.number)+" pushed")
if event.number > 15:
print("Event number out of range: ", event.number)
trellis.pixels[event.number] = WHITE
if shuffled_names[event.number] != "":
play_file(shuffled_names[event.number])
# turn the LED off when a rising edge is detected (button released)
elif event.edge == NeoTrellis.EDGE_FALLING:
trellis.pixels[event.number] = shuffled_colors[event.number]
for i in range(16):
# activate rising edge events on all keys
trellis.activate_key(i, NeoTrellis.EDGE_RISING)
# activate falling edge events on all keysshuff
trellis.activate_key(i, NeoTrellis.EDGE_FALLING)
# set all keys to trigger the blink callback
trellis.callbacks[i] = blink
# cycle the LEDs on startup
trellis.pixels[i] = ANIM_COLOR
time.sleep(.05)
# On start, set the pixels on trellis to the file name colors chosen
for i in range(16):
trellis.pixels[i] = shuffled_colors[i]
time.sleep(.05)
while True:
# call the sync function call any triggered callbacks
trellis.sync()
# Check push switch, reset trellis buttons randomization if pressed
if not push_switch.value:
myaudio.stop() # Stop any audio playing
print("RGB Switch Push - reset shuffle if needed")
shuffled_names = list(wavnames) # Reset with clean lists
shuffled_colors = list(button_colors)
for i in range(16):
trellis.pixels[i] = shuffled_colors[i]
time.sleep(.05)
Shuffled = False
led.color = GREEN
# Check accelerometer
if accel.shake(shake_threshold=15): # Change shake(val) to tapped
myaudio.stop() # Stop any audio playing
print("Unit Tapped - shuffle sound files to random buttons")
shuffled_names = list(wavnames) # Copy lists
shuffled_colors = list(button_colors)
for i in range(len(wavnames)): # Do the shuffling
random_i = random.randrange(len(wavnames))
# Swap current name with a random slot
name = shuffled_names[random_i]
shuffled_names[random_i] = shuffled_names[i]
shuffled_names[i] = name
number = shuffled_colors[random_i]
shuffled_colors[random_i] = shuffled_colors[i]
shuffled_colors[i] = number
for i in range(16):
trellis.pixels[i] = shuffled_colors[i]
time.sleep(.05)
print(shuffled_names)
print(shuffled_colors)
shuffled = True
led.color = RED
# the trellis can only be read every 17 milliseconds or so
time.sleep(.019)
Audio Files
The sounds used in this project are sampled from popular music and movies. The pack contains various sounds that are already in the supported audio format. The file names must contain a two digital number followed by a color and single phrase description (00-15). For example:
- 00-red-bird.wav
- 01-blue-cat.wav
- 02-green-dog.wav
The two digit number represents the button pad on the NeoTrellis. Located on the top of the PCB are labels with numbers 1-16. For example, the file name with "00" will be mapped to the first NeoPixel #1. A total of 16 audio files can be used.
Audio files must be in a directory named "sounds".
Adafruit CircuitPython supports 16-bit, Mono, 22.050kHz .wav audio format. See this guide to help format any audio files you might want to use in this project besides the files provided.
NeoPixel Colors
Supported colors are in the list below. Optionally create custom colors using RGB values. List of colors are located in the code on line 17.
# Color definitions OFF = (0, 0, 0) RED = (25, 0, 0) YELLOW = (25, 15, 0) GREEN = (0, 25, 0) CYAN = (0, 25, 25) BLUE = (0, 0, 25) PURPLE = (18, 0, 25) WHITE = (127, 127, 127)
Additional colors must be added to the array on line 87 and 88.
COLORS = ["RED", "YELLOW", "GREEN", "CYAN", "BLUE", "PURPLE", "WHITE"] COLOR_TUPLES = [RED, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE]
Page last edited January 21, 2025
Text editor powered by tinymce.