We'll be using CircuitPython for this project. Are you new to using CircuitPython? No worries, there is a full getting started guide here.
Adafruit suggests using the Mu editor to edit your code and have an interactive REPL in CircuitPython. You can learn about Mu and its installation in this tutorial.
There's a guide to get you up and running with Circuit Python specifically for the NeoTrellis M4. You should read it before starting to get the most recent CircuitPython build for the NeoTrellis M4 installed and running along with the required libraries.
Navigating the NeoTrellis
To get your NeoTrellis M4 set up to run this project's code, first follow these steps:
1) Update the bootloader for NeoTrellis from the NeoTrellis M4 guide
2) Install the latest CircuitPython for NeoTrellis from the NeoTrellis M4 guide
For this project you will need the following libraries:
- adafruit_trellism4.mpy
- neopixel.mpy
- adafruit_matrixkeypad.mpy
Download Code
Time to install the software, here's the code.py listing, click on the Download Project Bundle link in the top left to grab all the code.
# SPDX-FileCopyrightText: 2018 Dave Astels for Adafruit Industries # # SPDX-License-Identifier: MIT """ Tabletop RPG soundboard for the NeoTrellisM4 Adafruit invests time and resources providing this open source code. Please support Adafruit and open source hardware by purchasing products from Adafruit! Written by Dave Astels for Adafruit Industries Copyright (c) 2018 Adafruit Industries Licensed under the MIT license. All text above must be included in any redistribution. """ # pylint: disable=wildcard-import,unused-wildcard-import,eval-used import time import board import audioio import audiocore import audiomixer import adafruit_trellism4 from color_names import * # Our keypad + neopixel driver trellis = adafruit_trellism4.TrellisM4Express(rotation=0) SELECTED_COLOR = WHITE # the color for the selected sample SAMPLE_FOLDER = '/samples/' # the name of the folder containing the samples SAMPLES = [] BLACK = 0x000000 # load the sound & color specifications with open('soundboard.txt', 'r') as f: for line in f: cleaned = line.strip() if len(cleaned) > 0 and cleaned[0] != '#': if cleaned == 'pass': SAMPLES.append(('does_not_exist.wav', BLACK)) else: f_name, color = cleaned.split(',', 1) SAMPLES.append((f_name.strip(), eval(color.strip()))) # Parse the first file to figure out what format its in channel_count = None bits_per_sample = None sample_rate = None with open(SAMPLE_FOLDER+SAMPLES[0][0], 'rb') as f: wav = audiocore.WaveFile(f) channel_count = wav.channel_count bits_per_sample = wav.bits_per_sample sample_rate = wav.sample_rate print('%d channels, %d bits per sample, %d Hz sample rate ' % (wav.channel_count, wav.bits_per_sample, wav.sample_rate)) # Audio playback object - we'll go with either mono or stereo depending on # what we see in the first file if wav.channel_count == 1: audio = audioio.AudioOut(board.A1) elif wav.channel_count == 2: audio = audioio.AudioOut(board.A1, right_channel=board.A0) else: raise RuntimeError('Must be mono or stereo waves!') mixer = audiomixer.Mixer(voice_count=2, sample_rate=sample_rate, channel_count=channel_count, bits_per_sample=bits_per_sample, samples_signed=True) audio.play(mixer) # Clear all pixels trellis.pixels.fill(0) # Light up button with a valid sound file attached for i, v in enumerate(SAMPLES): filename = SAMPLE_FOLDER+v[0] try: with open(filename, 'rb') as f: wav = audiocore.WaveFile(f) print(filename, '%d channels, %d bits per sample, %d Hz sample rate ' % (wav.channel_count, wav.bits_per_sample, wav.sample_rate)) if wav.channel_count != channel_count: pass if wav.bits_per_sample != bits_per_sample: pass if wav.sample_rate != sample_rate: pass trellis.pixels[(i % 8, i // 8)] = v[1] except OSError: # File not found! skip to next pass def stop_playing_sample(details): print('playing: ', details) mixer.stop_voice(details['voice']) trellis.pixels[details['neopixel_location']] = details['neopixel_color'] details['file'].close() details['voice'] = None current_press = set() current_background = {'voice' : None} currently_playing = {'voice' : None} while True: pressed = set(trellis.pressed_keys) just_pressed = pressed - current_press # just_released = current_press - pressed for down in just_pressed: sample_num = down[1]*8 + down[0] try: filename = SAMPLE_FOLDER+SAMPLES[sample_num][0] f = open(filename, 'rb') wav = audiocore.WaveFile(f) if down[1] == 0: # background loop? if current_background['voice'] != None: print('Interrupt') stop_playing_sample(current_background) trellis.pixels[down] = WHITE mixer.play(wav, voice=0, loop=True) current_background = { 'voice': 0, 'neopixel_location': down, 'neopixel_color': SAMPLES[sample_num][1], 'sample_num': sample_num, 'file': f} else: if currently_playing['voice'] != None: print('Interrupt') stop_playing_sample(currently_playing) trellis.pixels[down] = WHITE mixer.play(wav, voice=1, loop=False) currently_playing = { 'voice': 1, 'neopixel_location': down, 'neopixel_color': SAMPLES[sample_num][1], 'sample_num': sample_num, 'file': f} except OSError: pass # File not found! skip to next # # check if any samples are done # # this currently doesn't work with the mixer until it supports per voice "is_playing" checking # if not audio.playing and currently_playing['voice'] != None: # stop_playing_sample(currently_playing) time.sleep(0.01) # a little delay here helps avoid debounce annoyances current_press = pressed
The code.py CircuitPython code should run as soon as you copy the file onto the NeoTrellis CIRCUITPY drive. Be sure you copy all the files shown above to your CIRCUITPY drive.
Now you can start pressing buttons for your sound effects!
If some sounds work but not others, you'll need to edit the soundboard.txt file as explained on the previous page to ensure the file names are correct and you get the color you want for the button.
If you believe you have the soundboard.txt file correct and you do not hear the sound:
- Check your cabling to ensure you have powered amplified speakers and that the are on and volume at a good level.
- Be sure all of your sounds have been converted to 22,050 KHz, 16-bit PCM WAV files. Use all Mono or Stereo files, don't mix Mono and Stereo. This guide will help you with the conversions. MP3 files cannot be played in this project, sorry, they'll need conversion to WAV.
Text editor powered by tinymce.