Pages: 1 [2] 3   Go Down
Author Topic: Need help with RGB rainbow colors  (Read 3249 times)
0 Members and 1 Guest are viewing this topic.
Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 211
Posts: 13494
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
//
//    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 );
}
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

West Des Moines, Iowa USA
Offline Offline
Sr. Member
****
Karma: 2
Posts: 428
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


Interesting! I just tossed this version into my "play" directory:
Code:
#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);
}
Logged

There's always a better way!

Belgium
Offline Offline
Full Member
***
Karma: 2
Posts: 211
I love Arduino!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 211
Posts: 13494
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Quote
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)

Code:
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);
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Belgium
Offline Offline
Full Member
***
Karma: 2
Posts: 211
I love Arduino!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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

Code:
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]);
}


Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 211
Posts: 13494
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

You need an interpolation function, not trivial as it can have many parameters depending on the way you interpolate.

linear interpolation is easiest (see code below, not tested might contain some bugs)

Code:
void interpolate( byte *col1, byte *col2, byte *out, int stepnr, int maxsteps)     
{
  for (int i =0; i<3; i++)
  {
    out[i] = col1[i] + stepnr * (col2[i] - col1[i]) / maxsteps);
  }
}

.... usage ...

for (int c=0; c<100; c++)
{
  byte newColor[3];
  interpolate(Red, Green, newColor, c, 100);
  displayColor(newColor);
}
Give it a try
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Belgium
Offline Offline
Full Member
***
Karma: 2
Posts: 211
I love Arduino!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Seems to be a bit to difficult for me, because I really don't know where I should place your code into my existing code smiley

Should an easy fade out and fade in between each color be easier?
Logged

West Des Moines, Iowa USA
Offline Offline
Sr. Member
****
Karma: 2
Posts: 428
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Every RBG color consists of a red component, a green component, and a blue component. To output a single color, all that's needed is to output its components. If you want indigo with red = 111, green = 0, and blue = 255 then all that's needed is
Code:
   analogWrite(redPin,111);
   analogWrite(greenPin,0);
   analogWrite(bluePin,255);

To produce the rainbow cycle you asked about, you'll find it helpful to take a look at a color wheel like the one I've attached below (click on the thumbnail to see full size). Notice that there are 6 (sixty degree) segments in each of which only one of the three components changes while the other two remain constant.

What that means is than if you want to smoothly transition all the way around the wheel, you can do so by setting up a sequence of six loops, each of which changes only one of the three components - as I did in my previous post.   smiley-mr-green


* rgb_wheel(sm).jpg (47.12 KB, 480x481 - viewed 23 times.)
Logged

There's always a better way!

Belgium
Offline Offline
Full Member
***
Karma: 2
Posts: 211
I love Arduino!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the tip! smiley-lol

Is it possible to fade out and fade back in to another color between the colors in my code, instead of a delay?
So the colors does not just go out, but fade out, and then fade in to another color.
« Last Edit: March 10, 2012, 12:39:41 pm by TiboJ » Logged

West Des Moines, Iowa USA
Offline Offline
Sr. Member
****
Karma: 2
Posts: 428
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Certainly. All you need to do is choose that "another color" and choose which direction around the color wheel you want to go, then write the sequence(s) to show the intermediate values.
Logged

There's always a better way!

West Des Moines, Iowa USA
Offline Offline
Sr. Member
****
Karma: 2
Posts: 428
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I might have misunderstood. If you were asking about fading the current color to dark, then gradually bringing up another color, then you might want to try something like this (untested):
Code:
void write_rgb_components(unsigned char r,unsigned char g,unsigned char b)
{  static unsigned char old_r, old_g, old_b;

   if (r != old_r) analogWrite(R,old_r = r);
   if (g != old_g) analogWrite(G,old_g = g);
   if (b != old_b) analogWrite(B,old_b = b);
   delay(50);
}

void fade_from(unsigned char r,unsigned char g,unsigned char b)
{  unsigned i;
   for (i = 255; i != 0; i--)
      write_rgb_components((i * r) >> 8,(i * g) >> 8,(i * b) >> 8);
   write_rgb_components(0,0,0);
}

void fade_to(unsigned char r,unsigned char g,unsigned char b)
{  unsigned i;
   for (i = 0; i < 256; i++)
      write_rgb_components((i * r) >> 8,(i * g) >> 8,(i * b) >> 8);
   write_rgb_components(r,g,b);
}
Logged

There's always a better way!

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Im not so good at this, but I find bitshift and other things like that hard to understand. I think that everybody is giving good advise, but its a bit over my head. Isn't it easier to make an array in the setup and then use it in the code without any calculations?

Code:
arrayPos=0;
stepSize=16

// red to magenta
for (x=0; x<255; x+stepSize){
  arrayRGB[arrayPos]=[255,0,x]
  arrayPos++;
}

// magenta to blue
for (x=255; x!=0; x-stepSize){
  arrayRGB[arrayPos]=[x,0,255]
  arrayPos++;
}

// blue to cyan
for (x=0; x<255; x+stepSize){
  arrayRGB[arrayPos]=[0,x,255]
  arrayPos++;
}

// cyan to green
for (x=255; x!=0; x--){
  arrayRGB[arrayPos]=[0,255,x]
  arrayPos++;
}


// green to yellow
for (x=0; x<255; x+stepSize){
  arrayRGB[arrayPos]=[x,255,0]
  arrayPos++;
}

// yellow to red
for (x=255; x!=0; x-stepSize){
  arrayRGB[arrayPos]=[255,x,0]
  arrayPos++;
}
Logged

West Des Moines, Iowa USA
Offline Offline
Sr. Member
****
Karma: 2
Posts: 428
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@tiirak - we can't assign three values to a single (scalar) array element, but if calculating the values is sufficiently simple, then it may actually cost less to calculate values as needed than to calculate them and store/fetch them from an array.
Logged

There's always a better way!

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry, Im a newbee here. Just tied to write quick and easy to understand. What about this?

Code:
// red to magenta
for (x=0; x<255; x+stepSize){
  arrayRGB[arrayPos][1]=255;
  arrayRGB[arrayPos][2]=0;
  arrayRGB[arrayPos][3]=x;
  arrayPos++;
}

And isn't it better to take memory (if possible) and not cycles?
Logged

West Des Moines, Iowa USA
Offline Offline
Sr. Member
****
Karma: 2
Posts: 428
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hmm - you just used up all available RAM to store 3-byte red values, and then your program crashed.  smiley-evil

It's up to you to decide if this is the best approach for your particular application. If the application were a simple learning exercise with a goal of transitioning smoothly from one displayed color to another, I would not be much inclined to worry about resources - but rather with my understanding of the interface between the standard hardware, my code, and techniques for producing color.
Logged

There's always a better way!

Pages: 1 [2] 3   Go Up
Jump to: