# Improved color wheel function

This was posted four years ago when I was 30 years old. Hopefully I have matured since then!

Posted at age 30.

For years I have generated rainbows using the `Wheel()` function in Adafruit’s NeoPixels library. While convenient, the linear transition between the primary colors resulted in significantly dimmer colors in between the primaries. Playing around today, I improved the result by using a quadratic equation to accelerate each color component’s journey from 0 to 255.

This video demonstrates rainbow patterns generated first with the linear wheel function and then with the quadratic one, twice each. The video does makes it appear the new function also suffers from some brightness variation but to a lesser extent; I cannot see that at all looking right at the lights versus watching the video.

The original function was like this:

```// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if(WheelPos < 85) {
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
```

The quadratic function is like this:

```// Input values 0 to 255 to get color values that transition R->G->B. 0 and 255
// are the same color. This is based on Adafruit's Wheel() function, which used
// a linear map that resulted in brightness peaks at 0, 85 and 170. This version
// uses a quadratic map to make values approach 255 faster while leaving full
// red or green or blue untouched. For example, Wheel(42) is halfway between
// red and green. The linear function yielded (126, 129, 0), but this one yields
// (219, 221, 0). This function is based on the equation the circle centered at
// (255,0) with radius 255:  (x-255)^2 + (y-0)^2 = r^2
unsigned long Wheel(byte position) {
byte R = 0, G = 0, B = 0;
if (position < 85) {
R = sqrt32((1530 - 9 * position) * position);
G = sqrt32(65025 - 9 * position * position);
} else if (position < 170) {
position -= 85;
R = sqrt32(65025 - 9 * position * position);
B = sqrt32((1530 - 9 * position) * position);
} else {
position -= 170;
G = sqrt32((1530 - 9 * position) * position);
B = sqrt32(65025 - 9 * position * position);
}
return strip.Color(R, G, B);
}
```

It uses the following helper function, which I slightly adjusted after finding it in Fast Square root function for integers. on the Arduino for STM32 forum:

```// Adapted from https://www.stm32duino.com/viewtopic.php?t=56#p8160
unsigned int sqrt32(unsigned long n) {
unsigned int c = 0x8000;
unsigned int g = 0x8000;
while(true) {
if(g*g > n) {
g ^= c;
}
c >>= 1;
if(c == 0) {
return g;
}
g |= c;
}
}
```

Initially I wrote a simpler function I would call from within the old `Wheel()` function instead of it calling `Adafruit_NeoPixel::Color()` directly. This still uses the same circle equation:

```// Use a quadratic map to make values approach 255 faster while
// leaving full red or green or blue untouched.
unsigned long color(byte r, byte g, byte b) {
I suspected I could optimize a bit by solving the equations as much as possible, hence I ended up with the rewritten `Wheel()` function above.