There were some flaws in the post HSV colour cycling LED on Arduino. This does much more what I wanted:
/* HSV fade/bounce for Arduino - Stewart C. Russell - scruss.com - 2010/09/19 Wiring: LED is RGB common cathode (SparkFun sku: COM-09264 or equivalent)     * Digital pin  9 → 165Ω resistor → LED Red pin     * Digital pin 10 → 100Ω resistor → LED Green pin     * Digital pin 11 → 100Ω resistor → LED Blue pin     * GND → LED common cathode. */ #define RED                9 // pin for red LED; green on RED+1 pin, blue on RED+2 pin #define DELAY              2 long rgb[3]; long rgbval, k; float hsv[3] = {   0.0, 0.5, 0.5 }; float hsv_min[3] = {   0.0, 0.0, 0.4 // keep V term greater than 0 for smoothness }; float hsv_max[3] = {   6.0, 1.0, 1.0 }; float hsv_delta[3] = {   0.0005, 0.00013, 0.00011 }; /* chosen LED SparkFun sku: COM-09264  has Max Luminosity (RGB): (2800, 6500, 1200)mcd  so we normalize them all to 1200 mcd -  R  1200/2800  =  0.428571428571429   =   109/256  G  1200/6500  =  0.184615384615385   =    47/256  B  1200/1200  =  1.0                 =   256/256  */ long bright[3] = {   109, 47, 256 }; void setup () {   randomSeed(analogRead(4));   for (k=0; k<3; k++) {     pinMode(RED + k, OUTPUT);     rgb[k]=0; // start with the LED off     analogWrite(RED + k, rgb[k] * bright[k]/256);     if (k>1 && random(100) > 50) {       // randomly twiddle direction of saturation and value increment on startup       hsv_delta[k] *= -1.0;     }   } } void loop() {   for (k=0; k<3; k++) { // for all three HSV values     hsv[k] += hsv_delta[k];     if (k<1) { // hue sweeps simply upwards       if (hsv[k] > hsv_max[k]) {         hsv[k]=hsv_min[k];       }        }     else { // saturation or value bounce around       if (hsv[k] > hsv_max[k] || hsv[k] < hsv_min[k]) {         hsv_delta[k] *= -1.0;         hsv[k] += hsv_delta[k];       }     }     hsv[k] = constrain(hsv[k], hsv_min[k], hsv_max[k]); // keep values in range   }   rgbval=HSV_to_RGB(hsv[0], hsv[1], hsv[2]);   rgb[0] = (rgbval & 0x00FF0000) >> 16; // there must be better ways   rgb[1] = (rgbval & 0x0000FF00) >> 8;   rgb[2] = rgbval & 0x000000FF;   for (k=0; k<3; k++) { // for all three RGB values     analogWrite(RED + k, rgb[k] * bright[k]/256);   }   delay(DELAY); } long HSV_to_RGB( float h, float s, float v ) {   /*      modified from Alvy Ray Smith's site:    http://www.alvyray.com/Papers/hsv2rgb.htm    H is given on [0, 6]. S and V are given on [0, 1].    RGB is returned as a 24-bit long #rrggbb    */   int i;   float m, n, f;   // not very elegant way of dealing with out of range: return black   if ((s<0.0) || (s>1.0) || (v<0.0) || (v>1.0)) {     return 0L;   }   if ((h < 0.0) || (h > 6.0)) {     return long( v * 255 ) + long( v * 255 ) * 256 + long( v * 255 ) * 65536;   }   i = floor(h);   f = h - i;   if ( !(i&1) ) {     f = 1 - f; // if i is even   }   m = v * (1 - s);   n = v * (1 - s * f);   switch (i) {   case 6:   case 0: // RETURN_RGB(v, n, m)     return long(v * 255 ) * 65536 + long( n * 255 ) * 256 + long( m * 255);   case 1: // RETURN_RGB(n, v, m)     return long(n * 255 ) * 65536 + long( v * 255 ) * 256 + long( m * 255);   case 2: // RETURN_RGB(m, v, n)     return long(m * 255 ) * 65536 + long( v * 255 ) * 256 + long( n * 255);   case 3: // RETURN_RGB(m, n, v)     return long(m * 255 ) * 65536 + long( n * 255 ) * 256 + long( v * 255);   case 4: // RETURN_RGB(n, m, v)     return long(n * 255 ) * 65536 + long( m * 255 ) * 256 + long( v * 255);   case 5: // RETURN_RGB(v, m, n)     return long(v * 255 ) * 65536 + long( m * 255 ) * 256 + long( n * 255);   } }Â
Leave a Reply