Skip to content

Commit 9d5c79e

Browse files
committed
Adding code for non-BLE darksaber
code for non-BLE darksaber
1 parent 55538fe commit 9d5c79e

File tree

1 file changed

+175
-0
lines changed

1 file changed

+175
-0
lines changed

CircuitPython_Darksaber/code.py

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
"""
2+
Prop-Maker based Darksaber
3+
Adapted from the Prop-Maker based Master Sword code
4+
by Kattni Rembor & Limor Fried
5+
Adafruit invests time and resources providing this open source code.
6+
Please support Adafruit and open source hardware by purchasing
7+
products from Adafruit!
8+
Written by Liz Clark for Adafruit Industries
9+
Copyright (c) 2021 Adafruit Industries
10+
Licensed under the MIT license.
11+
All text above must be included in any redistribution.
12+
"""
13+
14+
import time
15+
import random
16+
import board
17+
from digitalio import DigitalInOut, Direction
18+
import neopixel
19+
import adafruit_lis3dh
20+
from adafruit_led_animation.animation.solid import Solid
21+
from adafruit_led_animation.animation.pulse import Pulse
22+
from adafruit_led_animation.animation.comet import Comet
23+
24+
# CUSTOMISE SENSITIVITY HERE: smaller numbers = more sensitive to motion
25+
HIT_THRESHOLD = 250
26+
SWING_THRESHOLD = 150
27+
28+
# Set to the length in seconds of the "on.wav" file
29+
POWER_ON_SOUND_DURATION = 1.7
30+
31+
# NeoPixel setup
32+
NUM_PIXELS = 34 # Number of pixels used in project
33+
NEOPIXEL_PIN = board.D5
34+
POWER_PIN = board.D10
35+
36+
enable = DigitalInOut(POWER_PIN)
37+
enable.direction = Direction.OUTPUT
38+
enable.value = False
39+
40+
strip = neopixel.NeoPixel(NEOPIXEL_PIN, NUM_PIXELS, brightness=.5, auto_write=False)
41+
strip.fill(0) # NeoPixels off ASAP on startup
42+
strip.show()
43+
44+
# default NeoPixel color is white
45+
COLOR = (255, 255, 255)
46+
47+
# NeoPixel animations
48+
pulse = Pulse(strip, speed=0.05, color=COLOR, period=3)
49+
solid = Solid(strip, color=COLOR)
50+
comet = Comet(strip, speed=0.05, color=COLOR, tail_length=40)
51+
52+
#audio
53+
try:
54+
from audiocore import WaveFile
55+
except ImportError:
56+
from audioio import WaveFile
57+
58+
try:
59+
from audioio import AudioOut
60+
except ImportError:
61+
try:
62+
from audiopwmio import PWMAudioOut as AudioOut
63+
except ImportError:
64+
pass # not always supported by every board!
65+
66+
audio = AudioOut(board.A0) # Speaker
67+
wave_file = None
68+
69+
# Set up accelerometer on I2C bus, 4G range:
70+
i2c = board.I2C()
71+
accel = adafruit_lis3dh.LIS3DH_I2C(i2c)
72+
accel.range = adafruit_lis3dh.RANGE_4_G
73+
74+
def play_wav(name, loop=False):
75+
"""
76+
Play a WAV file in the 'sounds' directory.
77+
:param name: partial file name string, complete name will be built around
78+
this, e.g. passing 'foo' will play file 'sounds/foo.wav'.
79+
:param loop: if True, sound will repeat indefinitely (until interrupted
80+
by another sound).
81+
"""
82+
global wave_file # pylint: disable=global-statement
83+
print("playing", name)
84+
if wave_file:
85+
wave_file.close()
86+
try:
87+
wave_file = open('sounds/' + name + '.wav', 'rb')
88+
wave = WaveFile(wave_file)
89+
audio.play(wave, loop=loop)
90+
except OSError:
91+
pass # we'll just skip playing then
92+
93+
94+
def power_on(sound, duration):
95+
"""
96+
Animate NeoPixels with accompanying sound effect for power on.
97+
:param sound: sound name (similar format to play_wav() above)
98+
:param duration: estimated duration of sound, in seconds (>0.0)
99+
"""
100+
start_time = time.monotonic() # Save audio start time
101+
play_wav(sound)
102+
while True:
103+
elapsed = time.monotonic() - start_time # Time spent playing sound
104+
if elapsed > duration: # Past sound duration?
105+
break # Stop animating
106+
comet.animate()
107+
108+
# List of swing wav files without the .wav in the name for use with play_wav()
109+
swing_sounds = [
110+
'swing1',
111+
'swing2',
112+
'swing3',
113+
'swing4',
114+
]
115+
116+
# List of hit wav files without the .wav in the name for use with play_wav()
117+
hit_sounds = [
118+
'hit1',
119+
'hit2',
120+
'hit3',
121+
'hit4',
122+
]
123+
124+
mode = 0 # Initial mode = OFF
125+
126+
#RGB LED
127+
red_led = DigitalInOut(board.D11)
128+
green_led = DigitalInOut(board.D12)
129+
blue_led = DigitalInOut(board.D13)
130+
131+
red_led.direction = Direction.OUTPUT
132+
green_led.direction = Direction.OUTPUT
133+
blue_led.direction = Direction.OUTPUT
134+
135+
blue_led.value = True
136+
red_led.value = True
137+
green_led.value = True
138+
139+
# Main loop
140+
while True:
141+
142+
if mode == 0: # If currently off...
143+
enable.value = True
144+
power_on('on', POWER_ON_SOUND_DURATION) # Power up!
145+
play_wav('idle', loop=True) # Play idle sound now
146+
mode = 1 # Idle mode
147+
148+
elif mode >= 1: # If not OFF mode...
149+
x, y, z = accel.acceleration # Read accelerometer
150+
accel_total = x * x + z * z
151+
# (Y axis isn't needed, due to the orientation that the Prop-Maker
152+
# Wing is mounted. Also, square root isn't needed, since we're
153+
# comparing thresholds...use squared values instead.)
154+
if accel_total > HIT_THRESHOLD: # Large acceleration = HIT
155+
TRIGGER_TIME = time.monotonic() # Save initial time of hit
156+
play_wav(random.choice(hit_sounds)) # Start playing 'hit' sound
157+
solid.animate()
158+
mode = 3 # HIT mode
159+
elif mode == 1 and accel_total > SWING_THRESHOLD: # Mild = SWING
160+
TRIGGER_TIME = time.monotonic() # Save initial time of swing
161+
play_wav(random.choice(swing_sounds)) # Randomly choose from available swing sounds
162+
while audio.playing:
163+
pass # wait till we're done
164+
mode = 2 # we'll go back to idle mode
165+
166+
elif mode == 1:
167+
pulse.animate()
168+
elif mode > 1: # If in SWING or HIT mode...
169+
if audio.playing: # And sound currently playing...
170+
blend = time.monotonic() - TRIGGER_TIME # Time since triggered
171+
if mode == 2: # If SWING,
172+
blend = abs(0.5 - blend) * 2.0 # ramp up, down
173+
else: # No sound now, but still SWING or HIT modes
174+
play_wav('idle', loop=True) # Resume idle sound
175+
mode = 1 # Return to idle mode

0 commit comments

Comments
 (0)