diff --git a/src/patterns.py b/src/patterns.py index c42b56d..bee21e5 100644 --- a/src/patterns.py +++ b/src/patterns.py @@ -18,12 +18,10 @@ class Patterns: "rainbow_cycle": self.rainbow_cycle_step, "theater_chase": self.theater_chase_step, "blink": self.blink_step, - "random_color_wipe": self.random_color_wipe_step, - "random_rainbow_cycle": self.random_rainbow_cycle_step, - "random_theater_chase": self.random_theater_chase_step, - "random_blink": self.random_blink_step, "color_transition": self.color_transition_step, # Added new pattern "flicker": self.flicker_step, + "scanner": self.scanner_step, # New: Single direction scanner + "bidirectional_scanner": self.bidirectional_scanner_step, # New: Bidirectional scanner "external": None } self.selected = selected @@ -40,6 +38,9 @@ class Patterns: self.hold_start_time = utime.ticks_ms() # Time when the current color hold started + # New attributes for scanner patterns + self.scanner_direction = 1 # 1 for forward, -1 for backward + self.scanner_tail_length = 3 # Number of trailing pixels def sync(self): self.pattern_step=0 @@ -49,6 +50,8 @@ class Patterns: self.current_color_idx = 0 self.current_color = self.colors[self.current_color_idx] self.hold_start_time = utime.ticks_ms() # Reset hold time + # Reset scanner specific variables + self.scanner_direction = 1 self.tick() def set_pattern_step(self, step): @@ -258,65 +261,6 @@ class Patterns: self.pattern_step = (self.pattern_step + 1) % 2 self.last_update = current_time - def random_color_wipe_step(self): - current_time = utime.ticks_ms() - if utime.ticks_diff(current_time, self.last_update) >= self.delay: - color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) - if self.pattern_step < self.num_leds: - for i in range(self.num_leds): - self.n[i] = (0, 0, 0) - self.n[self.pattern_step] = self.apply_brightness(color) - self.n.write() - self.pattern_step += 1 - else: - self.pattern_step = 0 - self.last_update = current_time - - def random_rainbow_cycle_step(self): - current_time = utime.ticks_ms() - if utime.ticks_diff(current_time, self.last_update) >= self.delay: # Kept original delay for now - 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) - - random_offset = random.randint(0, 255) - for i in range(self.num_leds): - rc_index = (i * 256 // self.num_leds) + self.pattern_step + random_offset - self.n[i] = self.apply_brightness(wheel(rc_index & 255)) - self.n.write() - self.pattern_step = (self.pattern_step + 1) % 256 - self.last_update = current_time - - def random_theater_chase_step(self): - current_time = utime.ticks_ms() - if utime.ticks_diff(current_time, self.last_update) >= self.delay: - color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) - for i in range(self.num_leds): - if (i + self.pattern_step) % 3 == 0: - self.n[i] = self.apply_brightness(color) - else: - self.n[i] = (0, 0, 0) - self.n.write() - self.pattern_step = (self.pattern_step + 1) % 3 - self.last_update = current_time - - def random_blink_step(self): - current_time = utime.ticks_ms() - if utime.ticks_diff(current_time, self.last_update) >= self.delay*10: - color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) - if self.pattern_step % 2 == 0: - self.fill(self.apply_brightness(color)) - else: - self.fill((0, 0, 0)) - self.pattern_step = (self.pattern_step + 1) % 2 - self.last_update = current_time - def color_transition_step(self): current_time = utime.ticks_ms() @@ -377,3 +321,76 @@ class Patterns: flicker_color = self.apply_brightness(base_color, brightness_override=flicker_brightness) self.fill(flicker_color) self.last_update = current_time + + def scanner_step(self): + """ + Mimics a 'Knight Rider' style scanner, moving in one direction. + """ + current_time = utime.ticks_ms() + if utime.ticks_diff(current_time, self.last_update) >= self.delay: + self.fill((0, 0, 0)) # Clear all LEDs + + # Calculate the head and tail position + head_pos = self.pattern_step + color = self.apply_brightness(self.colors[0]) + + # Draw the head + if 0 <= head_pos < self.num_leds: + self.n[head_pos] = color + + # Draw the trailing pixels with decreasing brightness + for i in range(1, self.scanner_tail_length + 1): + tail_pos = head_pos - i + if 0 <= tail_pos < self.num_leds: + # Calculate fading color for tail + # Example: linear fade from full brightness to off + fade_factor = 1.0 - (i / (self.scanner_tail_length + 1)) + faded_color = tuple(int(c * fade_factor) for c in color) + self.n[tail_pos] = faded_color + + self.n.write() + + self.pattern_step += 1 + if self.pattern_step >= self.num_leds + self.scanner_tail_length: + self.pattern_step = 0 # Reset to start + + self.last_update = current_time + + def bidirectional_scanner_step(self): + """ + Mimics a 'Knight Rider' style scanner, moving back and forth. + """ + current_time = utime.ticks_ms() + if utime.ticks_diff(current_time, self.last_update) >= self.delay/100: + self.fill((0, 0, 0)) # Clear all LEDs + + color = self.apply_brightness(self.colors[0]) + + # Calculate the head position based on direction + head_pos = self.pattern_step + + # Draw the head + if 0 <= head_pos < self.num_leds: + self.n[head_pos] = color + + # Draw the trailing pixels with decreasing brightness + for i in range(1, self.scanner_tail_length + 1): + tail_pos = head_pos - (i * self.scanner_direction) + if 0 <= tail_pos < self.num_leds: + fade_factor = 1.0 - (i / (self.scanner_tail_length + 1)) + faded_color = tuple(int(c * fade_factor) for c in color) + self.n[tail_pos] = faded_color + + self.n.write() + + self.pattern_step += self.scanner_direction + + # Change direction if boundaries are reached + if self.scanner_direction == 1 and self.pattern_step >= self.num_leds: + self.scanner_direction = -1 + self.pattern_step = self.num_leds - 1 # Start moving back from the last LED + elif self.scanner_direction == -1 and self.pattern_step < 0: + self.scanner_direction = 1 + self.pattern_step = 0 # Start moving forward from the first LED + + self.last_update = current_time