Need help with RGB rainbow colors

Hey all,

I'm reading the 'Beginning Arduino' book to learn Arduino.
Now that I have completed Project 8(RGB Mood Lamp), I need to make an exercise.
I have to make all the colors of the rainbow with the three leds(red, green, blue), but I'm stuck with the code.

I have tried modifying the code of Project 8, but I can't find out how to let the LEDs switch between the colors of the rainbow.

Here is the code of project 8:

// Project 8 - Mood Lamp
float RGB1[3];
float RGB2[3];
float INC[3];

int red, green, blue;

int RedPin = 11;
int GreenPin = 10;
int BluePin = 9;

void setup() 
{ 
  	randomSeed(analogRead(0));
  
  	RGB1[0] = 0;
  RGB1[1] = 0;
  	RGB1[2] = 0;
  
  	RGB2[0] = random(256);
  	RGB2[1] = random(256);
  	RGB2[2] = random(256);  
} 
 
void loop() 
{ 
  	randomSeed(analogRead(0));
  
  	for (int x=0; x<3; x++) {
    		INC[x] = (RGB1[x] - RGB2[x]) / 256; } 
  
  	for (int x=0; x<256; x++) {
    		red = int(RGB1[0]);
    		green = int(RGB1[1]);
    		blue = int(RGB1[2]);

    		analogWrite (RedPin, red);  
    		analogWrite (GreenPin, green);   
    		analogWrite (BluePin, blue);     
   		delay(100);   
    
    		RGB1[0] -= INC[0];
    		RGB1[1] -= INC[1];    
    		RGB1[2] -= INC[2];    
  	}
  	for (int x=0; x<3; x++) {
  		RGB2[x] = random(556)-300;
  		RGB2[x] = constrain(RGB2[x], 0, 255); 
  		delay(1000);
 }
}

Any help would be appreciated! :wink:

Tibo

If you are developing this code on your own, you should be putting comments in to explain what each step/block is doing. If you are typing the code in from a book, the book should be explaining what each step is doing, and you should add the comments to the code to match what the book says.

However, it appears that the code is varying the color of each led at random. Just watch it long enough, and eventually you will see all the colors of the rainbow.

If you want to see the colors in some specific order, you need to explain what that order is.

PaulS:
If you want to see the colors in some specific order, you need to explain what that order is.

That's just what I want to do, but I don't understand how to do it. I don't want random rainbow colors, but colors of the rainbow in a specific order.
This is what the exercise says:

See if you can make the lights cycle through the colours of the
rainbow rather than between random colours.

For example: First red, then green, then yellow,...

ps: I added comments in my original, but they aren't here because I downloaded this code from the website of the book. :wink:

Anyone?

The colors are Red, Orange, Yellow, Green, Blue, Indigo, and Violet.

Determine the RGB values for each of these colors.
Set a beginning color and an ending color.
Morph between them.
New beginning color equals previous end color.
Morph between them.
Loop till done with last begin-end pair completed.

Now just figure out how to do the morphing.

Shouldn't take much effort if you think about it first!

HINT: Uses HSL <-> RGB

To help you understand color mixing, I googled "color wheel".
http://www.google.com/search?q=color+wheel&oe=utf-8&rls=org.mozilla:en-US:official&client=firefox-a&channel=np&safe=images&um=1&ie=UTF-8&hl=en&tbm=isch&source=og&sa=N&tab=wi&ei=OFtWT-KXAuLo0QGGrdyUCg&biw=1024&bih=638&sei=iVtWT83vHOLq0gGDnPy1Cg

Thank you for the answers!

lloyddean:
The colors are Red, Orange, Yellow, Green, Blue, Indigo, and Violet.

Determine the RGB values for each of these colors.
Set a beginning color and an ending color.
Morph between them.
New beginning color equals previous end color.
Morph between them.
Loop till done with last begin-end pair completed.

Now just figure out how to do the morphing.

Shouldn't take much effort if you think about it first!

HINT: Uses HSL <-> RGB
HSL and HSV - Wikipedia

I already have the colors and the values of them, but the problem is that I can't find out how to add the custom RGB color values in the code, and let them display. I've thinked and experimented with it and still no luck.
I'll try again tomorrow.

You should go for the HSL color model, then you can have the Hue just change from 0 to 255. you can keep the S and L constant (e.g. 127).

COnvert the HSL to RGB

and display them

so something like this and a bit from your own program. The convertion formulas can be found here on the forum or at wikipedia.

