From d83fa334e4a5fc5a9e5e9334391338d0e06c4ed9 Mon Sep 17 00:00:00 2001 From: Lukas Himbert Date: Sun, 27 Dec 2020 19:20:16 +0100 Subject: [PATCH] spinning rainbow --- spinning-rainbow.py | 133 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 spinning-rainbow.py diff --git a/spinning-rainbow.py b/spinning-rainbow.py new file mode 100644 index 0000000..95e0dba --- /dev/null +++ b/spinning-rainbow.py @@ -0,0 +1,133 @@ +# Try to import board and neopixel to run on the real hardware +try: + import board + import neopixel +except ImportError: + # Error, try to import the simulation from DutChen18 instead (https://github.com/standupmaths/xmastree2020/pull/5) + from sim import board, neopixel + +def xmaslight(): + # This is the code from my + + #NOTE THE LEDS ARE GRB COLOUR (NOT RGB) + + # Here are the libraries I am currently using: + import time + import re + from math import sin, cos, atan2, pi + #import board + #import neopixel + + # You are welcome to add any of these: + import random + import numpy + # import scipy + # import sys + + # If you want to have user changable values, they need to be entered from the command line + # so import sys sys and use sys.argv[0] etc + # some_value = int(sys.argv[0]) + + # IMPORT THE COORDINATES (please don't break this bit) + + coordfilename = "Python/coords.txt" + + fin = open(coordfilename,'r') + coords_raw = fin.readlines() + + coords_bits = [i.split(",") for i in coords_raw] + + coords = [] + + for slab in coords_bits: + new_coord = [] + for i in slab: + new_coord.append(int(re.sub(r'[^-\d]','', i))) + coords.append(new_coord) + + #set up the pixels (AKA 'LEDs') + PIXEL_COUNT = len(coords) # this should be 500 + + pixels = neopixel.NeoPixel(board.D18, PIXEL_COUNT, auto_write=False) + + + # YOU CAN EDIT FROM HERE DOWN + + # unzip coordinates + xs, ys, zs = list(zip(*coords)) + xs = numpy.array(xs) + ys = numpy.array(ys) + zs = numpy.array(zs) + + # normalize heights (0 to 1) + zs = (zs - zs.min()) / (zs.max() - zs.min()) + + # Find center of the tree + x0 = numpy.average([x for (x, _, _) in coords]) + y0 = numpy.average([y for (_, y, _) in coords]) + + # normalized radii (0 to 1) + radii = numpy.sqrt((xs - x0)**2, (ys - y0)**2) + radii = radii / radii.max() + + # azimuths + azimuths = numpy.arctan2(ys, xs) + + # VARIOUS SETTINGS + + # rotation speed in radians per second + # may be negative to reverse direction + speed = pi/2 + + # brightness factor: + # 0 = black + # 1 = maximum brightness + brightness_factor = 0.4 + + # colours in GRB order + white = (255, 255, 255) + black = (0, 0, 0) + ray_colors = [ + (0, 255, 0), + (165, 255, 0), + (255, 255, 0), + (128, 0, 0), + (0, 0, 255), + (0, 75, 130), + (130, 238, 238), + ] + ray_colors = [ (round(brightness_factor * g), round(brightness_factor * r), round(brightness_factor * b)) for (g, r, b) in ray_colors ] + # extend the colors so that the rainbow only spans half the circumference tree + ray_colors = ray_colors + len(ray_colors) * [black] + + # ray width; 2*pi/len(ray_colors) is the maximum + ray_width = 2*pi/len(ray_colors) + + # INITIALISE SOME VALUES + t0 = time.time() + + while True: + # Reset all lights to black + for i in range(len(coords)): + pixels[i] = black + # Turn them on again if they are at the "right" position + delta = time.time() - t0 + for (i, (φ, z)) in enumerate(zip(azimuths, zs)): + if z > 0.95: + # the top stays dark constantly, so it doesn't look too messy + continue + else: + for (j, color) in enumerate(ray_colors): + ray_offset = j * 2*pi / len(ray_colors) + if abs(φ + ray_offset + delta * speed) % (2*pi) <= ray_width: + pixels[i] = color + + # use the show() option as rarely as possible as it takes ages + # do not use show() each time you change a LED but rather wait until you have changed them all + pixels.show() + + return 'DONE' + + +# yes, I just put this at the bottom so it auto runs +xmaslight() -- 2.45.2