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); } }
1 comment