void loop()
{
L=127;
S=127;
for (H=0; H<256; H++)
{
  Red = convertRFromHSL(H,S,L);
  Green = convertGFromHSL(H,S,L);
  Blue = convertBFromHSL(H,S,L);
  analogWrite (RedPin, red);  
  analogWrite (GreenPin, green);   
  analogWrite (BluePin, blue);     
  delay(100);  
}
}

Succes

robtillaart:
You should go for the HSL color model, then you can have the Hue just change from 0 to 255. you can keep the S and L constant (e.g. 127).

COnvert the HSL to RGB

and display them

so something like this and a bit from your own program. The convertion formulas can be found here on the forum or at wikipedia.

void loop()

{
L=127;
S=127;
for (H=0; H<256; H++)
{
  Red = convertRFromHSL(H,S,L);
  Green = convertGFromHSL(H,S,L);
  Blue = convertBFromHSL(H,S,L);
  analogWrite (RedPin, red); 
  analogWrite (GreenPin, green);   
  analogWrite (BluePin, blue);     
  delay(100); 
}
}




Succes

Thank you, I'll will try this, and let you know if it worked or not. :wink:

This seems to be a bit difficult for me.
Is there really no way to choose which RGB color to display? It couldn't be that hard because it's an exercise in the 'Beginning Arduino' book, and there is nothing writed about HSL.

First of all, work out which colours you want to display. For the standard 'rainbow colours' that would be Red, Orange, Yellow, Green, Blue, Indigo and Voilet.

Then, work out the RGB values to display those colours on the LEDs. Use a website like 500+ Named Colours with rgb and hex values, or work it out for yourself.

Then, store the colour values in an array and cycle through them in your sketch. If you want smooth transitions between each colour, then you'll need to work out an interpolation routine to shift from one set of values to the next.

I've already got the colors RGB values, and I'll try to use it with arrays.
Thank you for the reply :wink:

I've never done any analog output, and I don't have any green or blue LEDS for testing - but it seems to me that you should be able to cycle through the rainbow with something as simple as

#define PAUSE 50  /* Slow to desired speed */

#define RED
#define GREEN      /* Define your LED pin numbers */
#define BLUE

unsigned char red=255,green=0,blue=0;

void setup(void)
{  analogWrite(RED,red);
   analogWrite(GREEN,green);
   analogWrite(BLUE,blue);
}
void loop(void)
{  do
   {  analogWrite(GREEN,++green);
      delay(PAUSE);
   }  while (255 != green);
   do
   {  analogWrite(RED,--red);
      delay(PAUSE);
   }  while (red);
   do
   {  analogWrite(BLUE,++blue);
      delay(PAUSE);
   }  while (255 != blue);
   do
   {  analogWrite(GREEN,--green);
      delay(PAUSE);
   }  while (green);
   do
   {  analogWrite(RED,++red);
      delay(PAUSE);
   }  while (255 != red);
   do
   {  analogWrite(BLUE,--blue);
      delay(PAUSE);
   }  while (blue);
}

Edited to fix pin defs

I will try this, thank you.

Should I make an array like this?: Red[] = {255,0,0}
And how do I make the array display the color then?

Your code works nice!
Now how can I make a color display with the RGB value that I want, for example: 111,0,255 ?

Should I make an array like this?: Red[] = {111,0,255}
And how do I make the array display the color then?

found this one in my experiments section. Code goes 360 degrees through hue space converting it to related RGB values.
links to 2 website included

//
//    FILE: RGB2HUE.pde
//  AUTHOR: Rob Tillaart
//    DATE: 2011-09-17 
//
// PUPROSE: color-rainbow
//
// http://www.dipzo.com/wordpress/?p=50
// http://www.easyrgb.com/index.php?X=MATH
//

int Rpin=10;
int Gpin=9;
int Bpin=11;

float H,S,L, Rval,Gval,Bval;

void HSL(float H, float S, float L, float& Rval, float& Gval, float& Bval);
float Hue_2_RGB( float v1, float v2, float vH );

void setup()
{
  Serial.begin(9600);

  pinMode(12, OUTPUT); 
}


void loop()
{
  S=1;
  L=.5;
  Rval=0;
  Gval=0;
  Bval=0;
  for (int i = 0; i< 360; i++)
  {
    HSL(i/360.0,S,L,Rval,Gval,Bval);

    //common anode configuration
    //analogWrite(Rpin, 255-Rval);
    //analogWrite(Gpin, 255-Gval);
    //analogWrite(Bpin, 255-Bval);
    //digitalWrite(12,HIGH);

    //common cathode configuration
    analogWrite(Rpin, Rval);
    analogWrite(Gpin, Gval);
    analogWrite(Bpin, Bval);
    digitalWrite(12,LOW);

    //print statements for debug
    Serial.print("position:");
    Serial.print(H);
    Serial.print(" R:");
    Serial.print(Rval);
    Serial.print(" G:");
    Serial.print(Gval);
    Serial.print(" B:");
    Serial.println(Bval);
    delay(100);
  }
}

