Skip to content

Instantly share code, notes, and snippets.

@postspectacular
Last active June 18, 2024 22:02
Show Gist options
  • Save postspectacular/2a4a8db092011c6743a7 to your computer and use it in GitHub Desktop.
Save postspectacular/2a4a8db092011c6743a7 to your computer and use it in GitHub Desktop.
Super compact HSV/RGB conversions for Arduino/C
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;
}
@postspectacular
Copy link
Author

There's no sensor at all, it's to control an RGB LED...

@AJ-Smoothie
Copy link

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

@baloghr
Copy link

baloghr commented May 8, 2023

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