Adafruit Industries, Essential service and business: NYC – Executive Order 202.6 - Read more.
0

RGB PWM
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

RGB PWM

by Nachimir on Fri Apr 18, 2008 7:08 pm

Limor, thank you for the arduino kit and tutorials :) I'm looking forward to going through more of them.

I have a couple of questions for anyone willing to answer them.

I went through the tuts then figured out RGB PWM fading by building on this example.

Here what I have it doing now with an RGB LED:
http://www.youtube.com/watch?v=hwV07dDHsaA

This is the sketch:

Code: Select all | TOGGLE FULL SIZE
// First RGB sketch, based on arduino.cc fade example

int valueR = 0;                            // variable to keep the actual value
int valueG = 0;
int valueB = 0;

int ledpinR = 9;                           // Red channel
int ledpinG = 11;                          // Green channel
int ledpinB = 10;                          // Blue channel

void setup()
{
  Serial.begin(9600);           // set up Serial library at 9600 bps
  Serial.println("Serial A-OK");
}

void loop()
{
  { Serial.println("R");}
  for(valueR = 0 ; valueR <= 255; valueR+=1) // R up
  {
    analogWrite(ledpinR, valueR);           // sets the value (range from 0 to 255)
    analogWrite(ledpinG, 0);
    analogWrite(ledpinB, 0);
 
    delay(5);                            // waits for 30 milli seconds to see the dimming effect
  }
{  Serial.println("R+G");}
   for(valueG = 0 ; valueG <= 255; valueG+=1) // G up, R on
  {
    analogWrite(ledpinR, 255);
    analogWrite(ledpinB, 0);
    analogWrite(ledpinG, valueG);

    delay(5);
  }
{  Serial.println("G");}
   for(valueR = 255 ; valueR >= 0; valueR-=1) // R down, G on
  {
    analogWrite(ledpinG, 255);
    analogWrite(ledpinB, 0);
    analogWrite(ledpinR, valueR);

    delay(5);
  }
{  Serial.println("G+B");  }   
   for(valueB = 0 ; valueB <= 255; valueB+=1) // B up, G on
  {
    analogWrite(ledpinG, 255);
    analogWrite(ledpinR, 0);
    analogWrite(ledpinB, valueB);

    delay(5);
  }

{  Serial.println("B");}
   for(valueG = 255 ; valueG >= 0; valueG-=1) // G down, B on
  {
    analogWrite(ledpinB, 255);
    analogWrite(ledpinR, 0);
    analogWrite(ledpinG, valueG);

    delay(5);
  }
{  Serial.println("B+R");}
  for(valueR = 0 ; valueR <= 255; valueR+=1) // R up, B on
  {
    analogWrite(ledpinB, 255);
    analogWrite(ledpinG, 0);
    analogWrite(ledpinR, valueR);

    delay(5);
  }
 {  Serial.println("B+R+G"); }   
   for(valueG = 0 ; valueG <= 255; valueG+=1) // G up, all on
  {
    analogWrite(ledpinB, 255);
    analogWrite(ledpinR, 255);
    analogWrite(ledpinG, valueG);
 
    delay(5);
  }

 
 {  Serial.println("RGB");}
 {
    analogWrite(ledpinR, 255);
    analogWrite(ledpinG, 255);
    analogWrite(ledpinB, 255);

  delay(1275);
  }

{  Serial.println("-R-G-B");}
  for(valueR,valueG,valueB = 255; valueR,valueG,valueB >=0; valueR-=1,valueG-=1,valueB-=1)   // Fade all out
  {
    analogWrite(ledpinR, valueR);
    analogWrite(ledpinG, valueG);
    analogWrite(ledpinB, valueB);

    delay(5);
  }

}


First question is this: As it hits the end of the 1275 delay, switching from the part I have marked with Serial.println("RGB"); to the next phase of "-R-G-B", the LED flickers out for a split second, with all channels (it appears) set to 0 (You can't make this out in the youtube video, but it's readily discernable with the naked eye). Is there something wrong with my code that's causing this to happen, rather than having it stay fully lit then fade down?