void HSL(float H, float S, float L, float& Rval, float& Gval, float& Bval)
{
  float var_1;
  float var_2;
  float Hu=H+.33;
  float Hd=H-.33;
  if ( S == 0 )                       //HSL from 0 to 1
  {
    Rval = L * 255;                      //RGB results from 0 to 255
    Gval = L * 255;
    Bval = L * 255;
  }
  else
  {
    if ( L < 0.5 ) 
      var_2 = L * ( 1 + S );
    else           
      var_2 = ( L + S ) - ( S * L );

    var_1 = 2 * L - var_2;

    Rval = round(255 * Hue_2_RGB( var_1, var_2, Hu ));
    Serial.print("Rval:");
    Serial.println(Hue_2_RGB( var_1, var_2, Hu ));
    Gval = round(255 * Hue_2_RGB( var_1, var_2, H ));
    Bval = round(255 * Hue_2_RGB( var_1, var_2, Hd ));
  }

}
float Hue_2_RGB( float v1, float v2, float vH )             //Function Hue_2_RGB
{
  if ( vH < 0 ) 
    vH += 1;
  if ( vH > 1 ) 
    vH -= 1;
  if ( ( 6 * vH ) < 1 ) 
    return ( v1 + ( v2 - v1 ) * 6 * vH );
  if ( ( 2 * vH ) < 1 ) 
    return ( v2 );
  if ( ( 3 * vH ) < 2 ) 
    return ( v1 + ( v2 - v1 ) * (.66-vH) * 6 );
  return ( v1 );
}

Interesting! I just tossed this version into my "play" directory:

#define R
#define G      /* Define analog LED pins */
#define B

unsigned char r=~0,g=0,b=0;

void aw(unsigned char p,unsigned char v)
{  analogWrite(p,v);
   delay(50);
}
void setup(void)
{  analogWrite(R,r);
   analogWrite(G,g);
   analogWrite(B,b);
}
void loop(void)
{  do aw(G,++g); while (~g);
   do aw(R,--r); while ( r);
   do aw(B,++b); while (~b);
   do aw(G,--g); while ( g);
   do aw(R,++r); while (~r);
   do aw(B,--b); while ( b);
}

They all work fine, but how can I make a color display with the RGB value that I want, for example the color indigo : 111,0,255(red led is less bright, green led is off, blue led is at full brightness) ?
So not automatic color change.

Should I make an array like this?: Red[] = {111,0,255}
And how do I make the array display the color then?

Should I make an array like this?: Red[] = {111,0,255}
And how do I make the array display the color then?

Yes, define colors as separate arrays
2) define a function something like this, (not tested)

byte indigo[] = { 111,0, 255 };
byte red [] = {255, 0, 0 };

void displayColor(byte *color)
{  analogWrite(R, color[0]);
   analogWrite(G, color[1]);
   analogWrite(B, color[2]);
}

then you can call - displayColor(red);

That's what I wanted!
With a little modification, it worked.
Thank you!

Now, how can I make a smooth transition between them?

byte red [] = { 255, 0, 0 };
byte orange [] = { 255,127,0 };
byte yellow [] = { 255,255,0 };
byte green [] = { 0,255,0 };
byte blue [] = { 0,0,255 };
byte indigo[] = { 111,0,255 };
byte violet[] = { 127,0,255 };

int R = 11;
int G = 10;
int B = 9;

#define DELAY 3000

void setup(){
  
  pinMode(R, OUTPUT);
  pinMode(G, OUTPUT);
  pinMode(B, OUTPUT);
}
void loop(){
  displayColor(red);
  delay(DELAY);
  displayColor(orange);
  delay(DELAY);
  displayColor(yellow);
  delay(DELAY);
  displayColor(green);
  delay(DELAY);
  displayColor(blue);
  delay(DELAY);
  displayColor(indigo);
  delay(DELAY);
  displayColor(violet);
  delay(DELAY);
}

  void displayColor(byte *color)
{  analogWrite(R, color[0]);
   analogWrite(G, color[1]);
   analogWrite(B, color[2]);
}