Last active
June 18, 2024 22:02
-
-
Save postspectacular/2a4a8db092011c6743a7 to your computer and use it in GitHub Desktop.
Super compact HSV/RGB conversions for Arduino/C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
int redPin = 6; | |
int greenPin = 5; | |
int bluePin = 9; | |
float col[3]; | |
float hue = 0.0; | |
void setup() { | |
pinMode(redPin, OUTPUT); | |
pinMode(greenPin, OUTPUT); | |
pinMode(bluePin, OUTPUT); | |
} | |
void loop() { | |
setColor(hsv2rgb(hue, 1.0, 1.0, col)); | |
delay(50); | |
hue += 0.01; | |
if (hue >= 1.0) hue = 0.0; | |
} | |
void setColor(float *rgb) { | |
analogWrite(redPin, (int)((1.0 - rgb[0]) * 255)); | |
analogWrite(greenPin, (int)((1.0 - rgb[1]) * 255)); | |
analogWrite(bluePin, (int)((1.0 - rgb[2]) * 255)); | |
} | |
// HSV->RGB conversion based on GLSL version | |
// expects hsv channels defined in 0.0 .. 1.0 interval | |
float fract(float x) { return x - int(x); } | |
float mix(float a, float b, float t) { return a + (b - a) * t; } | |
float step(float e, float x) { return x < e ? 0.0 : 1.0; } | |
float* hsv2rgb(float h, float s, float b, float* rgb) { | |
rgb[0] = b * mix(1.0, constrain(abs(fract(h + 1.0) * 6.0 - 3.0) - 1.0, 0.0, 1.0), s); | |
rgb[1] = b * mix(1.0, constrain(abs(fract(h + 0.6666666) * 6.0 - 3.0) - 1.0, 0.0, 1.0), s); | |
rgb[2] = b * mix(1.0, constrain(abs(fract(h + 0.3333333) * 6.0 - 3.0) - 1.0, 0.0, 1.0), s); | |
return rgb; | |
} | |
float* rgb2hsv(float r, float g, float b, float* hsv) { | |
float s = step(b, g); | |
float px = mix(b, g, s); | |
float py = mix(g, b, s); | |
float pz = mix(-1.0, 0.0, s); | |
float pw = mix(0.6666666, -0.3333333, s); | |
s = step(px, r); | |
float qx = mix(px, r, s); | |
float qz = mix(pw, pz, s); | |
float qw = mix(r, px, s); | |
float d = qx - min(qw, py); | |
hsv[0] = abs(qz + (qw - py) / (6.0 * d + 1e-10)); | |
hsv[1] = d / (qx + 1e-10); | |
hsv[2] = qx; | |
return hsv; | |
} |
You are absolutely beautiful :)! Is there anywhere you give an in-depth explanation of how all of your code works? (the important stuff like where is the 0.666666 number coming from, not how passing a array by reference works). I would very much appreciate that! Thank you again
Problems with inverted / non-inverted math in SetColor() function are related to the RGB LED diode you are using. The inverted version is for the common anode (CA) diode, while the non-inverted is for the common cathode (CA) RGB diode.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There's no sensor at all, it's to control an RGB LED...