343 lines
9.8 KiB
Python
343 lines
9.8 KiB
Python
import machine
|
||
import time
|
||
import neopixel
|
||
|
||
# ============================================================
|
||
# NEOPIXELS
|
||
# ============================================================
|
||
|
||
# 3-LED strip on GP17
|
||
STRIP_PIN = 17
|
||
STRIP_LEDS = 3
|
||
strip = neopixel.NeoPixel(machine.Pin(STRIP_PIN), STRIP_LEDS)
|
||
|
||
# Single flashing LED on GP28
|
||
SINGLE_PIN = 28
|
||
single = neopixel.NeoPixel(machine.Pin(SINGLE_PIN), 1)
|
||
|
||
# ============================================================
|
||
# BUTTONS (GP20, GP21, GP22)
|
||
# ============================================================
|
||
|
||
button_pins = [20, 21, 22]
|
||
buttons = [machine.Pin(pin, machine.Pin.IN, machine.Pin.PULL_UP) for pin in button_pins]
|
||
|
||
# ============================================================
|
||
# COLOR PALETTE (index-based)
|
||
# ============================================================
|
||
|
||
colors = [
|
||
(0, 0, 0), # 0 Off
|
||
(255, 0, 0), # 1 Red
|
||
(0, 255, 0), # 2 Green
|
||
(0, 0, 255), # 3 Blue
|
||
(255, 255, 0), # 4 Yellow
|
||
(0, 255, 255), # 5 Cyan
|
||
(255, 0, 255), # 6 Magenta
|
||
(255, 128, 0), # 7 Orange
|
||
(128, 0, 255), # 8 Purple
|
||
(255, 20, 147), # 9 Pink
|
||
(128, 255, 0), # 10 Lime
|
||
(255, 255, 255) # 11 White
|
||
]
|
||
|
||
# ============================================================
|
||
# STATE FOR PIXELS 0-2 (buttons)
|
||
# ============================================================
|
||
|
||
color_index = [0, 0, 0] # Color for each strip LED
|
||
brightness = [5, 5, 5] # Brightness 0–100%
|
||
last_state = [1, 1, 1]
|
||
press_time = [0, 0, 0]
|
||
|
||
# ============================================================
|
||
# FLASHING SINGLE PIXEL (GP28)
|
||
# ============================================================
|
||
|
||
FLASH_COLOR_INDEX = 1 # Choose color from palette (0–10)
|
||
FLASH_BRIGHTNESS = 5 # 0–100%
|
||
FLASH_INTERVAL_MS = 500 # Flash speed
|
||
|
||
flash_on = False
|
||
last_flash_time = time.ticks_ms()
|
||
|
||
# ============================================================
|
||
# HELPER FUNCTIONS
|
||
# ============================================================
|
||
|
||
def apply_brightness(color, level):
|
||
r, g, b = color
|
||
factor = level / 100
|
||
return (int(r * factor), int(g * factor), int(b * factor))
|
||
|
||
def update_strip():
|
||
for i in range(STRIP_LEDS):
|
||
strip[i] = apply_brightness(colors[color_index[i]], brightness[i])
|
||
strip.write()
|
||
|
||
def single_on():
|
||
c = apply_brightness(colors[FLASH_COLOR_INDEX], FLASH_BRIGHTNESS)
|
||
single[0] = c
|
||
single.write()
|
||
|
||
def single_off():
|
||
single[0] = (0, 0, 0)
|
||
single.write()
|
||
|
||
# ============================================================
|
||
# INITIAL STATE
|
||
# ============================================================
|
||
|
||
update_strip()
|
||
single_off()
|
||
|
||
class HeartbeatNeoPixel:
|
||
def __init__(self, neopixel_obj, pixel_index=0, color=(255, 0, 0), brightness=50, interval_ms=500):
|
||
self.np = neopixel_obj
|
||
self.index = pixel_index
|
||
self.color = color
|
||
self.brightness = brightness
|
||
self.interval = interval_ms
|
||
|
||
self.state = False
|
||
self.last_time = time.ticks_ms()
|
||
|
||
def apply_brightness(self, c):
|
||
r, g, b = c
|
||
factor = self.brightness / 100
|
||
return (int(r * factor), int(g * factor), int(b * factor))
|
||
|
||
def update(self):
|
||
now = time.ticks_ms()
|
||
if time.ticks_diff(now, self.last_time) >= self.interval:
|
||
self.state = not self.state
|
||
self.last_time = now
|
||
|
||
if self.state:
|
||
self.np[self.index] = self.apply_brightness(self.color)
|
||
else:
|
||
self.np[self.index] = (0, 0, 0)
|
||
|
||
self.np.write()
|
||
|
||
# heartbeat = HeartbeatNeoPixel(
|
||
# neopixel_obj=single,
|
||
# pixel_index=0,
|
||
# color=colors[FLASH_COLOR_INDEX],
|
||
# brightness=FLASH_BRIGHTNESS,
|
||
# interval_ms=FLASH_INTERVAL_MS
|
||
# )
|
||
# ============================================================
|
||
# MAIN LOOP
|
||
# ============================================================
|
||
|
||
while True:
|
||
now = time.ticks_ms()
|
||
|
||
# -----------------------------
|
||
# BUTTONS → control pixels 0–2
|
||
# -----------------------------
|
||
heartbeat.update()
|
||
|
||
for i in range(3):
|
||
state = buttons[i].value()
|
||
|
||
if last_state[i] == 1 and state == 0:
|
||
press_time[i] = now
|
||
|
||
if last_state[i] == 0 and state == 1:
|
||
duration = time.ticks_diff(now, press_time[i])
|
||
|
||
if duration > 500:
|
||
# LONG PRESS → adjust brightness
|
||
brightness[i] += 10
|
||
if brightness[i] > 100:
|
||
brightness[i] = 10
|
||
else:
|
||
# SHORT PRESS → next color
|
||
color_indimport machine
|
||
import time
|
||
import neopixel
|
||
|
||
# ============================================================
|
||
# HEARTBEAT CLASS (NeoPixel version)
|
||
# ============================================================
|
||
|
||
class HeartbeatNeoPixel:
|
||
def __init__(self, neopixel_obj, pixel_index=0, color=(255, 0, 0),
|
||
brightness=50, interval_ms=500):
|
||
self.np = neopixel_obj
|
||
self.index = pixel_index
|
||
self.color = color
|
||
self.brightness = brightness
|
||
self.interval = interval_ms
|
||
|
||
self.state = False
|
||
self.last_time = time.ticks_ms()
|
||
|
||
def apply_brightness(self, c):
|
||
r, g, b = c
|
||
factor = self.brightness / 100
|
||
return (int(r * factor), int(g * factor), int(b * factor))
|
||
|
||
def update(self):
|
||
now = time.ticks_ms()
|
||
if time.ticks_diff(now, self.last_time) >= self.interval:
|
||
self.state = not self.state
|
||
self.last_time = now
|
||
|
||
if self.state:
|
||
self.np[self.index] = self.apply_brightness(self.color)
|
||
else:
|
||
self.np[self.index] = (0, 0, 0)
|
||
|
||
self.np.write()
|
||
|
||
|
||
# ============================================================
|
||
# NEOPIXEL SETUP
|
||
# ============================================================
|
||
|
||
# 3-LED strip on GP17
|
||
STRIP_PIN = 17
|
||
STRIP_LEDS = 3
|
||
strip = neopixel.NeoPixel(machine.Pin(STRIP_PIN), STRIP_LEDS)
|
||
|
||
# Single heartbeat pixel on GP28
|
||
SINGLE_PIN = 28
|
||
single = neopixel.NeoPixel(machine.Pin(SINGLE_PIN), 1)
|
||
|
||
# ============================================================
|
||
# BUTTONS (GP20, GP21, GP22)
|
||
# ============================================================
|
||
|
||
button_pins = [20, 21, 22]
|
||
buttons = [machine.Pin(pin, machine.Pin.IN, machine.Pin.PULL_UP)
|
||
for pin in button_pins]
|
||
|
||
# ============================================================
|
||
# COLOR PALETTE
|
||
# ============================================================
|
||
|
||
colors = [
|
||
(255, 0, 0), # 0 Red
|
||
(0, 255, 0), # 1 Green
|
||
(0, 0, 255), # 2 Blue
|
||
(255, 255, 0), # 3 Yellow
|
||
(0, 255, 255), # 4 Cyan
|
||
(255, 0, 255), # 5 Magenta
|
||
(255, 128, 0), # 6 Orange
|
||
(128, 0, 255), # 7 Purple
|
||
(255, 20, 147), # 8 Pink
|
||
(128, 255, 0), # 9 Lime
|
||
(255, 255, 255) # 10 White
|
||
]
|
||
|
||
# ============================================================
|
||
# STATE FOR PIXELS 0–2 (BUTTON CONTROLLED)
|
||
# ============================================================
|
||
|
||
color_index = [0, 0, 0]
|
||
brightness = [50, 50, 50]
|
||
last_state = [1, 1, 1]
|
||
press_time = [0, 0, 0]
|
||
|
||
# ============================================================
|
||
# HEARTBEAT PIXEL CONFIG
|
||
# ============================================================
|
||
|
||
FLASH_COLOR_INDEX = 7 # choose from palette (0–10)
|
||
FLASH_BRIGHTNESS = 100
|
||
FLASH_INTERVAL_MS = 500 # speed of heartbeat blink
|
||
|
||
heartbeat = HeartbeatNeoPixel(
|
||
neopixel_obj=single,
|
||
pixel_index=0,
|
||
color=colors[FLASH_COLOR_INDEX],
|
||
brightness=FLASH_BRIGHTNESS,
|
||
interval_ms=FLASH_INTERVAL_MS
|
||
)
|
||
|
||
# ============================================================
|
||
# HELPER FUNCTIONS
|
||
# ============================================================
|
||
|
||
def apply_brightness(color, level):
|
||
r, g, b = color
|
||
factor = level / 100
|
||
return (int(r * factor), int(g * factor), int(b * factor))
|
||
|
||
def update_strip():
|
||
for i in range(STRIP_LEDS):
|
||
strip[i] = apply_brightness(colors[color_index[i]], brightness[i])
|
||
strip.write()
|
||
|
||
# ============================================================
|
||
# INITIAL STATE
|
||
# ============================================================
|
||
|
||
update_strip()
|
||
|
||
# ============================================================
|
||
# MAIN LOOP
|
||
# ============================================================
|
||
|
||
while True:
|
||
now = time.ticks_ms()
|
||
|
||
# --------------------------------------------
|
||
# BUTTON HANDLING FOR PIXELS 0, 1, 2
|
||
# --------------------------------------------
|
||
for i in range(3):
|
||
state = buttons[i].value()
|
||
|
||
if last_state[i] == 1 and state == 0:
|
||
press_time[i] = now
|
||
|
||
if last_state[i] == 0 and state == 1:
|
||
duration = time.ticks_diff(now, press_time[i])
|
||
|
||
if duration > 500:
|
||
# LONG PRESS → brightness
|
||
brightness[i] += 10
|
||
if brightness[i] > 100:
|
||
brightness[i] = 10
|
||
else:
|
||
# SHORT PRESS → next color
|
||
color_index[i] = (color_index[i] + 1) % len(colors)
|
||
|
||
update_strip()
|
||
time.sleep_ms(200) # debounce
|
||
|
||
last_state[i] = state
|
||
|
||
# --------------------------------------------
|
||
# HEARTBEAT PIXEL UPDATE (GP28)
|
||
# --------------------------------------------
|
||
heartbeat.update()
|
||
|
||
time.sleep_ms(10)
|
||
|
||
ex[i] = (color_index[i] + 1) % len(colors)
|
||
|
||
update_strip()
|
||
time.sleep_ms(200) # debounce
|
||
|
||
last_state[i] = state
|
||
|
||
# -----------------------------
|
||
# FLASHING SINGLE PIXEL (GP28)
|
||
# -----------------------------
|
||
# if time.ticks_diff(now, last_flash_time) >= FLASH_INTERVAL_MS:
|
||
# flash_on = not flash_on
|
||
# last_flash_time = now
|
||
#
|
||
# if flash_on:
|
||
# single_on()
|
||
# else:
|
||
# single_off()
|
||
|
||
|
||
time.sleep_ms(10)
|
||
|