Second question:
With
for(valueR,valueG,valueB = 255; valueR,valueG,valueB >=0; valueR-=1,valueG-=1,valueB-=1)
It was just a lucky guess that I could use commas to work on three things at once - I went through plenty of garbage code and guesswork to get there. Where are some good places I can learn about things like this? Any good books?

Third question:
Is my code anywhere near efficient, or have I put a lot of redundant stuff in there? could I achieve the same thing with a much shorter sketch?

Writing code is hard: I've never done anything beyond XHTML and CSS before, and it doesn't come naturally to me (I'm more into level design and art for games). I find circuits very comprehensible because they're tangible. Working out programming languages isn't so easy for me. I'm used to solving problems like a gamer, i.e. assuming all the elements I need are to hand are located within my current environment and findable without external help. != true! :)

(Next project outside of random messing around with sketches: ipod clickwheels as inputs :))
Last edited by Nachimir on Fri Apr 18, 2008 7:13 pm, edited 1 time in total.
Nachimir
 
Posts: 7
Joined: Thu Dec 07, 2006 2:06 pm

by cell on Fri Apr 18, 2008 10:41 pm

If you just set everything to 0 initially, you can eliminate some of your statements:

Code: Select all | TOGGLE FULL SIZE
for(valueR = 0 ; valueR <= 255; valueR+=1) // R up
  {
    analogWrite(ledpinR, valueR);           // sets the value (range from 0 to 255)
    analogWrite(ledpinG, 0);
    analogWrite(ledpinB, 0);
 
    delay(5);                            // waits for 30 milli seconds to see the dimming effect
  }


in the above, you could get rid of the lines which set ledpinG and ledpinB to 0. other than that it looks fine :)

cell
 
Posts: 44
Joined: Fri Nov 02, 2007 9:24 am

Re: RGB PWM

by mtbf0 on Sun Apr 20, 2008 7:03 am

rather extravagant use of braces. not really a problem here, but could cause scoping problems with more complicated code.

you spend a lot of time making calls to analogWrite setting values that are already set. as the talking heads say...
You start a conversation you can't even finish it.
You're talkin' a lot, but you're not sayin' anything.
When I have nothing to say, my lips are sealed.
Say something once, why say it again?

in your last loop all three values will reach zero at the same time, (give or take maybe a quarter of a microsecond), so there's not much point testing all of them.
Code: Select all | TOGGLE FULL SIZE
// First RGB sketch, based on arduino.cc fade example

int valueR = 0;                            // variable to keep the actual value
int valueG = 0;
int valueB = 0;

int ledpinR = 9;                           // Red channel
int ledpinG = 11;                          // Green channel
int ledpinB = 10;                          // Blue channel

void setup()
{
  Serial.begin(9600);           // set up Serial library at 9600 bps
  Serial.println("Serial A-OK");
  analogWrite (ledpinR, 0);
  analogWrite (ledpinG, 0);
  analogWrite (ledpinB, 0);
}

