Refactor n_chase pattern for bidirectional movement
- Updated n_chase to support bidirectional movement with n3 and n4 parameters - n3 controls forward steps per direction change - n4 controls backward steps per direction change - Pattern alternates between moving forward n3 steps and backward n4 steps - Each direction repeats for the specified number of steps before switching - Added test/9.py with n1=20, n2=20, n3=20, n4=-5 parameters - Updated to run as a thread-based pattern similar to other patterns
This commit is contained in:
131
src/patterns.py
131
src/patterns.py
@@ -295,48 +295,7 @@ class Patterns(PatternBase): # Inherit from PatternBase
|
|||||||
self.run = False
|
self.run = False
|
||||||
self.running = False
|
self.running = False
|
||||||
|
|
||||||
def n_chase(self):
|
|
||||||
"""Chase pattern - n1 LEDs on, n2 LEDs off, moving forward"""
|
|
||||||
self.run = True
|
|
||||||
|
|
||||||
# n1 = on width, n2 = off width
|
|
||||||
on_width = max(1, int(self.n1))
|
|
||||||
off_width = max(0, int(self.n2))
|
|
||||||
segment_length = on_width + off_width
|
|
||||||
|
|
||||||
if segment_length == 0:
|
|
||||||
segment_length = 1
|
|
||||||
|
|
||||||
# Calculate timing from delay
|
|
||||||
step_delay = max(10, int(self.delay)) # At least 10ms
|
|
||||||
|
|
||||||
step = 0
|
|
||||||
last_update = utime.ticks_ms()
|
|
||||||
color = self.apply_brightness(self.colors[0])
|
|
||||||
|
|
||||||
while self.run:
|
|
||||||
self.wdt.feed()
|
|
||||||
current_time = utime.ticks_ms()
|
|
||||||
|
|
||||||
# Move forward every step_delay ms
|
|
||||||
if utime.ticks_diff(current_time, last_update) >= step_delay:
|
|
||||||
# Clear all LEDs
|
|
||||||
self.n.fill((0, 0, 0))
|
|
||||||
|
|
||||||
# Draw the chase pattern - repeating segments across all LEDs
|
|
||||||
for i in range(self.num_leds):
|
|
||||||
pos_in_segment = (i + step) % segment_length
|
|
||||||
if pos_in_segment < on_width:
|
|
||||||
self.n[i] = color
|
|
||||||
|
|
||||||
self.n.write()
|
|
||||||
step = (step + 1) % segment_length
|
|
||||||
last_update = current_time
|
|
||||||
|
|
||||||
utime.sleep_ms(1)
|
|
||||||
|
|
||||||
self.run = False
|
|
||||||
self.running = False
|
|
||||||
|
|
||||||
# def flicker(self):
|
# def flicker(self):
|
||||||
# current_time = utime.ticks_ms()
|
# current_time = utime.ticks_ms()
|
||||||
@@ -372,34 +331,74 @@ class Patterns(PatternBase): # Inherit from PatternBase
|
|||||||
# self.last_update = current_time
|
# self.last_update = current_time
|
||||||
# return self.delay
|
# return self.delay
|
||||||
|
|
||||||
# def n_chase(self):
|
def n_chase(self):
|
||||||
# """
|
"""Chase pattern - n1 LEDs on, n2 LEDs off, bidirectional movement"""
|
||||||
# A theater chase pattern using n1 for on-width and n2 for off-width.
|
self.run = True
|
||||||
# """
|
|
||||||
# current_time = utime.ticks_ms()
|
|
||||||
# step_rate = max(1, int(self.n3))
|
|
||||||
# segment_length = self.n1 + self.n2
|
|
||||||
# if segment_length == 0: # Avoid division by zero
|
|
||||||
# self.fill((0,0,0))
|
|
||||||
# self.n.write()
|
|
||||||
# self.last_update = current_time
|
|
||||||
# return self.delay
|
|
||||||
|
|
||||||
# # Use controller's step for synchronization, but scale it for chasing
|
# n1 = on width, n2 = off width
|
||||||
# chase_step = (self.step * step_rate) % self.num_leds
|
on_width = max(1, int(self.n1))
|
||||||
|
off_width = max(0, int(self.n2))
|
||||||
|
segment_length = on_width + off_width
|
||||||
|
|
||||||
# for i in range(self.num_leds):
|
if segment_length == 0:
|
||||||
# # Calculate position relative to the chase head
|
segment_length = 1
|
||||||
# pos_from_head = (i - chase_step) % self.num_leds
|
|
||||||
# if pos_from_head < self.n1:
|
# n3 = forward steps per move, n4 = backward steps per move
|
||||||
# self.n[i] = self.apply_brightness(self.colors[0])
|
forward_steps = max(1, abs(int(self.n3)))
|
||||||
# else:
|
backward_steps = max(1, abs(int(self.n4)))
|
||||||
# self.n[i] = (0, 0, 0)
|
|
||||||
# self.n.write()
|
# Calculate timing from delay
|
||||||
|
step_delay = max(10, int(self.delay)) # At least 10ms
|
||||||
|
|
||||||
|
position = 0 # Current position of the chase head
|
||||||
|
phase = "forward" # "forward" or "backward"
|
||||||
|
steps_remaining = forward_steps
|
||||||
|
total_steps = 0 # Track total steps for wrapping
|
||||||
|
|
||||||
|
last_update = utime.ticks_ms()
|
||||||
|
color = self.apply_brightness(self.colors[0])
|
||||||
|
|
||||||
|
while self.run:
|
||||||
|
self.wdt.feed()
|
||||||
|
current_time = utime.ticks_ms()
|
||||||
|
|
||||||
|
# Check if it's time to move
|
||||||
|
if utime.ticks_diff(current_time, last_update) >= step_delay:
|
||||||
|
# Move position based on current phase
|
||||||
|
if phase == "forward":
|
||||||
|
total_steps = (total_steps + 1) % (self.num_leds * segment_length)
|
||||||
|
position = total_steps % segment_length
|
||||||
|
steps_remaining -= 1
|
||||||
|
if steps_remaining == 0:
|
||||||
|
phase = "backward"
|
||||||
|
steps_remaining = backward_steps
|
||||||
|
else: # backward
|
||||||
|
total_steps = (total_steps - 1) % (self.num_leds * segment_length)
|
||||||
|
position = total_steps % segment_length
|
||||||
|
steps_remaining -= 1
|
||||||
|
if steps_remaining == 0:
|
||||||
|
phase = "forward"
|
||||||
|
steps_remaining = forward_steps
|
||||||
|
|
||||||
|
# Clear all LEDs
|
||||||
|
self.n.fill((0, 0, 0))
|
||||||
|
|
||||||
|
# Draw the chase pattern - repeating segments across all LEDs
|
||||||
|
# Position determines where to start drawing on the strip
|
||||||
|
for i in range(self.num_leds):
|
||||||
|
# Create repeating pattern of on_width on, off_width off
|
||||||
|
pos_in_segment = ((i + position) % segment_length)
|
||||||
|
if pos_in_segment < on_width:
|
||||||
|
self.n[i] = color
|
||||||
|
|
||||||
|
self.n.write()
|
||||||
|
last_update = current_time
|
||||||
|
|
||||||
|
utime.sleep_ms(1)
|
||||||
|
|
||||||
|
self.run = False
|
||||||
|
self.running = False
|
||||||
|
|
||||||
# # Don't update internal step - use controller's step for sync
|
|
||||||
# self.last_update = current_time
|
|
||||||
# return self.delay
|
|
||||||
|
|
||||||
# def alternating(self):
|
# def alternating(self):
|
||||||
# # Use n1 as ON width and n2 as OFF width
|
# # Use n1 as ON width and n2 as OFF width
|
||||||
|
|||||||
62
test/n_chase/9.py
Normal file
62
test/n_chase/9.py
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
N-chase test 9: Cyan, on=20, off=20, delay=200ms
|
||||||
|
Runs forever
|
||||||
|
Run with: mpremote run test/n_chase/9.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
import patterns
|
||||||
|
import utime
|
||||||
|
from settings import Settings
|
||||||
|
from machine import WDT
|
||||||
|
|
||||||
|
print("Starting N-Chase Test 9: Cyan, on=20, off=20, delay=200ms")
|
||||||
|
print("Press Ctrl+C to stop")
|
||||||
|
|
||||||
|
# Load settings
|
||||||
|
settings = Settings()
|
||||||
|
|
||||||
|
# Initialize patterns using settings
|
||||||
|
p = patterns.Patterns(
|
||||||
|
pin=settings["led_pin"],
|
||||||
|
num_leds=settings["num_leds"],
|
||||||
|
brightness=255,
|
||||||
|
delay=200
|
||||||
|
)
|
||||||
|
|
||||||
|
# Configure test parameters
|
||||||
|
p.n1 = 20 # On width 20
|
||||||
|
p.n2 = 20 # Off width 20
|
||||||
|
p.n3 = 20 # Reserved for future use
|
||||||
|
p.n4 = -5 # Reserved for future use
|
||||||
|
p.colors = [(0, 255, 255)] # Cyan
|
||||||
|
|
||||||
|
print(f"LED Pin: {settings['led_pin']}")
|
||||||
|
print(f"LEDs: {settings['num_leds']}")
|
||||||
|
print(f"Brightness: {p.brightness}")
|
||||||
|
print(f"Delay: {p.delay}ms")
|
||||||
|
print(f"On width: {p.n1}")
|
||||||
|
print(f"Off width: {p.n2}")
|
||||||
|
print(f"n3: {p.n3}")
|
||||||
|
print(f"n4: {p.n4}")
|
||||||
|
print(f"Color: {p.colors[0]}")
|
||||||
|
|
||||||
|
# Initialize watchdog timer
|
||||||
|
wdt = WDT(timeout=10000)
|
||||||
|
wdt.feed()
|
||||||
|
|
||||||
|
# Start pattern
|
||||||
|
p.select("nc")
|
||||||
|
print("Pattern started. Running forever...")
|
||||||
|
|
||||||
|
# Run forever
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
wdt.feed()
|
||||||
|
utime.sleep_ms(100)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\nStopping...")
|
||||||
|
p.run = False
|
||||||
|
p.off()
|
||||||
|
print("LEDs turned off")
|
||||||
|
|
||||||
Reference in New Issue
Block a user