84 lines
2.8 KiB
Python
84 lines
2.8 KiB
Python
import time
|
|
|
|
import analogio
|
|
import board
|
|
import digitalio
|
|
import neopixel
|
|
|
|
try:
|
|
import urandom as random # for v1.0 API support
|
|
except:
|
|
import random
|
|
|
|
num_leds = 24 # 24 LED NeoPixel ring
|
|
neopixel_pin = board.D0 # Pin where NeoPixels are connected
|
|
vibration_pin = board.D1 # Pin where vibration switch is connected
|
|
analog_pin = board.A0 # Not connected to anything
|
|
strip = neopixel.NeoPixel(neopixel_pin, num_leds)
|
|
|
|
default_frame_len = 0.06 # Time (in seconds) of typical animation frame
|
|
max_frame_len = 0.25 # Gradually slows toward this
|
|
min_frame_len = 0.005 # But sometimes as little as this
|
|
cooldown_at = 2.0 # After this many seconds, start slowing down
|
|
dim_at = 2.5 # After this many seconds, dim LEDs
|
|
brightness_high = 0.5 # Active brightness
|
|
brightness_low = 0.125 # Idle brightness
|
|
|
|
color = [0, 120, 30] # Initial LED color
|
|
offset = 0 # Animation position
|
|
frame_len = default_frame_len # Frame-to-frame time, seconds
|
|
last_vibration = 0.0 # Time of last vibration
|
|
last_frame = 0.0 # Time of last animation frame
|
|
|
|
# Random number generator is seeded from an unused 'floating'
|
|
# analog input - this helps ensure the random color choices
|
|
# aren't always the same order.
|
|
pin = analogio.AnalogIn(analog_pin)
|
|
random.seed(pin.value)
|
|
pin.deinit()
|
|
|
|
# Set up digital pin for reading vibration switch
|
|
pin = digitalio.DigitalInOut(vibration_pin)
|
|
pin.direction = digitalio.Direction.INPUT
|
|
pin.pull = digitalio.Pull.UP
|
|
|
|
while True: # Loop forever...
|
|
|
|
while True:
|
|
# Compare time.monotonic() against last_frame to keep
|
|
# frame-to-frame animation timing consistent. Use this
|
|
# idle time to check the vibration switch for activity.
|
|
t = time.monotonic()
|
|
if t - last_frame >= frame_len:
|
|
break
|
|
if not pin.value: # Vibration switch activated?
|
|
color = [ # Pick a random RGB color...
|
|
random.randint(32, 255),
|
|
random.randint(32, 255),
|
|
random.randint(32, 255)]
|
|
frame_len = default_frame_len # Reset frame timing
|
|
last_vibration = t # Save last trigger time
|
|
|
|
# Stretch out frames if nothing has happened in a couple of seconds:
|
|
if ((t - last_vibration) > cooldown_at):
|
|
frame_len += 0.001 # Add 1 ms
|
|
if frame_len > max_frame_len:
|
|
frame_len = min_frame_len
|
|
|
|
# If we haven't registered a vibration in dim_at ms, go dim:
|
|
if (t - last_vibration) > dim_at:
|
|
strip.brightness = brightness_low
|
|
else:
|
|
strip.brightness = brightness_high
|
|
|
|
# Erase previous pixels and light new ones:
|
|
strip.fill([0, 0, 0])
|
|
for i in range(0, num_leds, 6):
|
|
strip[(offset + i) % num_leds] = color
|
|
|
|
strip.write() # and issue data to LED strip
|
|
|
|
# Increase pixel offset until it hits 6, then roll back to 0:
|
|
offset = (offset + 1) % 6
|
|
|
|
last_frame = t
|