void loop()
{
  Serial.println("R");
  for(valueR = 0 ; valueR <= 255; valueR+=1) // R up
  {
    analogWrite(ledpinR, valueR);           // sets the value (range from 0 to 255)
  delay(5);                            // waits for 30 milli seconds to see the dimming effect
  }

  Serial.println("R+G");
  for(valueG = 0 ; valueG <= 255; valueG+=1) // G up, R on
  {
    analogWrite(ledpinG, valueG);
    delay(5);
  }

  Serial.println("G");
  for(valueR = 255 ; valueR >= 0; valueR-=1) // R down, G on
  {
    analogWrite(ledpinR, valueR);
    delay(5);
  }

  Serial.println("G+B");
   for(valueB = 0 ; valueB <= 255; valueB+=1) // B up, G on
  {
    analogWrite(ledpinB, valueB);
    delay(5);
  }

  Serial.println("B");
   for(valueG = 255 ; valueG >= 0; valueG-=1) // G down, B on
  {
    analogWrite(ledpinG, valueG);
    delay(5);
  }

  Serial.println("B+R");
  for(valueR = 0 ; valueR <= 255; valueR+=1) // R up, B on
  {
    analogWrite(ledpinR, valueR);
    delay(5);
  }

  Serial.println("B+R+G");
   for(valueG = 0 ; valueG <= 255; valueG+=1) // G up, all on
  {
    analogWrite(ledpinG, valueG);
    delay(5);
  }

  Serial.println("RGB");
//  analogWrite(ledpinR, 255);
//  analogWrite(ledpinG, 255);
//  analogWrite(ledpinB, 255);
  delay(1275);

  Serial.println("-R-G-B");
  for(valueR,valueG,valueB = 255; valueB >=0; valueR-=1,valueG-=1,valueB-=1)   // Fade all out
  {
    analogWrite(ledpinR, valueR);
    analogWrite(ledpinG, valueG);
    analogWrite(ledpinB, valueB);
    delay(5);
  }

}


Nachimir wrote:First question is this: As it hits the end of the 1275 delay, switching from the part I have marked with Serial.println("RGB"); to the next phase of "-R-G-B", the LED flickers out for a split second, with all channels (it appears) set to 0 (You can't make this out in the youtube video, but it's readily discernable with the naked eye). Is there something wrong with my code that's causing this to happen, rather than having it stay fully lit then fade down?

hmmm. very mysterious.

