I\'ve currently managed to get my LED to cycle through eight colors that I\'ve selected. Everything is working correctly, except that I want to go for a more natural feel, and w
This is probably what you are looking for. Whenever we want to shift color over the spectrum and trasition the colors in a circular and smooth motion, what we are really doing is shifting light using HUE in the HSI/HSV (Hue, Saturation, Intensity/Value) color space.
Take if you will this figure:
We will attach a value from 0-360 for hue because hue has 360 degrees of color. A value of 0.00 - 1.00 for saturation, and a value of 0.00 -1.00 for intensity/value
Here is my circuit on the MEGA 2560:
Here is video of this code running:
So lets build a function that we can pass the hue value and a for loop inside our loop function to call that value 360 times to shift over the full rainbow of color.
//Define the pins we will use with our rgb led
int redPin = 9;
int greenPin = 10;
int bluePin = 11;
//define that we are using common anode leds
#define COMMON_ANODE
void setup()
{
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
}
int rgb[3];
//Arduino has no prebuilt function for hsi to rgb so we make one:
void hsi_to_rgb(float H, float S, float I) {
int r, g, b;
if (H > 360) {
H = H - 360;
}
// Serial.println("H: "+String(H));
H = fmod(H, 360); // cycle H around to 0-360 degrees
H = 3.14159 * H / (float)180; // Convert to radians.
S = S > 0 ? (S < 1 ? S : 1) : 0; // clamp S and I to interval [0,1]
I = I > 0 ? (I < 1 ? I : 1) : 0;
if (H < 2.09439) {
r = 255 * I / 3 * (1 + S * cos(H) / cos(1.047196667 - H));
g = 255 * I / 3 * (1 + S * (1 - cos(H) / cos(1.047196667 - H)));
b = 255 * I / 3 * (1 - S);
} else if (H < 4.188787) {
H = H - 2.09439;
g = 255 * I / 3 * (1 + S * cos(H) / cos(1.047196667 - H));
b = 255 * I / 3 * (1 + S * (1 - cos(H) / cos(1.047196667 - H)));
r = 255 * I / 3 * (1 - S);
} else {
H = H - 4.188787;
b = 255 * I / 3 * (1 + S * cos(H) / cos(1.047196667 - H));
r = 255 * I / 3 * (1 + S * (1 - cos(H) / cos(1.047196667 - H)));
g = 255 * I / 3 * (1 - S);
}
rgb[0] = r;
rgb[1] = g;
rgb[2] = b;
}
void setColor(int red, int green, int blue)
{
#ifdef COMMON_ANODE
red = 255 - red;
green = 255 - green;
blue = 255 - blue;
#endif
analogWrite(redPin, red);
analogWrite(greenPin, green);
analogWrite(bluePin, blue);
}
///here we have our main loop and the for loop to shift color
void loop()
{
//the for loop counts to 360 and because its in our control loop it will run forever
// We will use int i to increment the actual desired color
for (int i=0; i<=360;i++){
hsi_to_rgb(i,1,1);
setColor(rgb[0],rgb[1],rgb[2]);
//Changing the delay() value in milliseconds will change how fast the
//the light moves over the hue values
delay(5);
}
}