From 406f483ef02046cd25db9665693bd693c2d3cde0 Mon Sep 17 00:00:00 2001
From: jimmy <me@jimmy.nz>
Date: Wed, 31 Jan 2024 07:41:04 +0000
Subject: [PATCH] Add led patterns

---
 patterns.py | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 129 insertions(+)
 create mode 100644 patterns.py

diff --git a/patterns.py b/patterns.py
new file mode 100644
index 0000000..4093f7a
--- /dev/null
+++ b/patterns.py
@@ -0,0 +1,129 @@
+from ws2812 import WS2812B
+import uasyncio as asyncio
+import time, math
+
+class LedPatterns(WS2812B):
+    async def color_chase(self, color, wait):
+        for i in range(self.num_leds):
+            self.set(i, color)
+            await asyncio.sleep(wait)
+            self.show()
+        time.sleep(0.2)
+     
+    def wheel(self, pos):
+        # Input a value 0 to 255 to get a color value.
+        # The colours are a transition r - g - b - back to r.
+        if pos < 0 or pos > 255:
+            return (0, 0, 0)
+        if pos < 85:
+            return (255 - pos * 3, pos * 3, 0)
+        if pos < 170:
+            pos -= 85
+            return (0, 255 - pos * 3, pos * 3)
+        pos -= 170
+        return (pos * 3, 0, 255 - pos * 3)
+     
+     
+    async def rainbow_cycle(self, wait):
+        for j in range(255):
+            for i in range(self.num_leds):
+                rc_index = (i * 256 // self.num_leds) + j
+                self.set(i, self.wheel(rc_index & 255))
+            self.show()
+            await asyncio.sleep(wait)
+    
+    async def breathing(self, color, duration):
+        steps = 256  # Number of steps for the breathing effect
+        for _ in range(steps):
+            brightness = int(255 * abs(steps / 2 - _) / (steps / 2))  # Calculate brightness
+            self.fill((brightness * color[0] // 255, brightness * color[1] // 255, brightness * color[2] // 255))
+            self.show()
+            await asyncio.sleep(duration / steps)
+    
+    async def color_transition(self, start_color, end_color, duration):
+        steps = 256 # Number of steps for the color transition
+        for step in range(steps):
+            # Interpolate between start_color and end_color
+            color = (
+                int(start_color[0] + (end_color[0] - start_color[0]) * step / steps),
+                int(start_color[1] + (end_color[1] - start_color[1]) * step / steps),
+                int(start_color[2] + (end_color[2] - start_color[2]) * step / steps),
+            )
+            self.fill(color)
+            self.show()
+            await asyncio.sleep(duration / steps)
+            
+    async def scanner(self, color, speed):
+        position = 0
+        direction = 1  # 1 for moving right, -1 for moving left
+
+        while True:
+            self.fill((0, 0, 0))  # Clear the LEDs
+            self.set(position, color)  # Set the current position to the specified color
+            while self.busy():
+                pass
+            self.show()
+            await asyncio.sleep(speed)
+            position += direction
+            if position == self.num_leds - 1 or position == 0:
+                direction *= -1  # Reverse direction when reaching the end
+    
+    async def bidirectional_scanner(self, color_left, color_right=None, speed=0.1):
+        # If right color is not specified, use the left color
+        color_right = color_right or color_left
+
+        position_left = 0
+        position_right = self.num_leds - 1
+        direction_left = 1  # 1 for moving right, -1 for moving left
+        direction_right = -1  # 1 for moving right, -1 for moving left
+
+        while True:
+            self.fill((0, 0, 0))  # Clear the LEDs
+            self.set(position_left, color_left)  # Set the left position to the specified color
+            self.set(position_right, color_right)  # Set the right position to the specified color
+            self.show()
+            
+            await asyncio.sleep(speed)
+
+            position_left += direction_left
+            position_right += direction_right
+
+            # Reverse direction when reaching the end
+            if position_left == self.num_leds - 1 or position_left == 0:
+                direction_left *= -1
+            if position_right == self.num_leds - 1 or position_right == 0:
+                direction_right *= -1
+    
+    async def sine_wave_propagation(self, color, speed):
+        frequency = 10  # Adjust the frequency of the sine wave
+        phase = 0  # Initial phase of the sine wave
+
+        while True:
+            self.fill((0, 0, 0))  # Clear the LEDs
+            
+            for i in range(self.num_leds):
+                brightness = int(127.5 * (math.sin(frequency * i + phase) + 1))
+                self.set(i, (brightness * color[0] // 255, brightness * color[1] // 255, brightness * color[2] // 255))
+            while self.busy():
+                pass
+            self.show()
+            await asyncio.sleep(speed)
+            
+            # Update phase for the sine wave propagation
+            phase += 0.1
+
+async def run():
+    ws = LedPatterns(150, 0, 0, 0.1)
+    while True:
+        #await ws.color_transition(ws.RED, ws.BLUE, 2)
+        #await ws.color_transition(ws.BLUE, ws.GREEN, 2)
+        #await ws.color_transition(ws.GREEN, ws.RED, 2)
+        #await ws.bidirectional_scanner(ws.GREEN)
+        await ws.sine_wave_propagation(ws.RED, 0.1)
+
+
+
+if __name__ == "__main__":
+    loop = asyncio.get_event_loop()
+    asyncio.create_task(run())
+    loop.run_forever()