Second question:
With
for(valueR,valueG,valueB = 255; valueR,valueG,valueB >=0; valueR-=1,valueG-=1,valueB-=1)
It was just a lucky guess that I could use commas to work on three things at once - I went through plenty of garbage code and guesswork to get there. Where are some good places I can learn about things like this?
the internet.
Any good books?
kernighan and ritchie. 30 some years old and never goes out of style. it's, like, the bible.
Third question:
Is my code anywhere near efficient, or have I put a lot of redundant stuff in there? could I achieve the same thing with a much shorter sketch?
little shorter. yeah.
Writing code is hard:
no it's not. (cue maniacal laughter, theremin.)
I've never done anything beyond XHTML and CSS before, and it doesn't come naturally to me (I'm more into level design and art for games).
whatever that is.
I find circuits very comprehensible because they're tangible. Working out programming languages isn't so easy for me. I'm used to solving problems like a gamer, i.e. assuming all the elements I need are to hand are located within my current environment and findable without external help. != true! :)

seriously, if the internet is part of your environment, (and apparently it is), everything you need is at hand. i code only occasionally and am always looking up the crap my brain refuses to retain. download a copy of the mega168 datasheet. get a copy of k&r. (WARNING: ignore pointer referencing and dereferencing until you've already got a substance abuse problem of some sort.) bookmark the arduino playground and this site. just like that you've created your own little virtual world complete with trolls and troglodytes like me.
User avatar
mtbf0
 
Posts: 1645
Joined: Sat Nov 10, 2007 12:59 am
Location: oakland ca

by Silver on Mon Apr 21, 2008 3:53 am

Nachimir,

Welcome to the wonderful world of programming. You have found two of the most common errors that plague programmers. The first is called "off by one" or the "picket fence" error. The second is your guess that you could use commas to work on three things at once.

The first problem is using stored values for your loop counters. The way loops in C work is give a loop counter a starting value, a condition to test, and a way to change the counter so the condition will not be true forever. The problem occurs at the end of the loop. In order to exit your loop, your variable has to exceed 255. That means at the end of the loop your values will = 256. This doesn't present a problem until your last loop.

Second question:
With
for(valueR,valueG,valueB = 255; valueR,valueG,valueB >=0; valueR-=1,valueG-=1,valueB-=1)
It was just a lucky guess that I could use commas to work on three things at once - I went through plenty of garbage code and guesswork to get there. Where are some good places I can learn about things like this? Any good books?


This works, but not for the reason you think. You are not actually working on three values at once. "valueR,valueG,valueB=255" gets interpreted as "leave valueR alone, leave valueG alone, set valueB to 255". Because your previous loops have ended in all three variables equal to 256, you actually are sending (0,0,255) to the three pins. The next time through the loop you will be sending (255,255,254), etc.

You can see the problem by running this short sketch.

Code: Select all | TOGGLE FULL SIZE
// Test loop

int valueR = 10;                 // variable to keep the actual value
int valueG = 10;                 // set to 10 for this example
int valueB = 10;

void setup()
{
  Serial.begin(9600);           // set up Serial library at 9600 bps

  for(valueR,valueG,valueB = 0; valueR,valueG,valueB <=3; valueR+=1,valueG+=1,valueB+=1)   
  {
  Serial.print("R = ");
  Serial.println(valueR);
  Serial.print("G = ");
  Serial.println(valueG);
  Serial.print("B = ");
  Serial.println(valueB);
  Serial.println(" ");
  delay(1000);
  }
  Serial.println("Final values");
  Serial.print("R = ");
  Serial.println(valueR);
  Serial.print("G = ");
  Serial.println(valueG);
  Serial.print("B = ");
  Serial.println(valueB);
  Serial.println(" ");
}

void loop()
{
}

========= Simulated Output ===========
R = 10
G = 10
B = 0
 
R = 11
G = 11
B = 1
 
R = 12
G = 12
B = 2
 
R = 13
G = 13
B = 3
 
Final values
R = 14
G = 14
B = 4



As you can see, valueR and valueG do NOT get set to 0 as you suspected. Also, at the end of the loop, you will see that valueB is left at 4, not 3 as many programmers guess.

As for making your code more efficient, my personal rule is if I have any code that is repeated more than twice, I put it in a subroutine or function. I have modified your code a bit below, but I have not tested it. I know, I know, the rule is NEVER post code unless it is tested, but it is almost midnight and I don't have a tri-color LED to test with.

Code: Select all | TOGGLE FULL SIZE
// Tri-color LED with subroutine, based on arduino.cc fade example

int level;                                 //value to send

int ledpinR = 9;                           // Red channel
int ledpinG = 11;                          // Green channel
int ledpinB = 10;                          // Blue channel

void setup()
{
  Serial.begin(9600);                      // set up Serial library at 9600 bps

  analogWrite(ledpinR, 0);                 // sets initial values
  analogWrite(ledpinG, 0);
  analogWrite(ledpinB, 0);
}

void loop()
{
  countUp(ledpinR);
  countUp(ledpinG);
  countDown(ledpinR);
  countUp(ledpinB);
  countDown(ledpinG);
  countUp(ledpinR);
  countUp(ledpinG);
 
  delay(1275);
 
  for(level = 255; level >= 0; level--)    // R255 G255 B255 => R0 G0 B0
  {
    analogWrite(ledpinR, level);
    analogWrite(ledpinG, level);
    analogWrite(ledpinB, level);
    delay(5);
  }

}  //end of loop()

void countUp(int pin)
{
  for(int level = 0; level <= 255; level++)
  {
    analogWrite(pin, level);               // sets the value (range from 0 to 255)
    delay(5);                              // waits for 5 milliseconds to see the dimming effect
  }
}   //end of countUp

void countDown(int pin)
{
  for(int level = 255; level >= 0; level--)
  {
    analogWrite(pin, level);               // sets the value (range from 255 to 0)
    delay(5);                              // waits for 5 milliseconds to see the dimming effect
  }
}   //end of countDown



Hope this helps.

Silver
Silver
 
Posts: 12
Joined: Mon Apr 21, 2008 1:39 am

Please be positive and constructive with your questions and comments.