From fa7d60333b9110938156f5bba9913e0b29fb2a3b Mon Sep 17 00:00:00 2001 From: Kattni Rembor Date: Thu, 20 Dec 2018 11:16:42 -0600 Subject: [PATCH] Adding ESPuP Holiday Light files --- .../lights.html | 170 ++++++++++++++++++ ESP8266_MicroPython_Holiday_Lights/lights.py | 106 +++++++++++ 2 files changed, 276 insertions(+) create mode 100755 ESP8266_MicroPython_Holiday_Lights/lights.html create mode 100755 ESP8266_MicroPython_Holiday_Lights/lights.py diff --git a/ESP8266_MicroPython_Holiday_Lights/lights.html b/ESP8266_MicroPython_Holiday_Lights/lights.html new file mode 100755 index 000000000..cfa0226ae --- /dev/null +++ b/ESP8266_MicroPython_Holiday_Lights/lights.html @@ -0,0 +1,170 @@ + + + + + ESP8266 MicroPython Smart Holiday Lights + + + + +
+
+
+
+

MicroPython Smart Holiday Lights

+

Control your holiday lights using MicroPython and the + ESP8266 WiFi microcontroller.

+
+
+
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ +
+
+
+
+ + + + + + diff --git a/ESP8266_MicroPython_Holiday_Lights/lights.py b/ESP8266_MicroPython_Holiday_Lights/lights.py new file mode 100755 index 000000000..25b336d3f --- /dev/null +++ b/ESP8266_MicroPython_Holiday_Lights/lights.py @@ -0,0 +1,106 @@ +# ESP8266 MicroPython smart holiday lights project code. +# This will animate NeoPixels that can be controlled from the included +# lights.html web page. +# Author: Tony DiCola +# License: MIT License +import machine +import neopixel +import utime +import ujson + + +# Static configuration that never changes: +PIXEL_PIN = machine.Pin(15, machine.Pin.OUT) # Pin connected to the NeoPixels. +PIXEL_COUNT = 32 # Number of NeoPixels. +CONFIG_FILE = 'config.json' # Name of animation config file. + + +# Mirror the colors to make a ramp up and ramp down with no repeated colors. +def mirror(values): + # Add the input values in reverse order to the end of the array. + # However slice off the very first and very last items (the [1:-1] syntax) + # to prevent the first and last values from repeating. + # For example an input of: + # [1, 2, 3] + # Returns: + # [1, 2, 3, 2] + # Instead of returning: + # [1, 2, 3, 3, 2, 1] + # Which would duplicate 3 and 1 as you loop through the elements. + values.extend(list(reversed(values))[1:-1]) + return values + +# Linear interpolation helper: +def _lerp(x, x0, x1, y0, y1): + return y0 + (x - x0) * ((y1 - y0)/(x1 - x0)) + +# Animation functions: +def blank(config, np, pixel_count): + # Turn off all the pixels. + np.fill((0,0,0)) + np.write() + +def solid(config, np, pixel_count): + # Solid pulse of all pixels at the same color. + colors = config['colors'] + elapsed = utime.ticks_ms() // config['period_ms'] + current = elapsed % len(colors) + np.fill(colors[current]) + np.write() + +def chase(config, np, pixel_count): + # Chasing animation of pixels through different colors. + colors = config['colors'] + elapsed = utime.ticks_ms() // config['period_ms'] + for i in range(PIXEL_COUNT): + current = (elapsed+i) % len(colors) + np[i] = colors[current] + np.write() + +def smooth(config, np, pixel_count): + # Smooth pulse of all pixels at the same color. Interpolates inbetween colors + # for smoother animation. + colors = config['colors'] + period_ms = config['period_ms'] + ticks = utime.ticks_ms() + step = ticks // period_ms + offset = ticks % period_ms + color0 = colors[step % len(colors)] + color1 = colors[(step+1) % len(colors)] + color = (int(_lerp(offset, 0, period_ms, color0[0], color1[0])), + int(_lerp(offset, 0, period_ms, color0[1], color1[1])), + int(_lerp(offset, 0, period_ms, color0[2], color1[2]))) + np.fill(color) + np.write() + + +# Setup code: +# Initialize NeoPixels and turn them off. +np = neopixel.NeoPixel(PIXEL_PIN, PIXEL_COUNT) +np.fill((0,0,0)) +np.write() + +# Try loading the animation configuration, otherwise fall back to a blank default. +try: + with open(CONFIG_FILE, 'r') as infile: + config = ujson.loads(infile.read()) +except OSError: + # Couldn't load the config file, so fall back to a default blank animation. + config = { + 'colors': [[0,0,0]], + 'mirror_colors': False, + 'period_ms': 250, + 'animation': 'blank' + } + +# Mirror the color array if necessary. +if config['mirror_colors']: + config['colors'] = mirror(config['colors']) + +# Determine which animation function should be called. +animation = globals().get(config['animation'], blank) + +# Main loop code: +while True: + animation(config, np, PIXEL_COUNT) + utime.sleep(0.01)