Skip to content

Instantly share code, notes, and snippets.

@postspectacular
Last active January 4, 2025 00:13
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;
}
@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.

@454077
Copy link

454077 commented Jan 2, 2025

I am trying to implement this on TinkerCAD, but it's not working:
`#include <Adafruit_NeoPixel.h>

#define PIN 2 // input pin Neopixel is attached to

#define NUMPIXELS 3 // number of neopixels in strip

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

int redColor = 255;
int greenColor = 0;
int blueColor = 0;
int timeDel = 50;

void setup() {
// Initialize the NeoPixel library.
pixels.begin();
}

void loop() { //repeat while power is supplied to Uno board
for (float i=0.0; i < 100; i++){
int rAgAbA = [0,0,0];
redColor = (int)(hsv2rgb(i/100,1.0,1.0,rAgAbA)[0]);
greenColor = (int)(hsv2rgb(i/100,1.0,1.0,rAgAbA)[1]):
blueColor = (int)(hsv2rgb(i/100,1.0,1.0,rAgAbA)[2]);
setColor();
}
}

// setColor()
void setColor(){
for (int i=0; i < NUMPIXELS; i++) {
// pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
pixels.setPixelColor(i, pixels.Color(redColor, greenColor, blueColor));
}
// This sends the updated pixel color to the hardware.
pixels.show();
}

// 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;
}
`

@454077
Copy link

454077 commented Jan 2, 2025

I want the result to be something like:
where the sliders are external potentiometers (to be added later), each vertical strip of color is a NeoPixel, and each color is the color of light emitted by its corresponding NeoPixel.

@454077
Copy link

454077 commented Jan 2, 2025

@454077
Copy link

454077 commented Jan 4, 2025

NVM, i got it! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment