Open emdeex opened 4 years ago
This is probably the worst code you could learn from, since it's fairly contrived, ported from what I assume was code originally written for very limited microcontrollers, and thus completely disconnected from how any normal Python code might work.
The majority of noteworthy code lives in the wheel
function, which demonstrates a crude method of turning a number from 0-255 into an RGB colour value roughly approximating an imaginary position in a "rainbow".
def wheel(pos):
"""Generate rainbow colors across 0-255 positions."""
if pos < 85:
return Color(pos * 3, 255 - pos * 3, 0)
elif pos < 170:
pos -= 85
return Color(255 - pos * 3, 0, pos * 3)
else:
pos -= 170
return Color(0, pos * 3, 255 - pos * 3)
This is crude because colour theory already gives us the HSV (Hue, Saturation, Value) colourspace where H or "Hue" maps roughly to what you might consider a colour in a rainbow. I wrote something about this years ago which you might find useful- https://learn.pimoroni.com//tutorial/unicorn-hat/making-rainbows-with-unicorn-hat
Python has a colorsys
library that makes converting from RGB to HSV and back again pretty trivial. On a microcontroller the code above might be significantly more efficient, but on desktop Python there is no earthly reason why you'd use code as contrived as that above, in lieu of just doing colourspace conversions.
Broadly any "formula" for lighting a single LED should only ever accept the input values: "LED Index" and "Time" and only ever output one colour value. A rainbow would thus be produced either physically across the LED strip by driving the "Hue" (and thus the RGB value) from the "LED Index" or temporally over a period of time by deriving the "Hue" from "Time".
Things like the rainbow example in our Plasma library do this: https://github.com/pimoroni/plasma/blob/master/examples/rainbow.py
And a very extreme example from Unicorn HAT HD shows a range of functions which use just the X/Y coordinate from a square RGB display, and the "step" (which is just time, effectively) to create detailed demonscene style effects: https://github.com/pimoroni/unicorn-hat-hd/blob/master/examples/demo.py
This is extremely rough and untested and includes no strip setup, but the concise, Python way of doing rainbowCycle would look something like this:
import colorsys
import time
NUM_PIXELS = 10
def hue_to_rgb(h):
"""Convert a hue into an r, g, b color"""
return [int(c * 255) for c in colorsys.hsv_to_rgb(h, 1.0, 1.0)]
while True:
t = time.time() / 100 # Get the current timestep
# Iterate through each pixel
for i in range(NUM_PIXELS):
# Spread the Hue range over the pixels, but also cycle it over time
r, g, b = hue_to_rgb(t + i / NUM_PIXELS)
strip.setPixelColor(i, Color(r, g, b))
strip.show()
time.sleep(1.0 / 60) # Aim for ~60FPS
I'm loving playing with rainbowCycle, and its working fine.... but can anybody explain (for dummies) exactly what's going on with the formulas in the code?
I see it iterates through each neopixel, and uses the wheel function to set the color... but can you breakdown the formula like at
strip.setPixelColor(i, wheel((int(i * 256 / strip.numPixels()) + j) & 255))
? And how do thewait_ms
anditerations
variables interact with it?