Software

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 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
  • neopixel.mpy
  • adafruit_rgbled.py

Upload code.py

Click the link below to download the project  zip – This contains the code, audio and 3D files. Upload the code.py file to the CIRCUITPY drive.

Create a new folder on the CIRCUITPY drive and name it "sounds". Upload the audio files to that folder. The code will run properly when all of the files have been uploaded.

"""
Prop-Maker based Light Up Prop.
Adafruit invests time and resources providing this open source code.
Please support Adafruit and open source hardware by purchasing
products from Adafruit!
Written by Kattni Rembor for Adafruit Industries
Copyright (c) 2019 Adafruit Industries
Licensed under the MIT license.
All text above must be included in any redistribution.
"""
import time
import random
import digitalio
import audioio
import busio
import board
import adafruit_rgbled
import adafruit_lis3dh

# CUSTOMISE COLORS HERE:
MAIN_COLOR = (255, 0, 0)  # Default is red
HIT_COLOR = (255, 255, 255)  # Default is white

# CUSTOMISE SENSITIVITY HERE: smaller numbers = more sensitive to motion
HIT_THRESHOLD = 650
SWING_THRESHOLD = 125

# Set to the length in seconds of the "on.wav" file
POWER_ON_SOUND_DURATION = 1.5

POWER_PIN = board.D10

enable = digitalio.DigitalInOut(POWER_PIN)
enable.direction = digitalio.Direction.OUTPUT
enable.value = False

# Pin the Red LED is connected to
RED_LED = board.D11

# Pin the Green LED is connected to
GREEN_LED = board.D12

# Pin the Blue LED is connected to
BLUE_LED = board.D13

# Create the RGB LED object
led = adafruit_rgbled.RGBLED(RED_LED, GREEN_LED, BLUE_LED)

audio = audioio.AudioOut(board.A0)  # Speaker

# Set up accelerometer on I2C bus, 4G range:
i2c = busio.I2C(board.SCL, board.SDA)
accel = adafruit_lis3dh.LIS3DH_I2C(i2c)
accel.range = adafruit_lis3dh.RANGE_4_G

COLOR_HIT = HIT_COLOR  # "hit" color is HIT_COLOR set above
COLOR_SWING = MAIN_COLOR  # "swing" color is MAIN_COLOR set above


def play_wav(name, loop=False):
    """
    Play a WAV file in the 'sounds' directory.
    :param name: partial file name string, complete name will be built around
                 this, e.g. passing 'foo' will play file 'sounds/foo.wav'.
    :param loop: if True, sound will repeat indefinitely (until interrupted
                 by another sound).
    """
    print("playing", name)
    try:
        wave_file = open('sounds/' + name + '.wav', 'rb')
        wave = audioio.WaveFile(wave_file)
        audio.play(wave, loop=loop)
    except:  # pylint: disable=bare-except
        return


# List of swing wav files without the .wav in the name for use with play_wav()
swing_sounds = [
    'swing1',
    'swing2',
    'swing3',
    'swing4',
    'swing5',
    'swing6',
    'swing7',
    'swing8',
]

# List of hit wav files without the .wav in the name for use with play_wav()
hit_sounds = [
    'hit1',
    'hit2',
    'hit3',
    'hit4',
    'hit5',
    'hit6',
    'hit7',
    'hit8',
]

mode = 0  # Initial mode = OFF

# Main loop
while True:
    if mode == 0:  # If currently off...
        enable.value = True
        play_wav('on')  # Power up!
        led.color = MAIN_COLOR
        time.sleep(POWER_ON_SOUND_DURATION)
        play_wav('idle', loop=True)  # Play idle sound now
        mode = 1  # Idle mode

    elif mode >= 1:  # If not OFF mode...
        x, y, z = accel.acceleration  # Read accelerometer
        accel_total = x * x + z * z
        # (Y axis isn't needed, due to the orientation that the Prop-Maker
        # Wing is mounted.  Also, square root isn't needed, since we're
        # comparing thresholds...use squared values instead.)
        if accel_total > HIT_THRESHOLD:  # Large acceleration = HIT
            play_wav(random.choice(hit_sounds))  # Start playing 'hit' sound
            COLOR_ACTIVE = COLOR_HIT  # Set color to fade from
            mode = 3  # HIT mode
        elif mode == 1 and accel_total > SWING_THRESHOLD:  # Mild = SWING
            play_wav(random.choice(swing_sounds))  # Randomly choose from available swing sounds
            led.color = MAIN_COLOR  # Set color to main color
            mode = 2  # SWING mode
        elif mode == 1:
            # Idle color
            led.color = MAIN_COLOR
        elif mode > 1:  # If in SWING or HIT mode...
            if audio.playing:  # And sound currently playing...
                if mode == 2:  # If SWING,
                    led.color = MAIN_COLOR
                else:
                    led.color = HIT_COLOR  # Set color to hit color
            else:  # No sound now, but still SWING or HIT modes
                play_wav('idle', loop=True)  # Resume idle sound
                mode = 1  # Return to idle mode

Settings and Customization

If your are building the project as is, you shouldn't have to edit any of the values in the code. But, if you have a different setup, you'll want to read through the comments and make your desired changes.

  • Use the MAIN_COLOR and ALT_COLOR variables to change the main color of the RGB LED.
  • Accelerometer sensitivity can be adjusted in the HIT_THRESHOLD and SWING_THRESHOLD.
  • Audio is set to output via pin A0 (That's the analog pin #0 on the Feather M4 express).

Audio Files

The sounds used in this project are from the JKDF Soundfont pack, available to download here. The pack contains various sounds that are already in the supported audio format. Select the files you like and name them accordingly. 

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.

In the main loop, the swing and hit modes randomly choose from a list of sounds. For example, swing1.wav, swing2.wav, swing3, etc. This makes the motion effects feel much more varied and sounds less repetitive.

  • Power on – on.wav
  • Idle looping noise – idle.wav
  • Swing whoosh – swing.wav
  • Crash strike – hit.wav
This guide was first published on Jun 19, 2019. It was last updated on Jun 19, 2019. This page (Software) was last updated on Oct 15, 2019.