Go Down

Topic: Help on random led coloring? (Read 4 times) previous topic - next topic

marklar

Remove the color call from setup and add as the first line of loop()

Code: [Select]

const byte PIN_RED     = 9;
const byte PIN_GREEN = 10;
const byte PIN_BLUE    = 11;

void color(unsigned long v)
{
byte red = v & 255;
byte green = (v >> 8) & 255;
byte blue = (v >> 16) & 255;
analogWrite(PIN_RED,    red);
analogWrite(PIN_GREEN, green);
analogWrite(PIN_BLUE,  blue);
// red green blue values are available for other uses
}


void setup()
{
Serial.begin(9600);
pinMode(PIN_RED,   OUTPUT);  
pinMode(PIN_GREEN, OUTPUT);  
pinMode(PIN_BLUE,  OUTPUT);
randomSeed(analogRead(0));

}
void loop()
{
  color((unsigned long)random(0x01000000));
 if(PIN_RED > 100);{
   Serial.print("redled on ");
 }
   
   if(PIN_RED < 100);{
    Serial.print("redled off ");
   }
     delay(3000);
}


AWOL

Quote
void loop()
{
 if(PIN_RED > 100);{
   Serial.print("redled on ");
 }
   
   if(PIN_RED < 100);{
    Serial.print("redled off ");
   }
     delay(3000);
}

Unfortunately, the serial monitor just says "led on led off" every 3 seconds. Why does it do that?


There is no way your code as posted will say "led on led off".
It may say, "redled on redled off", but even this is unlikely because the value of PIN_RED is a constant 9.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

TBAr

