Here's a quick one; I'm making a Christmas display out of a bunch of serially controllable APA106
RGB LEDs, but how do I turn a value of
0 – 255 into a glorious RGW (Red Green White) struct with
the correct colour, and the correct wrapping rules?
First, some theory
The code in the next section is based on the RGB linear colour wheel approximation from the Adafruit NeoPixel library. So that I can make modifications to the generated colours, it helps to first visualise the RGB brightnesses against time. For a rainbow RGB pattern, that looks a bit like this:
We'll get onto the RGW stuff in a sec.
I'm writing this project in Rust, however my code is modified from the original RGB wheel C code from Adafruit.
Here's what the reference RGB function looks like in C:
Easy stuff. It's not perfect because it's linear instead of sinusoidal as we saw in the graph above, but it makes a good enough approximation for fading some LEDs over the rainbow. And it uses simple integer maths which is nice and fast.
This is what the same thing (still RGB) looks like in Rust:
Note that I'm using a struct to return the values because Rust is cool, and structs are cool.
Chrismus – RGW
Apparently the colours of Christmas are red, green and white. To this end, we need to make a slight modification to our wheel function to fade through white instead of blue:
There's one caveat to this algorithm: between white and red, there's this wishy washy pink colour that shows up. It's not that bad, but on my LED display it looks odd due to the other colours being reasonably well saturated.
The code to do this looks like the following:
// Red - green - white colour wheel
Proper wrapping was a bit hard to figure out because red is the only colour that wraps. Drawing diagrams really helps with this kind of stuff.