~quf/xmastree2020

d83fa334e4a5fc5a9e5e9334391338d0e06c4ed9 — Lukas Himbert 3 years ago a3354d2
spinning rainbow
1 files changed, 133 insertions(+), 0 deletions(-)

A spinning-rainbow.py
A spinning-rainbow.py => spinning-rainbow.py +133 -0
@@ 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()