Skip to content

Instantly share code, notes, and snippets.

@vshymanskyy
Created March 17, 2013 12:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vshymanskyy/5181274 to your computer and use it in GitHub Desktop.
Save vshymanskyy/5181274 to your computer and use it in GitHub Desktop.
Arduino sketch for cycling through HSV space with an RGB diode.
/*
RGB
*/
typedef class rgb
{
public:
float r; // percent
float g; // percent
float b; // percent
public:
rgb(void): r(0), g(0), b(0) {}
rgb(float _r, float _g, float _b): r(_r), g(_g), b(_b) {}
} rgb;
typedef class hsv
{
public:
float h; // angle in degrees
float s; // percent
float v; // percent
public:
hsv(void): h(0), s(0), v(0) {}
hsv(float _h, float _s, float _v): h(_h), s(_s), v(_v) {}
} hsv;
struct hsv rgb2hsv(struct rgb& in)
{
hsv out;
float min, max, delta;
min = in.r < in.g ? in.r : in.g;
min = min < in.b ? min : in.b;
max = in.r > in.g ? in.r : in.g;
max = max > in.b ? max : in.b;
out.v = max; // v
delta = max - min;
if( max > 0.0 ) {
out.s = (delta / max); // s
} else {
// r = g = b = 0 // s = 0, v is undefined
out.s = 0.0;
out.h = NAN; // its now undefined
return out;
}
if( in.r >= max ) // > is bogus, just keeps compilor happy
out.h = ( in.g - in.b ) / delta; // between yellow & magenta
else
if( in.g >= max )
out.h = 2.0 + ( in.b - in.r ) / delta; // between cyan & yellow
else
out.h = 4.0 + ( in.r - in.g ) / delta; // between magenta & cyan
out.h *= 60.0; // degrees
if( out.h < 0.0 )
out.h += 360.0;
return out;
}
struct rgb hsv2rgb(struct hsv& in)
{
float hh, p, q, t, ff;
long i;
rgb out;
if(in.s <= 0.0) { // < is bogus, just shuts up warnings
if(isnan(in.h)) { // in.h == NAN
out.r = in.v;
out.g = in.v;
out.b = in.v;
return out;
}
// error - should never happen
out.r = 0.0;
out.g = 0.0;
out.b = 0.0;
return out;
}
hh = in.h;
if(hh >= 360.0) hh = 0.0;
hh /= 60.0;
i = (long)hh;
ff = hh - i;
p = in.v * (1.0 - in.s);
q = in.v * (1.0 - (in.s * ff));
t = in.v * (1.0 - (in.s * (1.0 - ff)));
switch(i) {
case 0:
out.r = in.v;
out.g = t;
out.b = p;
break;
case 1:
out.r = q;
out.g = in.v;
out.b = p;
break;
case 2:
out.r = p;
out.g = in.v;
out.b = t;
break;
case 3:
out.r = p;
out.g = q;
out.b = in.v;
break;
case 4:
out.r = t;
out.g = p;
out.b = in.v;
break;
case 5:
default:
out.r = in.v;
out.g = p;
out.b = q;
break;
}
return out;
}
int pinR = 9;
int pinG = 10;
int pinB = 11;
void show(struct rgb& color)
{
analogWrite(pinR, 255 - (255.0 * color.r));
analogWrite(pinG, 255 - (255.0 * color.g));
analogWrite(pinB, 255 - (255.0 * color.b));
}
void showCycle()
{
for (int h = 0; h < 360; h++)
{
hsv color(h, 1.0, 1.0);
rgb col_rgb = hsv2rgb(color);
show(col_rgb);
delay(50);
}
}
void showCycle(int n)
{
for (int c = 0; c < n; c++)
{
showCycle();
}
}
#define BOUNCE_DURATION 20 // define an appropriate bounce time in ms for your switches
volatile unsigned long button1_timeout=0; // variable to hold ms count to debounce a pressed switch
volatile unsigned long button2_timeout=0; // variable to hold ms count to debounce a pressed switch
int button1_state = 0;
int button2_state = 0;
void button1_int()
{
button1_state = !button1_state;
// this is the interrupt handler for button presses
// it ignores presses that occur in intervals less then the bounce time
if(millis() > button1_timeout)
{
if (button1_state) {
rgb green(0, 1.0, 0);
show(green);
}
// Your code here to handle new button press
button1_timeout = millis() + BOUNCE_DURATION; // set whatever bounce time in ms is appropriate
}
}
void button2_int()
{
button2_state = !button2_state;
// this is the interrupt handler for button presses
// it ignores presses that occur in intervals less then the bounce time
if(millis() > button2_timeout)
{
if (button2_state) {
rgb red(1.0, 0, 0);
show(red);
}
// Your code here to handle new button press
button2_timeout = millis() + BOUNCE_DURATION; // set whatever bounce time in ms is appropriate
}
}
// the setup routine runs once when you press reset:
void setup()
{
pinMode(pinR, OUTPUT);
pinMode(pinG, OUTPUT);
pinMode(pinB, OUTPUT);
attachInterrupt(0, button1_int, CHANGE);
attachInterrupt(1, button2_int, CHANGE);
}
int prev_h=0;
// the loop routine runs over and over again forever:
void loop()
{
int h = map(analogRead(A1), 0, 1023, 0, 360);
if (h > prev_h+2 || h<prev_h-2) {
hsv color(h, 1.0, 1.0);
rgb col_rgb = hsv2rgb(color);
show(col_rgb);
prev_h = h;
}
delay(10);
//showCycle();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment