Skip to content

Commit b25f7ef

Browse files
committed
Adding code and sounds for Tron Disk
Adding code and sounds for Tron Disk
1 parent fa18a19 commit b25f7ef

File tree

11 files changed

+242
-0
lines changed

11 files changed

+242
-0
lines changed

Propmaker_Tron_Disk/code.py

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
# SPDX-FileCopyrightText: 2021 Liz Clark for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
"""
6+
Prop-Maker based Tron Disk
7+
Adapted from the Darksaber code
8+
Adafruit invests time and resources providing this open source code.
9+
Please support Adafruit and open source hardware by purchasing
10+
products from Adafruit!
11+
Written by Liz Clark for Adafruit Industries
12+
Copyright (c) 2023 Adafruit Industries
13+
Licensed under the MIT license.
14+
All text above must be included in any redistribution.
15+
"""
16+
17+
import time
18+
import random
19+
import board
20+
from digitalio import DigitalInOut, Direction
21+
import neopixel
22+
import adafruit_lis3dh
23+
from adafruit_led_animation.animation.solid import Solid
24+
from adafruit_led_animation.animation.pulse import Pulse
25+
from adafruit_led_animation.animation.comet import Comet
26+
27+
from adafruit_bluefruit_connect.packet import Packet
28+
from adafruit_bluefruit_connect.color_packet import ColorPacket
29+
30+
from adafruit_ble import BLERadio
31+
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
32+
from adafruit_ble.services.nordic import UARTService
33+
34+
# BLE setup
35+
ble = BLERadio()
36+
uart_service = UARTService()
37+
advertisement = ProvideServicesAdvertisement(uart_service)
38+
39+
# CUSTOMISE SENSITIVITY HERE: smaller numbers = more sensitive to motion
40+
HIT_THRESHOLD = 250
41+
SWING_THRESHOLD = 150
42+
43+
# Set to the length in seconds of the "on.wav" file
44+
POWER_ON_SOUND_DURATION = 1.7
45+
46+
# NeoPixel setup
47+
NUM_PIXELS = 37 # Number of pixels used in project
48+
NEOPIXEL_PIN = board.D5
49+
POWER_PIN = board.D10
50+
51+
enable = DigitalInOut(POWER_PIN)
52+
enable.direction = Direction.OUTPUT
53+
enable.value = False
54+
55+
strip = neopixel.NeoPixel(NEOPIXEL_PIN, NUM_PIXELS, brightness=.5, auto_write=False)
56+
strip.fill(0) # NeoPixels off ASAP on startup
57+
strip.show()
58+
59+
# default NeoPixel color is white
60+
COLOR = (0, 161, 255)
61+
62+
# NeoPixel animations
63+
pulse = Pulse(strip, speed=0.05, color=COLOR, period=3)
64+
solid = Solid(strip, color=COLOR)
65+
comet = Comet(strip, speed=0.05, color=COLOR, tail_length=40)
66+
67+
#audio
68+
try:
69+
from audiocore import WaveFile
70+
except ImportError:
71+
from audioio import WaveFile
72+
73+
try:
74+
from audioio import AudioOut
75+
except ImportError:
76+
try:
77+
from audiopwmio import PWMAudioOut as AudioOut
78+
except ImportError:
79+
pass # not always supported by every board!
80+
81+
audio = AudioOut(board.A0) # Speaker
82+
wave_file = None
83+
84+
# Set up accelerometer on I2C bus, 4G range:
85+
i2c = board.I2C() # uses board.SCL and board.SDA
86+
# i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller
87+
accel = adafruit_lis3dh.LIS3DH_I2C(i2c)
88+
accel.range = adafruit_lis3dh.RANGE_4_G
89+
90+
def play_wav(name, loop=False):
91+
"""
92+
Play a WAV file in the 'sounds' directory.
93+
:param name: partial file name string, complete name will be built around
94+
this, e.g. passing 'foo' will play file 'sounds/foo.wav'.
95+
:param loop: if True, sound will repeat indefinitely (until interrupted
96+
by another sound).
97+
"""
98+
global wave_file # pylint: disable=global-statement
99+
print("playing", name)
100+
if wave_file:
101+
wave_file.close()
102+
try:
103+
wave_file = open('sounds/' + name + '.wav', 'rb')
104+
wave = WaveFile(wave_file)
105+
audio.play(wave, loop=loop)
106+
except OSError:
107+
pass # we'll just skip playing then
108+
109+
110+
def power_on(sound, duration):
111+
"""
112+
Animate NeoPixels with accompanying sound effect for power on.
113+
:param sound: sound name (similar format to play_wav() above)
114+
:param duration: estimated duration of sound, in seconds (>0.0)
115+
"""
116+
start_time = time.monotonic() # Save audio start time
117+
play_wav(sound)
118+
while True:
119+
elapsed = time.monotonic() - start_time # Time spent playing sound
120+
if elapsed > duration: # Past sound duration?
121+
break # Stop animating
122+
comet.animate()
123+
124+
# List of swing wav files without the .wav in the name for use with play_wav()
125+
swing_sounds = [
126+
'swing1',
127+
'swing2',
128+
'swing3',
129+
'swing4',
130+
]
131+
132+
# List of hit wav files without the .wav in the name for use with play_wav()
133+
hit_sounds = [
134+
'hit1',
135+
'hit2',
136+
'hit3',
137+
'hit4',
138+
]
139+
140+
mode = 0 # Initial mode = OFF
141+
142+
#RGB LED
143+
red_led = DigitalInOut(board.D11)
144+
green_led = DigitalInOut(board.D12)
145+
blue_led = DigitalInOut(board.D13)
146+
147+
red_led.direction = Direction.OUTPUT
148+
green_led.direction = Direction.OUTPUT
149+
blue_led.direction = Direction.OUTPUT
150+
151+
blue_led.value = True
152+
red_led.value = True
153+
green_led.value = True
154+
155+
# Darksaber start-up before loop
156+
if mode == 0: # If currently off...
157+
enable.value = True
158+
power_on('on', POWER_ON_SOUND_DURATION) # Power up!
159+
play_wav('idle', loop=True) # Play idle sound now
160+
mode = 1 # Idle mode
161+
162+
while True:
163+
# begin advertising BLE
164+
ble.start_advertising(advertisement)
165+
# if no BLE connection...
166+
# allows it to be used without the bluefruit app connection
167+
while not ble.connected:
168+
if mode >= 1: # If not OFF mode...
169+
x, y, z = accel.acceleration # Read accelerometer
170+
accel_total = x * x + z * z
171+
# (Y axis isn't needed, due to the orientation that the Prop-Maker
172+
# Wing is mounted. Also, square root isn't needed, since we're
173+
# comparing thresholds...use squared values instead.)
174+
if accel_total > HIT_THRESHOLD: # Large acceleration = HIT
175+
TRIGGER_TIME = time.monotonic() # Save initial time of hit
176+
play_wav(random.choice(hit_sounds)) # Start playing 'hit' sound
177+
# NeoPixels are solid on with a hit
178+
solid.animate()
179+
mode = 3 # HIT mode
180+
elif mode == 1 and accel_total > SWING_THRESHOLD: # Mild = SWING
181+
TRIGGER_TIME = time.monotonic() # Save initial time of swing
182+
play_wav(random.choice(swing_sounds)) # Randomly choose from available swing sounds
183+
while audio.playing:
184+
pass # wait till we're done
185+
mode = 2 # we'll go back to idle mode
186+
elif mode == 1:
187+
# pulse animation when idling or swinging
188+
pulse.animate()
189+
elif mode > 1: # If in SWING or HIT mode...
190+
if audio.playing: # And sound currently playing...
191+
blend = time.monotonic() - TRIGGER_TIME # Time since triggered
192+
if mode == 2: # If SWING,
193+
blend = abs(0.5 - blend) * 2.0 # ramp up, down
194+
else: # No sound now, but still SWING or HIT modes
195+
play_wav('idle', loop=True) # Resume idle sound
196+
mode = 1 # Return to idle mode
197+
ble.stop_advertising()
198+
199+
# if BLE is connected...
200+
while ble.connected:
201+
# color picker from bluefruit app
202+
if uart_service.in_waiting:
203+
packet = Packet.from_stream(uart_service)
204+
# if a color packet is recieved...
205+
if isinstance(packet, ColorPacket):
206+
print(packet.color)
207+
# color for the different animations are updated
208+
comet.color = packet.color
209+
solid.color = packet.color
210+
pulse.color = packet.color
211+
solid.animate()
212+
# repeat of the above code
213+
if mode >= 1: # If not OFF mode...
214+
x, y, z = accel.acceleration # Read accelerometer
215+
accel_total = x * x + z * z
216+
# (Y axis isn't needed, due to the orientation that the Prop-Maker
217+
# Wing is mounted. Also, square root isn't needed, since we're
218+
# comparing thresholds...use squared values instead.)
219+
if accel_total > HIT_THRESHOLD: # Large acceleration = HIT
220+
TRIGGER_TIME = time.monotonic() # Save initial time of hit
221+
play_wav(random.choice(hit_sounds)) # Start playing 'hit' sound
222+
# NeoPixels are solid on with a hit
223+
solid.animate()
224+
mode = 3 # HIT mode
225+
elif mode == 1 and accel_total > SWING_THRESHOLD: # Mild = SWING
226+
TRIGGER_TIME = time.monotonic() # Save initial time of swing
227+
play_wav(random.choice(swing_sounds)) # Randomly choose from available swing sounds
228+
while audio.playing:
229+
pass # wait till we're done
230+
mode = 2 # we'll go back to idle mode
231+
232+
elif mode == 1:
233+
# pulse animation when idling or swinging
234+
pulse.animate()
235+
elif mode > 1: # If in SWING or HIT mode...
236+
if audio.playing: # And sound currently playing...
237+
blend = time.monotonic() - TRIGGER_TIME # Time since triggered
238+
if mode == 2: # If SWING,
239+
blend = abs(0.5 - blend) * 2.0 # ramp up, down
240+
else: # No sound now, but still SWING or HIT modes
241+
play_wav('idle', loop=True) # Resume idle sound
242+
mode = 1 # Return to idle mode
43.2 KB
Binary file not shown.
43.2 KB
Binary file not shown.
43.2 KB
Binary file not shown.
28.7 KB
Binary file not shown.
87 KB
Binary file not shown.

Propmaker_Tron_Disk/sounds/on.wav

67.3 KB
Binary file not shown.
30.4 KB
Binary file not shown.
30.4 KB
Binary file not shown.
28.2 KB
Binary file not shown.

0 commit comments

Comments
 (0)