Add Rezz goggles CircuitPython code
This commit is contained in:
parent
5535606a82
commit
1a887fe1e4
1 changed files with 125 additions and 0 deletions
125
Rezz_Goggles/rezz.py
Executable file
125
Rezz_Goggles/rezz.py
Executable file
|
|
@ -0,0 +1,125 @@
|
|||
# pylint: disable=import-error
|
||||
|
||||
"""
|
||||
NeoPixel goggles inspired by Rezz
|
||||
|
||||
No interactive controls; speed, color and directions randomize periodically.
|
||||
"""
|
||||
|
||||
from random import random, randrange
|
||||
from time import monotonic
|
||||
import board
|
||||
import neopixel
|
||||
import adafruit_fancyled.adafruit_fancyled as fancy
|
||||
|
||||
# Configurable defaults
|
||||
|
||||
BRIGHTNESS = 0.15 # 0.0 (off) to 1.0 (max brightness)
|
||||
|
||||
# Global variables
|
||||
|
||||
# Declare NeoPixel object. Data from ItsyBitsy pin 5 because it has built-in
|
||||
# level shifting. Each LED eye has 44 pixels, so 88 total. Leave brightness
|
||||
# at 1.0 here (NeoPixel library runs faster at full brightness) and adjust
|
||||
# the global BRIGHTNESS above instead (used later when selecting HSV colors).
|
||||
PIXELS = neopixel.NeoPixel(
|
||||
board.D5, 88, auto_write=False, brightness=1.0, pixel_order=neopixel.RGB)
|
||||
|
||||
# MODE indicates the current animation state through several bit fields.
|
||||
# Bit 0 indicates the second eye is x-axis mirrored (1) or an exact copy
|
||||
# of the first (0). Bit 1 indicates hue is slowly cycling (2) vs holding
|
||||
# steady (0). Bit 2 indicates the middle of the 3 LED rings moves the
|
||||
# opposite (4) or same (0) direction as the other 2.
|
||||
MODE = randrange(8) # 0 to 7
|
||||
# Every few seconds, one of the above attributes is randomly toggled.
|
||||
# This keeps track of the last time.
|
||||
TIME_OF_LAST_MODE_SWITCH = 0
|
||||
# HUE works around the color wheel, see FancyLED docs.
|
||||
HUE = random()
|
||||
# Relative position of MIDDLE of 3 rings, 0 to 143
|
||||
MIDDLE_POS = randrange(144)
|
||||
# Relative position of INNER and OUTER rings, 0 to 143
|
||||
POS = randrange(144)
|
||||
# Amount to increment POS and MIDDLE_POS each frame
|
||||
SPEED = 2 + random() * 5
|
||||
|
||||
# The MIRROR_X and OFFSET(OUTER,MIDDLE,INNER) arrays precompute some values
|
||||
# for each pixel so we don't need to repeat that math every frame or LED.
|
||||
MIRROR_X = []
|
||||
OFFSET_OUTER = []
|
||||
OFFSET_MIDDLE = []
|
||||
OFFSET_INNER = []
|
||||
for i in range(24):
|
||||
MIRROR_X.append(67 - ((i + 11) % 24))
|
||||
OFFSET_OUTER.append(i * 6)
|
||||
for i in range(16):
|
||||
MIRROR_X.append(83 - ((i + 7) % 16))
|
||||
OFFSET_MIDDLE.append(i * 9)
|
||||
for i in range(4):
|
||||
MIRROR_X.append(87 - ((i + 2) % 4))
|
||||
OFFSET_INNER.append(i * 36)
|
||||
|
||||
|
||||
def set_pixel(index, color):
|
||||
"""Set one pixel in both eyes. Pass in pixel index (0 to 43) and
|
||||
color (as a packed RGB value). If MODE bit 0 is set, second eye
|
||||
will be X-axis mirrored, else an exact duplicate."""
|
||||
# Set pixel in first eye
|
||||
PIXELS[index] = color
|
||||
# Set pixel in second eye (mirrored or direct)
|
||||
if MODE & 1:
|
||||
PIXELS[MIRROR_X[index]] = color
|
||||
else:
|
||||
PIXELS[44 + index] = color
|
||||
|
||||
|
||||
# Main loop, repeat indefinitely...
|
||||
while True:
|
||||
|
||||
# Check if 5 seconds have passed since last mode switch
|
||||
NOW = monotonic()
|
||||
if (NOW - TIME_OF_LAST_MODE_SWITCH) > 5:
|
||||
# Yes. Save the time, change ONE mode bit, randomize speed
|
||||
TIME_OF_LAST_MODE_SWITCH = NOW
|
||||
MODE ^= 1 << randrange(3)
|
||||
SPEED = 2 + random() * 5
|
||||
|
||||
# Generate packed RGB value based on current HUE value
|
||||
COLOR = fancy.CHSV(HUE, 1.0, BRIGHTNESS).pack()
|
||||
|
||||
# Draw outer ring; 24 pixels, 8 lit
|
||||
for i in range(24):
|
||||
j = (POS + OFFSET_OUTER[i]) % 72
|
||||
if j < 24:
|
||||
set_pixel(i, COLOR)
|
||||
else:
|
||||
set_pixel(i, 0)
|
||||
# Draw middle ring; 16 pixels, 6 lit
|
||||
for i in range(16):
|
||||
j = (OFFSET_MIDDLE[i] + MIDDLE_POS) % 72
|
||||
if j < 27:
|
||||
set_pixel(24 + i, COLOR)
|
||||
else:
|
||||
set_pixel(24 + i, 0)
|
||||
# Draw inner ring; 4 pixels, 3 lit
|
||||
for i in range(4):
|
||||
j = (POS + OFFSET_INNER[i]) % 144
|
||||
if j < 108:
|
||||
set_pixel(40 + i, COLOR)
|
||||
else:
|
||||
set_pixel(40 + i, 0)
|
||||
|
||||
# Push new state to LEDs
|
||||
PIXELS.show()
|
||||
|
||||
# If MODE bit 1 is set, advance hue (else holds steady)
|
||||
if MODE & 2:
|
||||
HUE += 0.003
|
||||
|
||||
# Increment position of inner & outer ring
|
||||
POS = (POS + SPEED) % 144
|
||||
# Middle ring advances one way or other depending on MODE bit 2
|
||||
if MODE & 4:
|
||||
MIDDLE_POS = (MIDDLE_POS - SPEED) % 144
|
||||
else:
|
||||
MIDDLE_POS = (MIDDLE_POS + SPEED) % 144
|
||||
Loading…
Reference in a new issue