Maker.io main logo

TRON DISC

2023-08-15 | By Adafruit Industries

License: See Original Project 3D Printing LED Strips Programmers Wearables Adafruit Feather

Courtesy of Adafruit

Guide by Ruiz Brothers

Overview

 

 

You can build a Tron-inspired prop using NeoPixel LEDs and CircuitPython.

Powered by the Adafruit Feather and Prop-Maker FeatherWing, this ‎Tron disc is fully 3D printed.

With the power of neodymium magnets, this disc can actually ‎attach to your back!

leds_loop_3

Disc_2

Using a mobile device and the Bluefruit app, you can change the ‎color of the LEDs, so it's easy to switch your team color.

The Prop-Maker FeatherWing and Feather Bluefruit are the perfect ‎pair for making advanced props with motion-activated lights and ‎sounds that can be controlled wirelessly from your phone or watch.

pair_4

pair_5

The code is written in CircuitPython, so it’s easy to modify to fit just ‎about any prop with lights and sounds.

It uses Bluetooth (BLE) and the LED animation library to trigger ‎lighting effects with the Prop-Maker’s on-board accelerometer.

lighting_6

Parts

parts_7

lighting_7

CircuitPython for Feather nRF52840

CircuitPython is a derivative of MicroPython designed to simplify ‎experimentation and education on low-costmicrocontrollers. 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.

The following instructions will show you how to install CircuitPython. ‎If you've already installed CircuitPython but are looking to update it ‎or reinstall it, the same steps work for that as well!

Set up CircuitPython Quick Start!

Follow this quick step-by-step for super-fast Python power :)

Download the latest version of CircuitPython for this board via CircuitPython.org

Click the link above to download the latest UF2 file.

Download and save it to your desktop (or wherever is handy).

download_8

Plug your Feather nRF52840 into your computer using a known-‎good USB cable.

A lot of people end up using charge-only USB cables and it is very ‎frustrating! So, make sure you have a USB cable you know is good ‎for data sync.

Double-click the Reset button next to the USB connector on your ‎board, and you will see the NeoPixel RGB LED turn green (identified ‎by the arrow in the image). If it turns red, check the USB cable, try ‎another USB port, etc. Note: The little red LED next to the USB ‎connector will pulse red. That's ok!

If double-clicking doesn't work the first time, try again. Sometimes it ‎can take a few tries to get the rhythm right!

board_9

You will see a new disk drive appear called FTHR840BOOT.

Drag the adafruit_circuitpython_etc.uf2 file to FTHR840BOOT.

drive_10

drive_11 

The LED will flash. Then, the FTHR840BOOT drive will disappear, ‎and a new disk drive called CIRCUITPY will appear.

That's it, you're done! :)

drag_12

Code

code_13

Once you've set up your Feather nRF52840 with CircuitPython, you ‎can access the code and necessary libraries bydownloading 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.

zipped_14

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2021 Liz Clark for Adafruit Industries
#
# SPDX-License-Identifier: MIT

"""
Prop-Maker based Tron Disk
Adapted from the Darksaber code
Adafruit invests time and resources providing this open source code.
Please support Adafruit and open source hardware by purchasing
products from Adafruit!
Written by Liz Clark for Adafruit Industries
Copyright (c) 2023 Adafruit Industries
Licensed under the MIT license.
All text above must be included in any redistribution.
"""

import time
import random
import board
from digitalio import DigitalInOut, Direction
import neopixel
import adafruit_lis3dh
from adafruit_led_animation.animation.solid import Solid
from adafruit_led_animation.animation.pulse import Pulse
from adafruit_led_animation.animation.comet import Comet

from adafruit_bluefruit_connect.packet import Packet
from adafruit_bluefruit_connect.color_packet import ColorPacket

from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.nordic import UARTService

# BLE setup
ble = BLERadio()
uart_service = UARTService()
advertisement = ProvideServicesAdvertisement(uart_service)

# CUSTOMISE SENSITIVITY HERE: smaller numbers = more sensitive to motion
HIT_THRESHOLD = 250
SWING_THRESHOLD = 150

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