#17
Sep 15, 2009, 10:00 am Last Edit: Sep 15, 2009, 10:07 am by TBAr Reason: 1
Code: [Select]

 if(PIN_RED > 100)[glow];[/glow]{
...
   if(PIN_RED < 100)[glow];[/glow]{

AWOL

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

marklar

What I have found is that using the HSV spectrum really helps when you want to pull random colors.  What you will notice from a function that gets  any random color out of 16 million is that you end up with white-out colors and the result may be less than what you really want.

Also, you most likely want to control more than one LED and will want more control than just setting a random color.  To that end I am working on an LED class and I have put together some randomizing functions.  You can set a random color (out of the 16 M) or you can set a random hue from 0 to 255.  While the normal hue spectrum is 0 to 360, I convert this to a 0 to 255 spectrum to allow the storage of a full color in one byte (not three) .. when all I care about is the color.

This allows you to control your Saturation and Brightness (Value) and when your color (Hue) changes .. it keeps the same basic brightness / look.  Then when you want to keep the same color but just make it more or less bright - you can adjust the Hue and Saturation and the basic color will stay the same.

This is a full demo you can copy / paste into a new project.

Hope this helps.
Code: [Select]

//- Joseph Francis - Open Source - As Is, etc.

#ifndef RGBCommonLED_H
#define RGBCommonLED_H

#include "WProgram.h"


class RGBCommonLED {
public:
 RGBCommonLED(int rpin, int gpin, int bpin);
 ~RGBCommonLED();

 //--- methods
 void setRGB(byte r, byte g, byte b);
 void setHSV(byte h, byte s, byte v);
 void setColor(unsigned long v);
 void setHue(byte level);
 void setSat(byte level);
 void setVal(byte level);

 void adjHue(int level);
 void adjSat(int level);
 void adjVal(int level);

 void setRandomColor();
 void setRandomHue();
 void setRandomSat();
 void setRandomVal();

 //--- easy for the chip / code
 void setHSVLevel(int section, byte level);
 void adjHSVLevel(int section, int level);
 void setRandomHSVLevel(int section);
 
 //--- Used to update the led pins (or related vars that update on scan)
 void updateLED();

 //--- Conversion routine that loads the "o"s with a value from 0 to 255 for RGVB
 void HSVToRGB( unsigned int inHue, unsigned int inSaturation, unsigned int inValue,
   unsigned int *oR, unsigned int *oG, unsigned int *oB );

 //--- Conversion routine that loads the "o"s with a value from 0 to 255 for S and V
 //    and load oH with a value from 0 to 360 .. use map(returnval,0,360,0,255) to convert
 void RGBToHSV( unsigned int inRed, unsigned int inGreen, unsigned int inBlue,
   unsigned int *oH, unsigned int *oS, unsigned int *oV );

 //--- When needed - this will update the HSV value by converting from the RGB value
 //   currently set
 void updateHSVFromRGB();

 //--- pins for this led, in order R G B
 int pins[3];
 //--- colors for this led, in order R G B
 int rgb[3];
 //--- colors in HSV format, in order H S V
 int hsv[3];

private:
 //--- used to keep from converting when we dont have to (already did - no change);
 boolean hsvSet;
 void setRGBFromHSV();
 void setHSVFromRGB();
};

#endif


//<<constructor>>
RGBCommonLED::RGBCommonLED(int rpin, int gpin, int bpin){
 pins[0] = rpin;
 pins[1] = gpin;
 pins[2] = bpin;
 hsvSet = false;
}

//<<destructor>>
RGBCommonLED::~RGBCommonLED(){/*nothing to destruct*/
}

void RGBCommonLED::setColor(unsigned long v)
{
 this->setRGB((v & 255),((v >> 8) & 255),(v >> 16) & 255);
}


void RGBCommonLED::setRGB(byte r, byte g, byte b){
 rgb[0] = r;
 rgb[1] = g;
 rgb[2] = b;
 hsvSet = false;
}

void RGBCommonLED::setHSV(byte h, byte s, byte v){
 hsv[0] = h;
 hsv[1] = s;
 hsv[2] = v;
 this->setRGBFromHSV();
 hsvSet = true;
}


void RGBCommonLED::setHSVLevel(int section, byte level){
 updateHSVFromRGB();
 hsv[section] = level;
 this->setRGBFromHSV();
}

void RGBCommonLED::setHue(byte level){
 this->setHSVLevel(0,level);
}

void RGBCommonLED::setSat(byte level){
 this->setHSVLevel(1,level);
}

void RGBCommonLED::setVal(byte level){
 this->setHSVLevel(2,level);
}

void RGBCommonLED::adjHSVLevel(int section, int level){
 updateHSVFromRGB();
 int th = hsv[section] + level;

 if( th < 0 ){
   th = 255 + th;    
 }
 else if( th > 255 ) {
   th = 255 - th;    
 }

 th = constrain(th,0,255); //just in case?
 hsv[section] = th;
 this->setRGBFromHSV();
}

void RGBCommonLED::adjHue(int level){
 this->adjHSVLevel(0,level);
}

void RGBCommonLED::adjSat(int level){
 this->adjHSVLevel(1,level);
}

void RGBCommonLED::adjVal(int level){
 this->adjHSVLevel(2,level);
}



void RGBCommonLED::RGBToHSV( unsigned int inRed, unsigned int inGreen, unsigned int inBlue,
unsigned int *oH, unsigned int *oS, unsigned int *oV )
{
 //struct Color_HSV HSV; //structure to return
 double vals[3]; //thue = temporary var (linked to hue)
 unsigned char maxc=0, minc=0; //red=0, green=1, blue=2
 double hue, sat, val;

 vals[0]=inRed;
 vals[1]=inGreen;
 vals[2]=inBlue;
 //red is set as maximum and minimum
 if(vals[1]>vals[maxc]) maxc=1; //if green is greater, make green the max.
 if(vals[2]>vals[maxc]) maxc=2; //if blue is greater, make blue the max
 if(vals[1]<vals[minc]) minc=1; //if green is less, make green the min.
 if(vals[2]<vals[minc]) minc=2; //if blue is less, make blue the min.
 val = vals[maxc]; //set the HSV.val to the maximum component value (this is a final value)
 if(vals[maxc]==0) //if maximum component is 0, color must be black
   sat = hue = 0; //so set values to 0 manually to avoid div by 0 errors
 else
 { //otherwise, calculate the values
   sat=255*(1-(vals[minc]/vals[maxc])); //compressed equation - original: HSV.sat=((vals[maxc]-vals[minc])/vals[maxc])*255;
   hue = 60 * ((maxc*2) + (vals[(maxc+1)%3] - vals[(maxc+2)%3])/(vals[maxc] - vals[minc])); //this cannot be simplified - and i havn't got time to explain it
 }
 if(hue < 0) hue += 360; //corrector for hues in -60 to 0 range
 *oH = hue; //map(hue,0,360,0,255);
 *oS = sat;
 *oV = val;
}

void RGBCommonLED::HSVToRGB( unsigned int inHue, unsigned int inSaturation, unsigned int inValue,
unsigned int *oR, unsigned int *oG, unsigned int *oB )
{
 if( inSaturation == 0 )
 {
   // achromatic (grey)
   *oR = *oG = *oB = inValue;
 }
 else
 {
   unsigned int scaledHue = (inHue * 6);
   unsigned int sector = scaledHue >> 8; // sector 0 to 5 around the color wheel
   unsigned int offsetInSector = scaledHue - (sector << 8);      // position within the sector
   unsigned int p = (inValue * ( 255 - inSaturation )) >> 8;
   unsigned int q = (inValue * ( 255 - ((inSaturation * offsetInSector) >> 8) )) >> 8;
   unsigned int t = (inValue * ( 255 - ((inSaturation * ( 255 - offsetInSector )) >> 8) )) >> 8;

   switch( sector ) {
   case 0:
     *oR = inValue;
     *oG = t;
     *oB = p;
     break;
   case 1:
     *oR = q;
     *oG = inValue;
     *oB = p;
     break;
   case 2:
     *oR = p;
     *oG = inValue;
     *oB = t;
     break;
   case 3:
     *oR = p;
     *oG = q;
     *oB = inValue;
     break;
   case 4:
     *oR = t;
     *oG = p;
     *oB = inValue;
     break;
   default:            // case 5:
     *oR = inValue;
     *oG = p;
     *oB = q;
     break;
   }
 }
}

void RGBCommonLED::setRandomColor(){
 this->setColor((unsigned long)random(0x01000000));
}

void RGBCommonLED::setRandomHue(){
 this->setRandomHSVLevel(0);
}
void RGBCommonLED::setRandomSat(){
 this->setRandomHSVLevel(1);
}
void RGBCommonLED::setRandomVal(){
 this->setRandomHSVLevel(2);
}

void RGBCommonLED::setRandomHSVLevel(int section){
 this->setHSVLevel(section, (unsigned int)random(0x0100));
}


void RGBCommonLED::updateHSVFromRGB(){
 //   if (hsvSet)
 //     return;
 this->setHSVFromRGB();  
 hsvSet = true;
}


void RGBCommonLED::updateLED(){
 analogWrite(this->pins[0], rgb[0]);
 analogWrite(this->pins[1], rgb[1]);
 analogWrite(this->pins[2], rgb[2]);
}


void RGBCommonLED::setRGBFromHSV(){
 unsigned int h = hsv[0];
 unsigned int s = hsv[1];
 unsigned int v = hsv[2];
 unsigned int r = 0;
 unsigned int g = 0;
 unsigned int b = 0;
 HSVToRGB(h,s,v,&r,&g,&b);
 this->setRGB(r,g,b);
}

void RGBCommonLED::setHSVFromRGB(){
 unsigned int r = rgb[0];
 unsigned int g = rgb[1];
 unsigned int b = rgb[2];
 unsigned int h;
 unsigned int s;
 unsigned int v;

 this->RGBToHSV(r,g,b,&h,&s,&v);
 hsv[0] = map(h,0,360,0,255);
 hsv[1] = s;
 hsv[2] = v;
 hsvSet = true;
}

RGBCommonLED led1(10,11,9);

void setup()
{
 Serial.begin(9600);
 randomSeed(analogRead(0));
 testRGB();
}

void testRGB(){
 led1.setRGB(255,0,0);
 led1.updateLED();
 delay(500);
 led1.setRGB(0,255,0);
 led1.updateLED();
 delay(500);
 led1.setRGB(0,0,255);
 led1.updateLED();
 delay(2000);
 return;

}

void loop()
{  
 led1.setRandomHue();
 led1.setSat(255);
 led1.setVal(255);
 led1.updateLED();
 delay(1000);
 led1.setRandomColor();
 led1.updateLED();
 delay(1000);
 return;

}





Grumpy_Mike

I found a good way of generating random colours is to generate the triplet (RGB) and then make each component in turn equal to zero. This gives three related colours that don't bland out.

There is some example code written in 'processing' to do this on the site for this project:-
http://www.thebox.myzen.co.uk/Hardware/Mini_Monome.html

ikestarm

It still won't work. All I want is to be able to make an rgb led show 1 completely random color and have it know the values 0-255 of each color so I can use them later. Now I just want it to display a message in the serial monitor to see if it knows the values, however it won't work. I am new to this, please bear with me. :)

Grumpy_Mike

OK so post your code and lets see where you are up to.

ikestarm

Code: [Select]
const byte PIN_RED     = 9;
const byte PIN_GREEN = 10;
const byte PIN_BLUE    = 11;

void color(unsigned long v)
{
byte red = v & 255;
byte green = (v >> 8) & 255;
byte blue = (v >> 16) & 255;
analogWrite(PIN_RED,    red);
analogWrite(PIN_GREEN, green);
analogWrite(PIN_BLUE,  blue);
// red green blue values are available for other uses
}


void setup()
{
Serial.begin(9600);
pinMode(PIN_RED,   OUTPUT);
pinMode(PIN_GREEN, OUTPUT);
pinMode(PIN_BLUE,  OUTPUT);
randomSeed(analogRead(0));

 color((unsigned long)random(0x01000000));
 analogRead(PIN_RED);
 if(PIN_RED > 100);{
   Serial.print("redled on ");
 }

   if(PIN_RED < 100);{
    Serial.print("redled off ");
   }

}
void loop()
{

     
}


the serial monitor says "red led on redled off" every time, hit restart no matter what.

AWOL

#24
Sep 16, 2009, 08:33 am Last Edit: Sep 16, 2009, 10:44 am by AWOL Reason: 1
Your problem was already answered in reply #17 by TBAr.

Look closely.

You've also declared PIN_RED with a value of 9 (hint: therefore it will always be less than 100), but this is set as an output, and you're using it as an analogue input, and you discard the value read by your "analogRead".
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

ikestarm

#25
Sep 16, 2009, 11:36 pm Last Edit: Sep 16, 2009, 11:44 pm by ikestarm Reason: 1
I didn't know what I was thinking, I was just trying to get it to work. I don't get what it says in #17 though

If it will always think it is 9, then how will it work?

Grumpy_Mike

#26
Sep 17, 2009, 09:25 am Last Edit: Sep 17, 2009, 09:26 am by Grumpy_Mike Reason: 1
Quote
If it will always think it is 9, then how will it work?


It won't, you are doing it wrong.

You can't read the value sent out to the PWM of a digital output with an analogue read. This reads the value from an analogue input pin.
What you have to do is to remember what you set the RGB values to by using global variables.

You are also confusing the pin number, that's the actual connection, with the value you wrote to that pin number. That's why it is always 9 it is always a pin number. So use the value, not the pin number, in the if statement.

Finally DON'T follow the closing brackets in an if statement with a semicolon. If you do the if statement has no effect. That was pointed out to you way back in reply #17 but you seem to keep missing it.

Try this:-

Code: [Select]

const byte PIN_RED     = 9;
const byte PIN_GREEN = 10;
const byte PIN_BLUE    = 11;
byte red, green, blue;

void color(unsigned long v)
{
 red = v & 255;
 green = (v >> 8) & 255;
 blue = (v >> 16) & 255;
analogWrite(PIN_RED,    red);
analogWrite(PIN_GREEN, green);
analogWrite(PIN_BLUE,  blue);
// red green blue values are available for other uses
}


void setup()
{
Serial.begin(9600);
pinMode(PIN_RED,   OUTPUT);
pinMode(PIN_GREEN, OUTPUT);
pinMode(PIN_BLUE,  OUTPUT);
randomSeed(analogRead(0));

 color((unsigned long)random(0x01000000));
 if(red > 100){
   Serial.print("redled on ");
 }
   else {
    Serial.print("redled off ");
   }
  serial.print(" green value ");
  serial.println(green, DEC);

}
void loop()
{
}


AWOL

Quote
If it will always think it is 9, then how will it work?

By correcting it.

Reply 17 highlighted the semicolons (in yellow, at least on my screen) after the "if" statement.

Code: [Select]
if (RED_PIN > 100);
is a valid 'C' statement that does precisely nothing (except, perhaps, waste a few machine cycles, unless the compiler optimises it out).
even if you write it out correctly as
Code: [Select]

if (RED_PIN > 100) {
  Serial.print ("redled on ");
}


"redled on" will never be printed, because you've already told the compiler that the value of RED_PIN is 9, which is less than 100.

You need to separate the value "RED_LED" which is a convenient label for a pin on the device, from the value you might want to write as a PWM value to that pin.

Your "analogRead (RED_PIN);" is a function returning a value, but unless you're using a Mega, there is no analogue pin 9.
"analogRead" does not return the value you wrote with an "analogWrite".



"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

ikestarm

#28
Sep 17, 2009, 10:14 pm Last Edit: Sep 17, 2009, 10:18 pm by ikestarm Reason: 1
sorry I didn't know what the highlighting meant

}
   else {
    Serial.print("redled off ");
   }
  [glow]serial.print(" green value ");[/glow]
  serial.println(green, DEC);

}
void loop()
{
}

it says "serial not declared when I try to compile it. Why?

AWOL

Quote
serial.print(" green value ");
 

Because you didn't spell it "Serial"
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Go Up