diff --git a/src/patterns.py b/src/patterns.py index 7e093dd..b499de9 100644 --- a/src/patterns.py +++ b/src/patterns.py @@ -26,11 +26,13 @@ class Patterns: "external": None } self.selected = selected - self.color1 = color1 - self.color2 = color2 + self.colors = [color1, color2] self.transition_duration = delay * 10 # Default transition duration is 10 times the delay self.transition_step = 0 - self.current_color = self.color1 + self.current_color = self.colors[0] + + # New: Track the current index for color transitions + self.current_color_idx = 0 def sync(self): self.pattern_step=0 @@ -57,18 +59,62 @@ class Patterns: self.brightness = brightness def set_color1(self, color): - self.color1 = color + self.colors[0] = color if self.selected == "color_transition": + # Restart transition if color 0 (start color) is changed self.transition_step = 0 - self.current_color = self.color1 + self.current_color_idx = 0 # Ensure we start from the new color[0] + self.current_color = self.colors[0] def set_color2(self, color): - self.color2 = color + self.colors[1] = color if self.selected == "color_transition": - self.transition_step = 0 - self.current_color = self.color1 + # No direct effect on current_color here, but transition will eventually use it + pass + def set_colors(self, colors): + self.colors = colors + + def set_color(self, num, color): + # Changed: More robust index check + if 0 <= num < len(self.colors): + self.colors[num] = color + # If the changed color is part of the current or next transition, + # restart the transition for smoother updates + if self.selected == "color_transition": + current_from_idx = self.current_color_idx + current_to_idx = (self.current_color_idx + 1) % len(self.colors) + if num == current_from_idx or num == current_to_idx: + self.transition_step = 0 + # Optionally reset current_color_idx if num is the start color + if num == current_from_idx: + self.current_color_idx = num + self.current_color = self.colors[num] + return True + elif num == len(self.colors): # Allow setting a new color at the end + self.colors.append(color) + return True + return False + + def add_color(self, color): + self.colors.append(color) + + def del_color(self, num): + # Changed: More robust index check and using del for lists + if 0 <= num < len(self.colors): + del self.colors[num] + # If the color being deleted was part of the current transition, + # re-evaluate the current_color_idx + if self.selected == "color_transition": + if len(self.colors) < 2: # Need at least two colors for transition + self.select("off") # Or some other default + else: + self.current_color_idx %= len(self.colors) # Adjust index if it's out of bounds + self.transition_step = 0 + self.current_color = self.colors[self.current_color_idx] + return True + return False def apply_brightness(self, color): return tuple(int(c * self.brightness / 255) for c in color) @@ -78,9 +124,15 @@ class Patterns: self.selected = pattern self.sync() # Reset pattern state when selecting a new pattern if pattern == "color_transition": - self.transition_step = 0 - self.current_color = self.color1 - self.transition_duration = self.delay * 10 # Initialize transition duration + if len(self.colors) < 2: + print("Warning: 'color_transition' requires at least two colors. Switching to 'on'.") + self.selected = "on" # Fallback if not enough colors + self.sync() # Re-sync for the new pattern + else: + self.transition_step = 0 + self.current_color_idx = 0 # Start from the first color in the list + self.current_color = self.colors[self.current_color_idx] + self.transition_duration = self.delay * 10 # Initialize transition duration return True return False @@ -91,7 +143,7 @@ class Patterns: self.n.write() def fill(self, color=None): - fill_color = color if color is not None else self.color1 + fill_color = color if color is not None else self.colors[0] for i in range(self.num_leds): self.n[i] = fill_color self.n.write() @@ -100,11 +152,11 @@ class Patterns: self.fill((0, 0, 0)) def on(self): - self.fill(self.apply_brightness(self.color1)) + self.fill(self.apply_brightness(self.colors[0])) def color_wipe_step(self): - color = self.apply_brightness(self.color1) + color = self.apply_brightness(self.colors[0]) current_time = utime.ticks_ms() if utime.ticks_diff(current_time, self.last_update) >= self.delay: if self.pattern_step < self.num_leds: @@ -142,7 +194,7 @@ class Patterns: if utime.ticks_diff(current_time, self.last_update) >= self.delay: for i in range(self.num_leds): if (i + self.pattern_step) % 3 == 0: - self.n[i] = self.apply_brightness(self.color1) + self.n[i] = self.apply_brightness(self.colors[0]) else: self.n[i] = (0, 0, 0) self.n.write() @@ -153,7 +205,7 @@ class Patterns: current_time = utime.ticks_ms() if utime.ticks_diff(current_time, self.last_update) >= self.delay: if self.pattern_step % 2 == 0: - self.fill(self.apply_brightness(self.color1)) + self.fill(self.apply_brightness(self.colors[0])) else: self.fill((0, 0, 0)) self.pattern_step = (self.pattern_step + 1) % 2 @@ -224,21 +276,30 @@ class Patterns: def color_transition_step(self): current_time = utime.ticks_ms() - # Use delay for how often to update the transition, not for the duration + + if len(self.colors) < 2: + # Not enough colors to transition, possibly switch to 'on' or 'off' + self.fill(self.apply_brightness(self.colors[0])) + return # Exit if there aren't enough colors + if utime.ticks_diff(current_time, self.last_update) >= 1: # Update frequently for smooth transition self.transition_step += utime.ticks_diff(current_time, self.last_update) self.last_update = current_time + color_from = self.colors[self.current_color_idx] + color_to_idx = (self.current_color_idx + 1) % len(self.colors) + color_to = self.colors[color_to_idx] + if self.transition_step >= self.transition_duration: - # Transition complete, swap colors and restart - self.color1, self.color2 = self.color2, self.color1 - self.transition_step = 0 + # Transition complete to the next color + self.current_color_idx = color_to_idx # Move to the next color in the sequence + self.transition_step = 0 # Reset transition step # Calculate the interpolation factor (0 to 1) factor = self.transition_step / self.transition_duration # Get the interpolated color and apply brightness - interpolated_color = self.interpolate_color(self.color1, self.color2, factor) + interpolated_color = self.interpolate_color(color_from, color_to, factor) self.current_color = self.apply_brightness(interpolated_color) # Fill the LEDs with the current interpolated color @@ -248,7 +309,9 @@ class Patterns: if __name__ == "__main__": p = Patterns(4, 180) p.set_color1((255,0,0)) - p.set_color2((0,255,0)) + p.set_color2((0,0,255)) # Blue + p.add_color((0,255,0)) # Green + p.add_color((255,255,0)) # Yellow #p.set_delay(10) try: while True: diff --git a/src/settings.py b/src/settings.py index f67faa4..4e7cdac 100644 --- a/src/settings.py +++ b/src/settings.py @@ -54,7 +54,12 @@ class Settings(dict): print(data) for key, value in data.items(): print(key, value) - if key == "color1": + if key == "colors": + buff = [] + for color in value: + buff.append(tuple(int(color[i:i+2], 16) for i in self.color_order)) + patterns.set_colors(buff) + elif key == "color1": patterns.set_color1(tuple(int(value[i:i+2], 16) for i in self.color_order)) # Convert hex to RGB elif key == "color2": patterns.set_color2(tuple(int(value[i:i+2], 16) for i in self.color_order)) # Convert hex to RGB @@ -84,6 +89,7 @@ class Settings(dict): else: return "Invalid key", 400 self[key] = value + #print(self) patterns.sync() if save: self.save()