Add segments and double_circle patterns with shared presets
Introduce double_circle and segments-based patterns on the Pico, refactor the Presets engine to expose a logical ring over all strips, and migrate presets/test code from the old point pattern to segments while switching to a top-level presets.json. Made-with: Cursor
This commit is contained in:
264
pico/test/test_multi_patterns.py
Normal file
264
pico/test/test_multi_patterns.py
Normal file
@@ -0,0 +1,264 @@
|
||||
"""
|
||||
On-device test that exercises Segments and multiple SegmentsTransition presets via Presets.
|
||||
|
||||
Usage (from pico/ dir or project root with adjusted paths):
|
||||
|
||||
mpremote connect <device> cp src/*.py :
|
||||
mpremote connect <device> cp src/patterns/*.py :patterns
|
||||
mpremote connect <device> cp lib/*.py :
|
||||
mpremote connect <device> cp test/test_multi_patterns.py :
|
||||
mpremote connect <device> run test_multi_patterns.py
|
||||
"""
|
||||
|
||||
import utime
|
||||
|
||||
from presets import Presets, Preset
|
||||
|
||||
|
||||
def run_for(presets, duration_ms):
|
||||
"""Tick the current pattern for duration_ms."""
|
||||
start = utime.ticks_ms()
|
||||
while utime.ticks_diff(utime.ticks_ms(), start) < duration_ms:
|
||||
presets.tick()
|
||||
utime.sleep_ms(10)
|
||||
|
||||
|
||||
def make_segments_preset(name, colors, n_values, brightness=255):
|
||||
"""
|
||||
Helper to build a Preset for the 'segments' pattern.
|
||||
|
||||
colors: list of up to 4 (r,g,b) tuples
|
||||
n_values: list/tuple of 8 ints [n1..n8]
|
||||
"""
|
||||
cs = list(colors)[:4]
|
||||
while len(cs) < 4:
|
||||
cs.append((0, 0, 0))
|
||||
|
||||
n1, n2, n3, n4, n5, n6, n7, n8 = n_values
|
||||
data = {
|
||||
"p": "segments",
|
||||
"c": cs,
|
||||
"b": brightness,
|
||||
"n1": n1,
|
||||
"n2": n2,
|
||||
"n3": n3,
|
||||
"n4": n4,
|
||||
"n5": n5,
|
||||
"n6": n6,
|
||||
"n7": n7,
|
||||
"n8": n8,
|
||||
}
|
||||
return name, Preset(data)
|
||||
|
||||
|
||||
def make_segments_transition_preset(name, colors, n_values, duration_ms=1000, brightness=255):
|
||||
"""
|
||||
Helper to build a Preset for the 'segments_transition' pattern.
|
||||
|
||||
Starts from whatever is currently displayed and fades to the
|
||||
new segments layout over duration_ms.
|
||||
"""
|
||||
cs = list(colors)[:4]
|
||||
while len(cs) < 4:
|
||||
cs.append((0, 0, 0))
|
||||
|
||||
n1, n2, n3, n4, n5, n6, n7, n8 = n_values
|
||||
data = {
|
||||
"p": "segments_transition",
|
||||
"c": cs,
|
||||
"b": brightness,
|
||||
"d": duration_ms,
|
||||
"n1": n1,
|
||||
"n2": n2,
|
||||
"n3": n3,
|
||||
"n4": n4,
|
||||
"n5": n5,
|
||||
"n6": n6,
|
||||
"n7": n7,
|
||||
"n8": n8,
|
||||
}
|
||||
return name, Preset(data)
|
||||
|
||||
|
||||
def main():
|
||||
presets = Presets()
|
||||
presets.load()
|
||||
|
||||
num_leds = presets.strip_length(0)
|
||||
if num_leds <= 0:
|
||||
print("No strips; aborting multi-pattern test.")
|
||||
return
|
||||
|
||||
print("Starting multi-pattern test with Presets...")
|
||||
|
||||
quarter = num_leds // 4
|
||||
half = num_leds // 2
|
||||
|
||||
# 1. Static segments: simple R/G/B bands
|
||||
name_static, preset_static = make_segments_preset(
|
||||
"mp_segments_static",
|
||||
colors=[(255, 0, 0), (0, 255, 0), (0, 0, 255)],
|
||||
n_values=[
|
||||
0,
|
||||
quarter - 1, # red
|
||||
quarter,
|
||||
2 * quarter - 1, # green
|
||||
2 * quarter,
|
||||
3 * quarter - 1, # blue
|
||||
0,
|
||||
-1,
|
||||
],
|
||||
)
|
||||
|
||||
# 2a. Segments transition: fade from previous buffer to new colors (slow)
|
||||
name_trans1, preset_trans1 = make_segments_transition_preset(
|
||||
"mp_segments_transition_1",
|
||||
colors=[(255, 255, 255), (255, 0, 255), (0, 255, 255)],
|
||||
n_values=[
|
||||
0,
|
||||
half - 1, # white on first half
|
||||
half,
|
||||
num_leds - 1, # magenta on second half
|
||||
0,
|
||||
-1, # cyan unused in this example
|
||||
0,
|
||||
-1,
|
||||
],
|
||||
duration_ms=3000,
|
||||
)
|
||||
|
||||
# 2b. Segments transition: fade between two different segment layouts
|
||||
name_trans2, preset_trans2 = make_segments_transition_preset(
|
||||
"mp_segments_transition_2",
|
||||
colors=[(255, 0, 0), (0, 0, 255)],
|
||||
n_values=[
|
||||
0,
|
||||
quarter - 1, # red first quarter
|
||||
quarter,
|
||||
2 * quarter - 1, # blue second quarter
|
||||
0,
|
||||
-1,
|
||||
0,
|
||||
-1,
|
||||
],
|
||||
duration_ms=4000,
|
||||
)
|
||||
|
||||
# 2c. Segments transition: thin moving band (center quarter only)
|
||||
band_start = quarter // 2
|
||||
band_end = band_start + quarter
|
||||
name_trans3, preset_trans3 = make_segments_transition_preset(
|
||||
"mp_segments_transition_3",
|
||||
colors=[(0, 255, 0)],
|
||||
n_values=[
|
||||
band_start,
|
||||
band_end - 1, # green band in the middle
|
||||
0,
|
||||
-1,
|
||||
0,
|
||||
-1,
|
||||
0,
|
||||
-1,
|
||||
],
|
||||
duration_ms=5000,
|
||||
)
|
||||
|
||||
# 2d. Segments transition: full-ring warm white fade
|
||||
name_trans4, preset_trans4 = make_segments_transition_preset(
|
||||
"mp_segments_transition_4",
|
||||
colors=[(255, 200, 100)],
|
||||
n_values=[
|
||||
0,
|
||||
num_leds - 1, # entire strip
|
||||
0,
|
||||
-1,
|
||||
0,
|
||||
-1,
|
||||
0,
|
||||
-1,
|
||||
],
|
||||
duration_ms=6000,
|
||||
)
|
||||
|
||||
# 2e. Segments transition: alternating warm/cool halves
|
||||
name_trans5, preset_trans5 = make_segments_transition_preset(
|
||||
"mp_segments_transition_5",
|
||||
colors=[(255, 180, 100), (100, 180, 255)],
|
||||
n_values=[
|
||||
0,
|
||||
half - 1, # warm first half
|
||||
half,
|
||||
num_leds - 1, # cool second half
|
||||
0,
|
||||
-1,
|
||||
0,
|
||||
-1,
|
||||
],
|
||||
duration_ms=5000,
|
||||
)
|
||||
|
||||
# 2f. Segments transition: narrow red band near start
|
||||
narrow_start = num_leds // 16
|
||||
narrow_end = narrow_start + max(4, num_leds // 32)
|
||||
name_trans6, preset_trans6 = make_segments_transition_preset(
|
||||
"mp_segments_transition_6",
|
||||
colors=[(255, 0, 0)],
|
||||
n_values=[
|
||||
narrow_start,
|
||||
narrow_end - 1,
|
||||
0,
|
||||
-1,
|
||||
0,
|
||||
-1,
|
||||
0,
|
||||
-1,
|
||||
],
|
||||
duration_ms=4000,
|
||||
)
|
||||
|
||||
# Register presets in Presets and run them in sequence
|
||||
presets.presets[name_static] = preset_static
|
||||
presets.presets[name_trans1] = preset_trans1
|
||||
presets.presets[name_trans2] = preset_trans2
|
||||
presets.presets[name_trans3] = preset_trans3
|
||||
presets.presets[name_trans4] = preset_trans4
|
||||
presets.presets[name_trans5] = preset_trans5
|
||||
presets.presets[name_trans6] = preset_trans6
|
||||
|
||||
print("Showing static segments...")
|
||||
presets.select(name_static)
|
||||
presets.tick() # draw once
|
||||
run_for(presets, 3000)
|
||||
|
||||
print("Running segments transition 1 (fading to new half/half layout)...")
|
||||
presets.select(name_trans1)
|
||||
run_for(presets, 3500)
|
||||
|
||||
print("Running segments transition 2 (fading to quarter-band layout)...")
|
||||
presets.select(name_trans2)
|
||||
run_for(presets, 4500)
|
||||
|
||||
print("Running segments transition 3 (fading to center green band)...")
|
||||
presets.select(name_trans3)
|
||||
run_for(presets, 5500)
|
||||
|
||||
print("Running segments transition 4 (fading to full warm white ring)...")
|
||||
presets.select(name_trans4)
|
||||
run_for(presets, 6500)
|
||||
|
||||
print("Running segments transition 5 (fading to warm/cool halves)...")
|
||||
presets.select(name_trans5)
|
||||
run_for(presets, 5500)
|
||||
|
||||
print("Running segments transition 6 (fading to narrow red band)...")
|
||||
presets.select(name_trans6)
|
||||
run_for(presets, 4500)
|
||||
|
||||
print("Multi-pattern test finished. Turning off LEDs.")
|
||||
presets.select("off")
|
||||
presets.tick()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user