from machine import Pin
import neopixel
import time
import urandom
# -----------------------------
# Konfiguration
# -----------------------------
NUM_LEDS = 8
NUM_STRIPS = 6
STRIP_PINS = [2, 3, 4, 5, 6, 7]
EFFECT_BUTTON_PIN = 8
WHITE_TRIGGER_PIN = 9
# Setup NeoPixel-Streifen
strips = [neopixel.NeoPixel(Pin(pin), NUM_LEDS) for pin in STRIP_PINS]
# Pins
button_pin = Pin(EFFECT_BUTTON_PIN, Pin.IN, Pin.PULL_UP)
white_input = Pin(WHITE_TRIGGER_PIN, Pin.IN, Pin.PULL_UP)
# Modusverwaltung
mode = 0
num_modes = 7 # 0=aus, 1..6 alte Effekte, 7=äußere LEDs rot
# Debounce
last_button_state = 1
last_debounce_time = time.ticks_ms()
debounce_delay = 200 # ms
# -----------------------------
# Hilfsfunktionen
# -----------------------------
def set_all(r, g, b):
for strip in strips:
for i in range(NUM_LEDS):
strip[i] = (r, g, b)
strip.write()
def wheel(pos):
if pos < 85:
return (pos * 3, 255 - pos * 3, 0)
elif pos < 170:
pos -= 85
return (255 - pos * 3, 0, pos * 3)
else:
pos -= 170
return (0, pos * 3, 255 - pos * 3)
# -----------------------------
# Effektzustände
# -----------------------------
effect_state = {
"fade_level": 0,
"fade_dir": 1,
"chase_pos": 0,
"twinkle_last": time.ticks_ms(),
"twinkle_on": [],
"gradient_shift": 0,
"breath_level": 0,
"breath_dir": 1
}
# -----------------------------
# Effekte (nicht-blockierend)
# -----------------------------
def effect_off():
set_all(0, 0, 0)
def effect_fade():
level = effect_state["fade_level"]
dir = effect_state["fade_dir"]
set_all(level, level, level)
level += dir * 5
if level >= 255:
level = 255
dir = -1
elif level <= 0:
level = 0
dir = 1
effect_state["fade_level"] = level
effect_state["fade_dir"] = dir
def effect_theater_chase():
pos = effect_state["chase_pos"]
for strip in strips:
for i in range(NUM_LEDS):
strip[i] = (255, 0, 0) if (i + pos) % 2 == 0 else (0, 0, 0)
strip.write()
effect_state["chase_pos"] = (pos + 1) % 2
def effect_fire():
for strip in strips:
for i in range(NUM_LEDS):
r = urandom.getrandbits(7) + 128 # 128-255
g = urandom.getrandbits(5) # 0-31
b = 0
strip[i] = (r, g, b)
strip.write()
def effect_twinkle():
now = time.ticks_ms()
if time.ticks_diff(now, effect_state["twinkle_last"]) > 100:
effect_state["twinkle_on"] = [urandom.getrandbits(1) for _ in range(NUM_LEDS)]
for strip in strips:
for i in range(NUM_LEDS):
val = 255 if effect_state["twinkle_on"][i] else 0
strip[i] = (val, val, val)
strip.write()
effect_state["twinkle_last"] = now
def effect_color_gradient():
shift = effect_state["gradient_shift"]
for j in range(NUM_LEDS):
color = wheel((j * 256 // NUM_LEDS + shift) % 256)
for strip in strips:
strip[j] = color
for strip in strips:
strip.write()
effect_state["gradient_shift"] = (shift + 2) % 256
def effect_breathing():
level = effect_state["breath_level"]
dir = effect_state["breath_dir"]
color = int(level)
set_all(0, 0, color)
level += dir * 5
if level >= 255:
level = 255
dir = -1
elif level <= 0:
level = 0
dir = 1
effect_state["breath_level"] = level
effect_state["breath_dir"] = dir
def effect_outer_red():
for strip in strips:
for i in range(NUM_LEDS):
if i == 0 or i == NUM_LEDS - 1:
strip[i] = (255, 0, 0)
else:
strip[i] = (0, 0, 0)
strip.write()
# -----------------------------
# Hauptschleife
# -----------------------------
while True:
# Weißlicht hat Vorrang
if white_input.value() == 0:
set_all(255, 255, 255)
else:
if mode == 0:
effect_off()
elif mode == 1:
effect_fade()
elif mode == 2:
effect_theater_chase()
elif mode == 3:
effect_fire()
elif mode == 4:
effect_twinkle()
elif mode == 5:
effect_color_gradient()
elif mode == 6:
effect_breathing()
elif mode == 7:
effect_outer_red()
# Taster für Effektwechsel mit Debounce
current_state = button_pin.value()
if current_state == 0 and last_button_state == 1:
if time.ticks_diff(time.ticks_ms(), last_debounce_time) > debounce_delay:
mode = (mode + 1) % (num_modes + 1)
last_debounce_time = time.ticks_ms()
last_button_state = current_state
# Kurze Pause für CPU
time.sleep(0.02)