#  NeoPixel setup
NUM_PIXELS = 37  # Number of pixels used in project
NEOPIXEL_PIN = board.D5
POWER_PIN = board.D10

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

strip = neopixel.NeoPixel(NEOPIXEL_PIN, NUM_PIXELS, brightness=.5, auto_write=False)
strip.fill(0)  # NeoPixels off ASAP on startup
strip.show()

#  default NeoPixel color is white
COLOR = (0, 161, 255)

#  NeoPixel animations
pulse = Pulse(strip, speed=0.05, color=COLOR, period=3)
solid = Solid(strip, color=COLOR)
comet = Comet(strip, speed=0.05, color=COLOR, tail_length=40)

#audio
try:
    from audiocore import WaveFile
except ImportError:
    from audioio import WaveFile

try:
    from audioio import AudioOut
except ImportError:
    try:
        from audiopwmio import PWMAudioOut as AudioOut
    except ImportError:
        pass  # not always supported by every board!

audio = AudioOut(board.A0)  # Speaker
wave_file = None

# Set up accelerometer on I2C bus, 4G range:
i2c = board.I2C()  # uses board.SCL and board.SDA
# i2c = board.STEMMA_I2C()  # For using the built-in STEMMA QT connector on a microcontroller
accel = adafruit_lis3dh.LIS3DH_I2C(i2c)
accel.range = adafruit_lis3dh.RANGE_4_G

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).
    """
    global wave_file  # pylint: disable=global-statement
    print("playing", name)
    if wave_file:
        wave_file.close()
    try:
        wave_file = open('sounds/' + name + '.wav', 'rb')
        wave = WaveFile(wave_file)
        audio.play(wave, loop=loop)
    except OSError:
        pass # we'll just skip playing then


def power_on(sound, duration):
    """
    Animate NeoPixels with accompanying sound effect for power on.
    :param sound: sound name (similar format to play_wav() above)
    :param duration: estimated duration of sound, in seconds (>0.0)
    """
    start_time = time.monotonic()  # Save audio start time
    play_wav(sound)
    while True:
        elapsed = time.monotonic() - start_time  # Time spent playing sound
        if elapsed > duration:  # Past sound duration?
            break  # Stop animating
        comet.animate()

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

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

mode = 0  # Initial mode = OFF

#RGB LED
red_led = DigitalInOut(board.D11)
green_led = DigitalInOut(board.D12)
blue_led = DigitalInOut(board.D13)

red_led.direction = Direction.OUTPUT
green_led.direction = Direction.OUTPUT
blue_led.direction = Direction.OUTPUT

blue_led.value = True
red_led.value = True
green_led.value = True

#  Darksaber start-up before loop
if mode == 0:  # If currently off...
    enable.value = True
    power_on('on', POWER_ON_SOUND_DURATION)  # Power up!
    play_wav('idle', loop=True)  # Play idle sound now
    mode = 1  # Idle mode

while True:
    #  begin advertising BLE
    ble.start_advertising(advertisement)
    #  if no BLE connection...
    #  allows it to be used without the bluefruit app connection
    while not ble.connected:
        if 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
                TRIGGER_TIME = time.monotonic()  # Save initial time of hit
                play_wav(random.choice(hit_sounds))  # Start playing 'hit' sound
                #  NeoPixels are solid on with a hit
                solid.animate()
                mode = 3  # HIT mode
            elif mode == 1 and accel_total > SWING_THRESHOLD:  # Mild = SWING
                TRIGGER_TIME = time.monotonic()  # Save initial time of swing
                play_wav(random.choice(swing_sounds))  # Randomly choose from available swing sounds
                while audio.playing:
                    pass # wait till we're done
                mode = 2  # we'll go back to idle mode
            elif mode == 1:
                #  pulse animation when idling or swinging
                pulse.animate()
            elif mode > 1:  # If in SWING or HIT mode...
                if audio.playing:  # And sound currently playing...
                    blend = time.monotonic() - TRIGGER_TIME  # Time since triggered
                    if mode == 2:  # If SWING,
                        blend = abs(0.5 - blend) * 2.0  # ramp up, down
                else:  # No sound now, but still SWING or HIT modes
                    play_wav('idle', loop=True)  # Resume idle sound
                    mode = 1  # Return to idle mode
    ble.stop_advertising()

    #  if BLE is connected...
    while ble.connected:
        #  color picker from bluefruit app
        if uart_service.in_waiting:
            packet = Packet.from_stream(uart_service)
            #  if a color packet is recieved...
            if isinstance(packet, ColorPacket):
                print(packet.color)
                #  color for the different animations are updated
                comet.color = packet.color
                solid.color = packet.color
                pulse.color = packet.color
                solid.animate()
        #  repeat of the above code
        if 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
                TRIGGER_TIME = time.monotonic()  # Save initial time of hit
                play_wav(random.choice(hit_sounds))  # Start playing 'hit' sound
                #  NeoPixels are solid on with a hit
                solid.animate()
                mode = 3  # HIT mode
            elif mode == 1 and accel_total > SWING_THRESHOLD:  # Mild = SWING
                TRIGGER_TIME = time.monotonic()  # Save initial time of swing
                play_wav(random.choice(swing_sounds))  # Randomly choose from available swing sounds
                while audio.playing:
                    pass # wait till we're done
                mode = 2  # we'll go back to idle mode

            elif mode == 1:
                #  pulse animation when idling or swinging
                pulse.animate()
            elif mode > 1:  # If in SWING or HIT mode...
                if audio.playing:  # And sound currently playing...
                    blend = time.monotonic() - TRIGGER_TIME  # Time since triggered
                    if mode == 2:  # If SWING,
                        blend = abs(0.5 - blend) * 2.0  # ramp up, down
                else:  # No sound now, but still SWING or HIT modes
                    play_wav('idle', loop=True)  # Resume idle sound
                    mode = 1  # Return to idle mode

View on GitHub

Upload the Code and Libraries to the Feather ‎nRF52840‎

After downloading the Project Bundle, plug your Feather into the ‎computer's USB port with a known good USB data+power cable. 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 ‎nRF52840's CIRCUITPY drive.

  • code.py

  • lib directory

  • sound directory

Your Feather nRF52840 CIRCUITPY drive should look like this after ‎copying the lib folder, sound folder and the code.py file.

copying_15

Circuit Diagram

The wiring diagram below provides a visual reference for connecting ‎the components. It is not true to scale; it is justmeant to be used as ‎reference. This diagram was created using the Fritzing software ‎package.

Take a moment to review the components in the circuit diagram. ‎This illustration is meant for referencing wiredconnections - the ‎length of wire, position and size of components are not exact.

diagram_16

illustration_17

3D Printing

Parts List

STL files for 3D printing are oriented to print "as-is" on FDM style machines. Parts are designed to 3D print without any support material. Original design source may be downloaded using the links below.

print_18

Edit Design

Download STLs

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

slice_19

Filament Change

Use the filament change script to print the disc in multiple colors.

Go to Extensions -> Post Processing -> Modify G-Code

Select Filament Change.

filament_21

filament_20

Top Cover Layers

Enter 12 in the Layer section to print the first 12 layers in white PLA.

Click on add script and select Filament Change to add one more ‎color change.

Layers 13 to 123 will print in black PLA.

Enter 123 in the Layer section to print the rest of the cover in white ‎PLA.

Layers 124 and up will print the remainder in white PLA.

layers_22

Bottom Cover Layers

Add a filament change script and enter 3 in the Layer section.

Layers 1 to 3 will print in black PLA. Layers 4 and up will print in white PLA.

bottom_23

Assembly

Solder Headers

Align socket header pins to the Prop-Maker wing. Use a breadboard ‎to help solder the short side of the headers to the Prop-Maker.

Solder socket headers to the top side of the Feather nRF52840 board. ‎Then, solder pin headers to the bottom side of the Prop-Maker ‎FeatherWing so it can be plugged into the Feather.

solder_24

solder_25

Mount Feather

Align the Feather board to the stand-offs on the bottom cover part, ‎with the USB port facing the slide switch mount.

mount_26

Measure LED strip

Place the LED strips over the inner and outer walls, measure and cut to length.

The side light LEDs will mount to the inner wall.

mount_27

Remove Sheath

Remove the sheath to fit the LED strips around the walls.

remove_28

LED wires

Use a 3 pin JST connector to connect the LED strips to the Prop-Maker port.

led_29

 

Solder LED strips

Measure a short silicone ribbon to connect both LED strips.

connect_30

Place LEDs

Plug the 3 pin JST connector into the STEMMA port on the Prop-‎Maker.

connect_31

USB extension

Measure a short 5 wire silicon ribbon cable to extend the USB port.

usb_32

Mount the USB breakout

The USB breakout board mounts with two M2.5x4mm long screws.

usb_33

Speaker Mount

Connect the speaker to the port on the Prop-Maker.

speaker_34

Slide switch mount

Measure a short 2 wire cable to enable the slide switch.

EN and G on the Prop-Maker connect to any two pins on the slide switch.

The slide switch press fits at an angle with the slide positioned in the middle.

speaker_35

Battery extension

Shorten a 2 pin JST wire to connect the battery.

battery_36

Battery mount

A 2200mAh battery slides between the clips on the base.

battery_37

Place Magnets

Carefully orient the magnets in each mount. The caps tightly press fit over the magnets.

place_38

Attach cover

Align the slide switch and USB port to the top cover.

place_39

Cover screws

Align the case to the four screws holes on the side.

Use four M2x10mm long nylon screws to attach the top and bottom ‎cover together.

Harness assemble

The harness Plate is attached to the back of a Running Vest with ‎nylon string. Pass the string through the mesh fabric and loops on the Plate.

Place magnets into each mount and press-fit a printed cap over ‎each one.

harness_40

harness_41

Complete!

complete_42

Use

Bluetooth Control

This project uses the Adafruit Bluefruit LE connect app (available ‎free for Android and iOS) to trigger the lights and sounds. It uses the ‎Color Picker module to choose different colors. If you haven't ‎downloaded the app yet, use the button below to install it on your ‎mobile device.

bluetooth_43

Download BLE Connect App iOS

Download BLE Connect App for Android

Using Bluefruit LE Connect App

Turn on the Feather by either connecting it via USB to your ‎computer or with the slide switch.

Open the Bluefruit LE Connect app and locate the device ‎named CIRCUITPY and tap the connect button. Locate and tap ‎on Controller. Under module, tap on Color Picker.

Color Picker

You can change the color of the NeoPixel LEDs by using the Color ‎Picker. Tap connect, select Controller. Under module, tap on Color ‎Picker. Use the color wheel to select a color and the slider to adjust ‎the brightness. Tap the send color button to trigger the color.

Apple Watch

If you have an Apple Watch, you can use the Bluefruit LE Connect ‎App just like the mobile app. The Apple Watch app is included with ‎the iOS app download.

apple_44

Led_strips_leds_hero_hoddie_45

制造商零件编号 4062
ADAFRUIT FEATHER NRF52840 EXPRES
Adafruit Industries LLC
制造商零件编号 3988
PROP-MAKER FEATHERWING LOOSE HDR
Adafruit Industries LLC
制造商零件编号 3636
ADDRESS LED STRIP 1M
Adafruit Industries LLC
制造商零件编号 3923
SPEAKER 8OHM 1W TOP PORT
Adafruit Industries LLC
制造商零件编号 3894
JST PH 3PIN TO FEMALE SOCKET CAB
Adafruit Industries LLC
制造商零件编号 1833
USB MICRO-B BREAKOUT BOARD
Adafruit Industries LLC
制造商零件编号 3890
CBL RIBN 10COND FLAT BLACK 3.28'
Adafruit Industries LLC
制造商零件编号 1131
JST-PH BATTERY EXT CABLE
Adafruit Industries LLC
Add all DigiKey Parts to Cart
TechForum

Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.

Visit TechForum