From 83cb34d6a8aaebca2297bc8ef09618cbb805a727 Mon Sep 17 00:00:00 2001 From: jimmy Date: Sun, 26 Oct 2025 00:15:53 +1300 Subject: [PATCH] Add sine brightness pattern --- src/patterns.py | 47 ++++++++++++++++ test/sine_brightness.py | 120 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 test/sine_brightness.py diff --git a/src/patterns.py b/src/patterns.py index 2e1a589..10a62c5 100644 --- a/src/patterns.py +++ b/src/patterns.py @@ -1,6 +1,7 @@ import utime import random +import math from patterns_base import PatternBase # Import PatternBase import _thread from machine import WDT @@ -24,6 +25,7 @@ class Patterns(PatternBase): # Inherit from PatternBase "on": self.on, "bl": self.blink, "cl": self.circle_loading, + "sb": self.sine_brightness, } self.step = 0 self.run = True @@ -138,6 +140,51 @@ class Patterns(PatternBase): # Inherit from PatternBase self.run = False self.running = False + def sine_brightness(self): + """Sine wave brightness pattern - n1=min brightness, brightness=max brightness, wavelength=delay""" + self.run = True + + # Calculate sine wave parameters + min_brightness = max(0, int(self.n1)) # n1 = minimum brightness + max_brightness = self.brightness # brightness = maximum brightness + amplitude = max_brightness - min_brightness # Range between min and max + wavelength = max(1, self.delay) # Wavelength = delay in ms + + # Convert wavelength to frequency (cycles per second) + frequency = 1000.0 / wavelength # Hz + + start_time = utime.ticks_ms() + + while self.run: + self.wdt.feed() + current_time = utime.ticks_ms() + + # Calculate time elapsed in seconds + elapsed_ms = utime.ticks_diff(current_time, start_time) + elapsed_seconds = elapsed_ms / 1000.0 + + # Calculate sine wave value (-1 to 1) + sine_value = math.sin(2 * math.pi * frequency * elapsed_seconds) + + # Convert to brightness (min_brightness to max_brightness) + current_brightness = int(min_brightness + (sine_value + 1) * amplitude / 2) + current_brightness = max(0, min(255, current_brightness)) + + # Apply brightness to all LEDs + color = self.apply_brightness(self.colors[0]) + # Override brightness with calculated value + adjusted_color = ( + int(color[0] * current_brightness / 255), + int(color[1] * current_brightness / 255), + int(color[2] * current_brightness / 255) + ) + + self.fill(adjusted_color) + self.n.write() + + self.run = False + self.running = False + # def flicker(self): # current_time = utime.ticks_ms() # base_color = self.colors[0] diff --git a/test/sine_brightness.py b/test/sine_brightness.py new file mode 100644 index 0000000..9820e6d --- /dev/null +++ b/test/sine_brightness.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +""" +Test script for sine brightness pattern +Run with: mpremote run test/sine_brightness.py +""" + +import patterns +import utime +from settings import Settings +from machine import WDT + +def run_test_case(p, test_name, duration_ms=5000): + """Run a test case for specified duration""" + print(f"\n--- {test_name} ---") + print(f"Parameters: n1={p.n1} min brightness, brightness={p.brightness} max brightness, delay={p.delay}ms wavelength") + print(f"Color: {p.colors[0]}") + print(f"Running for {duration_ms//1000} seconds...") + + # Initialize watchdog timer + wdt = WDT(timeout=10000) + wdt.feed() + + # Start pattern + p.select("sb") + + # Run for specified duration + start_time = utime.ticks_ms() + while utime.ticks_diff(utime.ticks_ms(), start_time) < duration_ms: + wdt.feed() + utime.sleep_ms(100) + + # Stop pattern + p.run = False + print(f"{test_name} completed") + + # Brief pause between tests + utime.sleep_ms(500) + +def test_sine_brightness(): + print("Testing sine brightness pattern with multiple configurations...") + + # Load settings + settings = Settings() + + # Initialize patterns using settings + p = patterns.Patterns( + pin=settings["led_pin"], + num_leds=settings["num_leds"], + brightness=51, # 20% brightness + delay=1000 # Base wavelength + ) + + print(f"LED Pin: {settings['led_pin']}") + print(f"LEDs: {settings['num_leds']}") + print(f"Base Brightness: {p.brightness}") + + # Test Case 1: Slow breathing + p.n1 = 10 # Min brightness 10 + p.brightness = 40 # Max brightness 40 + p.delay = 3000 # 3 second cycle + p.colors = [(255, 0, 0)] # Red + run_test_case(p, "Test 1: Slow breathing (10-40 brightness)", 12000) + + # Test Case 2: Fast pulsing + p.n1 = 5 # Min brightness 5 + p.brightness = 51 # Max brightness 51 + p.delay = 500 # 0.5 second cycle + p.colors = [(0, 255, 0)] # Green + run_test_case(p, "Test 2: Fast pulsing (5-51 brightness)", 8000) + + # Test Case 3: Medium breathing + p.n1 = 15 # Min brightness 15 + p.brightness = 45 # Max brightness 45 + p.delay = 1500 # 1.5 second cycle + p.colors = [(0, 0, 255)] # Blue + run_test_case(p, "Test 3: Medium breathing (15-45 brightness)", 10000) + + # Test Case 4: Very slow breathing + p.n1 = 20 # Min brightness 20 + p.brightness = 30 # Max brightness 30 + p.delay = 5000 # 5 second cycle + p.colors = [(255, 255, 0)] # Yellow + run_test_case(p, "Test 4: Very slow breathing (20-30 brightness)", 15000) + + # Test Case 5: Very fast pulsing + p.n1 = 0 # Min brightness 0 + p.brightness = 51 # Max brightness 51 + p.delay = 200 # 0.2 second cycle + p.colors = [(255, 0, 255)] # Magenta + run_test_case(p, "Test 5: Very fast pulsing (0-51 brightness)", 6000) + + # Test Case 6: Low range, slow cycle + p.n1 = 25 # Min brightness 25 + p.brightness = 35 # Max brightness 35 + p.delay = 4000 # 4 second cycle + p.colors = [(0, 255, 255)] # Cyan + run_test_case(p, "Test 6: Low range, slow cycle (25-35 brightness)", 12000) + + # Test Case 7: High range, medium cycle + p.n1 = 5 # Min brightness 5 + p.brightness = 51 # Max brightness 51 + p.delay = 1000 # 1 second cycle + p.colors = [(255, 128, 0)] # Orange + run_test_case(p, "Test 7: High range, medium cycle (5-51 brightness)", 8000) + + # Test Case 8: Ultra fast strobe + p.n1 = 0 # Min brightness 0 + p.brightness = 51 # Max brightness 51 + p.delay = 100 # 0.1 second cycle + p.colors = [(128, 0, 255)] # Purple + run_test_case(p, "Test 8: Ultra fast strobe (0-51 brightness)", 4000) + + print("\n=== All tests completed ===") + + # Turn off LEDs + p.off() + print("LEDs turned off") + +if __name__ == "__main__": + test_sine_brightness()