Skip to content

Commit 51679ea

Browse files
authored
Merge pull request #955 from adafruit/rezz
Add Rezz goggles CircuitPython code
2 parents 5535606 + 1a887fe commit 51679ea

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed

Rezz_Goggles/rezz.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# pylint: disable=import-error
2+
3+
"""
4+
NeoPixel goggles inspired by Rezz
5+
6+
No interactive controls; speed, color and directions randomize periodically.
7+
"""
8+
9+
from random import random, randrange
10+
from time import monotonic
11+
import board
12+
import neopixel
13+
import adafruit_fancyled.adafruit_fancyled as fancy
14+
15+
# Configurable defaults
16+
17+
BRIGHTNESS = 0.15 # 0.0 (off) to 1.0 (max brightness)
18+
19+
# Global variables
20+
21+
# Declare NeoPixel object. Data from ItsyBitsy pin 5 because it has built-in
22+
# level shifting. Each LED eye has 44 pixels, so 88 total. Leave brightness
23+
# at 1.0 here (NeoPixel library runs faster at full brightness) and adjust
24+
# the global BRIGHTNESS above instead (used later when selecting HSV colors).
25+
PIXELS = neopixel.NeoPixel(
26+
board.D5, 88, auto_write=False, brightness=1.0, pixel_order=neopixel.RGB)
27+
28+
# MODE indicates the current animation state through several bit fields.
29+
# Bit 0 indicates the second eye is x-axis mirrored (1) or an exact copy
30+
# of the first (0). Bit 1 indicates hue is slowly cycling (2) vs holding
31+
# steady (0). Bit 2 indicates the middle of the 3 LED rings moves the
32+
# opposite (4) or same (0) direction as the other 2.
33+
MODE = randrange(8) # 0 to 7
34+
# Every few seconds, one of the above attributes is randomly toggled.
35+
# This keeps track of the last time.
36+
TIME_OF_LAST_MODE_SWITCH = 0
37+
# HUE works around the color wheel, see FancyLED docs.
38+
HUE = random()
39+
# Relative position of MIDDLE of 3 rings, 0 to 143
40+
MIDDLE_POS = randrange(144)
41+
# Relative position of INNER and OUTER rings, 0 to 143
42+
POS = randrange(144)
43+
# Amount to increment POS and MIDDLE_POS each frame
44+
SPEED = 2 + random() * 5
45+
46+
# The MIRROR_X and OFFSET(OUTER,MIDDLE,INNER) arrays precompute some values
47+
# for each pixel so we don't need to repeat that math every frame or LED.
48+
MIRROR_X = []
49+
OFFSET_OUTER = []
50+
OFFSET_MIDDLE = []
51+
OFFSET_INNER = []
52+
for i in range(24):
53+
MIRROR_X.append(67 - ((i + 11) % 24))
54+
OFFSET_OUTER.append(i * 6)
55+
for i in range(16):
56+
MIRROR_X.append(83 - ((i + 7) % 16))
57+
OFFSET_MIDDLE.append(i * 9)
58+
for i in range(4):
59+
MIRROR_X.append(87 - ((i + 2) % 4))
60+
OFFSET_INNER.append(i * 36)
61+
62+
63+
def set_pixel(index, color):
64+
"""Set one pixel in both eyes. Pass in pixel index (0 to 43) and
65+
color (as a packed RGB value). If MODE bit 0 is set, second eye
66+
will be X-axis mirrored, else an exact duplicate."""
67+
# Set pixel in first eye
68+
PIXELS[index] = color
69+
# Set pixel in second eye (mirrored or direct)
70+
if MODE & 1:
71+
PIXELS[MIRROR_X[index]] = color
72+
else:
73+
PIXELS[44 + index] = color
74+
75+
76+
# Main loop, repeat indefinitely...
77+
while True:
78+
79+
# Check if 5 seconds have passed since last mode switch
80+
NOW = monotonic()
81+
if (NOW - TIME_OF_LAST_MODE_SWITCH) > 5:
82+
# Yes. Save the time, change ONE mode bit, randomize speed
83+
TIME_OF_LAST_MODE_SWITCH = NOW
84+
MODE ^= 1 << randrange(3)
85+
SPEED = 2 + random() * 5
86+
87+
# Generate packed RGB value based on current HUE value
88+
COLOR = fancy.CHSV(HUE, 1.0, BRIGHTNESS).pack()
89+
90+
# Draw outer ring; 24 pixels, 8 lit
91+
for i in range(24):
92+
j = (POS + OFFSET_OUTER[i]) % 72
93+
if j < 24:
94+
set_pixel(i, COLOR)
95+
else:
96+
set_pixel(i, 0)
97+
# Draw middle ring; 16 pixels, 6 lit
98+
for i in range(16):
99+
j = (OFFSET_MIDDLE[i] + MIDDLE_POS) % 72
100+
if j < 27:
101+
set_pixel(24 + i, COLOR)
102+
else:
103+
set_pixel(24 + i, 0)
104+
# Draw inner ring; 4 pixels, 3 lit
105+
for i in range(4):
106+
j = (POS + OFFSET_INNER[i]) % 144
107+
if j < 108:
108+
set_pixel(40 + i, COLOR)
109+
else:
110+
set_pixel(40 + i, 0)
111+
112+
# Push new state to LEDs
113+
PIXELS.show()
114+
115+
# If MODE bit 1 is set, advance hue (else holds steady)
116+
if MODE & 2:
117+
HUE += 0.003
118+
119+
# Increment position of inner & outer ring
120+
POS = (POS + SPEED) % 144
121+
# Middle ring advances one way or other depending on MODE bit 2
122+
if MODE & 4:
123+
MIDDLE_POS = (MIDDLE_POS - SPEED) % 144
124+
else:
125+
MIDDLE_POS = (MIDDLE_POS + SPEED) % 144

0 commit comments

Comments
 (0)