|
| 1 | +# SPDX-FileCopyrightText: 2017 Phillip Burgess for Adafruit Industries |
| 2 | +# |
| 3 | +# SPDX-License-Identifier: MIT |
| 4 | + |
| 5 | +import time |
| 6 | + |
| 7 | +import analogio |
| 8 | +import board |
| 9 | +import digitalio |
| 10 | +import neopixel |
| 11 | + |
| 12 | +try: |
| 13 | + import urandom as random # for v1.0 API support |
| 14 | +except ImportError: |
| 15 | + import random |
| 16 | + |
| 17 | +num_leds = 24 # 24 LED NeoPixel ring |
| 18 | +neopixel_pin = board.D0 # Pin where NeoPixels are connected |
| 19 | +vibration_pin = board.D1 # Pin where vibration switch is connected |
| 20 | +analog_pin = board.A0 # Not connected to anything |
| 21 | +strip = neopixel.NeoPixel(neopixel_pin, num_leds) |
| 22 | + |
| 23 | +default_frame_len = 0.06 # Time (in seconds) of typical animation frame |
| 24 | +max_frame_len = 0.25 # Gradually slows toward this |
| 25 | +min_frame_len = 0.005 # But sometimes as little as this |
| 26 | +cooldown_at = 2.0 # After this many seconds, start slowing down |
| 27 | +dim_at = 2.5 # After this many seconds, dim LEDs |
| 28 | +brightness_high = 0.5 # Active brightness |
| 29 | +brightness_low = 0.125 # Idle brightness |
| 30 | + |
| 31 | +color = [0, 120, 30] # Initial LED color |
| 32 | +offset = 0 # Animation position |
| 33 | +frame_len = default_frame_len # Frame-to-frame time, seconds |
| 34 | +last_vibration = 0.0 # Time of last vibration |
| 35 | +last_frame = 0.0 # Time of last animation frame |
| 36 | + |
| 37 | +# Random number generator is seeded from an unused 'floating' |
| 38 | +# analog input - this helps ensure the random color choices |
| 39 | +# aren't always the same order. |
| 40 | +pin = analogio.AnalogIn(analog_pin) |
| 41 | +random.seed(pin.value) |
| 42 | +pin.deinit() |
| 43 | + |
| 44 | +# Set up digital pin for reading vibration switch |
| 45 | +pin = digitalio.DigitalInOut(vibration_pin) |
| 46 | +pin.direction = digitalio.Direction.INPUT |
| 47 | +pin.pull = digitalio.Pull.UP |
| 48 | + |
| 49 | +while True: # Loop forever... |
| 50 | + |
| 51 | + while True: |
| 52 | + # Compare time.monotonic() against last_frame to keep |
| 53 | + # frame-to-frame animation timing consistent. Use this |
| 54 | + # idle time to check the vibration switch for activity. |
| 55 | + t = time.monotonic() |
| 56 | + if t - last_frame >= frame_len: |
| 57 | + break |
| 58 | + if not pin.value: # Vibration switch activated? |
| 59 | + color = [ # Pick a random RGB color... |
| 60 | + random.randint(32, 255), |
| 61 | + random.randint(32, 255), |
| 62 | + random.randint(32, 255)] |
| 63 | + frame_len = default_frame_len # Reset frame timing |
| 64 | + last_vibration = t # Save last trigger time |
| 65 | + |
| 66 | + # Stretch out frames if nothing has happened in a couple of seconds: |
| 67 | + if (t - last_vibration) > cooldown_at: |
| 68 | + frame_len += 0.001 # Add 1 ms |
| 69 | + if frame_len > max_frame_len: |
| 70 | + frame_len = min_frame_len |
| 71 | + |
| 72 | + # If we haven't registered a vibration in dim_at ms, go dim: |
| 73 | + if (t - last_vibration) > dim_at: |
| 74 | + strip.brightness = brightness_low |
| 75 | + else: |
| 76 | + strip.brightness = brightness_high |
| 77 | + |
| 78 | + # Erase previous pixels and light new ones: |
| 79 | + strip.fill([0, 0, 0]) |
| 80 | + for i in range(0, num_leds, 6): |
| 81 | + strip[(offset + i) % num_leds] = color |
| 82 | + |
| 83 | + strip.write() # and issue data to LED strip |
| 84 | + |
| 85 | + # Increase pixel offset until it hits 6, then roll back to 0: |
| 86 | + offset = (offset + 1) % 6 |
| 87 | + |
| 88 | + last_frame = t |
0 commit comments