Swapping from using 3 LEDs to a single RGB LED

Ok i got it working. Now the problem is getting the LED to be off. When i get the value down to zero the LED is full on. This will limit the colors i can produce but then that's no a big deal.

Next step will involve more coding and i'll ask help for later on in the thread i have in the software section. But it has to do with getting the fade values to report back to the PC so i can see where they are at.

Thanks everyone for the help. Sorry about my ignorance.

When i get the value down to zero the LED is full on

And when it is 255?

255 is off now its just a matter of incorporating it into the sketch so that when it hits 0 it goes to 255 instead. So i'm working out those minor details right now.

so that when it hits 0 it goes to 255 instead

Hint: Subtract.

If you think of it as positive logic, i.e. writing 25% of 255 means you get 25% brightness, encapsulate your "analogWrite"s in a simple method that does the subtraction for you.

I got it worked out. unless you see a more simplistic solution.

/*
  created 14 Jan 2010
  by digimike
  modified 14 jan 2010
  by digimike
  */
  
  
  int redled = 9;    // assign LED to pin 9
  int redup = 2;    // assign pushbuttons to pins
  int reddown = 3;
  
  int r_btn_up = 0;    // variable for reading the pushbuttons
  int r_btn_down = 0;
  int fadered = -5;    // starting brightness values for each led
  
 
  void setup () {     
    pinMode(redup, INPUT);    //initialize pushbutton pins as input:
    pinMode(reddown, INPUT);
    digitalWrite(redup, HIGH);
    digitalWrite(reddown, HIGH);
  }
  
  void loop() {
// increase the brightness
    r_btn_up = digitalRead(redup);    //check button state
    if(r_btn_up == LOW && fadered >= -250) {
      if(fadered == 255) {fadered = 0;} // if fade value is 255 (off) set it to 0
      // if button is pressed increase brightness by 5
      // as long as brightness isn't greater than -250
      fadered -=5;
      analogWrite(redled, fadered);  // lights LED at current brightness level
      delay(250);  // allows time so button won't be detected multiple times 
    }
    
// decrease brightness
    r_btn_down = digitalRead(reddown);    //check button state
    if(r_btn_down == LOW && fadered <= -5) {
      // if button is pressed decrease brightness by 5
      // as long as brightness isn't less than -5
      fadered +=5;
      if(fadered == 0) {fadered = 255;}  
      // when the fade value reaches 0, 255 is stored to the fade value to turn off the LED
      analogWrite(redled, fadered);  // lights LED at current brightness level
      delay(250);  // allows time so button won't be detected multiple times
    }
    
  }

As you can see i added a line so that when the fade value is 0 it then stores 255 to the fade value. Then on the increase brightness if it finds the fade value is 255 it then stores it at 0.

Poor code.

Try:

  void setup () {
    pinMode(redup, INPUT);    //initialize pushbutton pins as input:
    pinMode(reddown, INPUT);
    digitalWrite(redup, HIGH);
    digitalWrite(reddown, HIGH);
  }

  void loop() {
// increase the brightness
    r_btn_up = digitalRead(redup);    //check button state
    if(r_btn_up == LOW) {
      // if button is pressed increase brightness by 5
      fadered -=5;
        if (fadered < 0) { fadered = 0; } // don't let fadered get below zero
      analogWrite(redled, fadered);  // lights LED at current brightness level
      delay(250);  // allows time so button won't be detected multiple times
    }

// decrease brightness
    r_btn_down = digitalRead(reddown);    //check button state
    if(r_btn_down == LOW) {
      // if button is pressed decrease brightness by 5
      fadered +=5;
      if (fadered > 255) {fadered = 255;}  //don't let fadered get above 255
      analogWrite(redled, fadered);  // lights LED at current brightness level
      delay(250);  // allows time so button won't be detected multiple times
    }

  }

It would be slightly more efficient if you used e.g. if (fadered <= 250) { fadered += 5; }, but I prefer to make damn sure the variable stays in range.

Doesn’t work.

negative numbers have to be used for the values so that the RGB will light. The RGB is getting +5V dirrectly and the cathode sides are connected to the pins. Because of this a value of 0 as the LED full on rather then off. In this case 255 is full off. The reason i have the “&& fadered >= -250”, is i don’t want it to automaticly cycle round to the oposite value. I want it to stop. This way the up button only increases the brightness and the down btton decreases. If i wanted to be efficient about it then i would only have 1 button per color and let it cycle around again. I don’t need to have it look for fadered to be <0 since i know it will hit 0 and go no further. Likewise with the >255. By tomorrow morning i’ll have it fully documented here. Including the breadboard diagam prepaired in Fritzing.

Set it up yourself with a single LED. Just wire the anode to +5 and the cathode to a PWM pin threw a 220 Ohm resistor. The buttons is wired from ground to one of the pins.

EDIT: That is the way the code was, minus the if statments inside the if statments, when i was using plain LEDs. But the fact that my RGB uses a common anode rather then cathode it had to be switched to negative numbers as you see it.

If i had an RGB with a common cathode then i could have the cade as you showed it minus:

if(fadered == 255) {fadered = 0;}

and

if(fadered == 0) {fadered = 255;}

The

if(r_btn_up == LOW && fadered <= 250)

and

if(r_btn_down == LOW && fadered <= 5)

would still have to look like that to prevent the fadered value from looping around again.

Also in your version the

fadered -=5;

should read

fadered +=5;

and vice versa for the next one down. Otherwise the up button dimms and the down button brightens.

negative numbers have to be used for the values so that the RGB will light

No, no, no, with a side-order of wrong.

Please read what has been written. "analogWrite" takes positive numbers, to set the PWM mark:space ratio (duty-cycle). A 25% duty-cycle with the LED connected to supply and the signal pin will result in a 75% ON time, because whilst the pin is LOW, current will sink through the load. When the pin is HIGH no current can flow because there is no (well, virtually none) potential difference between the pin and the supply, so for 25% of the time, the LED is off.

Now, to simplify things, imagine that analogWrite takes values in the range 0..100 (%).

I want the LED to be lit 30% of the time, so I call:

analogWrite (100 - 30);

So now I want the LED to be fully on (100%):

analogWrite (100 - 100);

See, no negative numbers.

Just to make it more obvious, when the pin is at zero volts the LED is fully bright. This is because the cathode is tied to the positive rail of the power supply, and the LED lights when the pin is brought to 0V. If the pin was HIGH (say 5V, although it isn't going to go that high), then the two sides of the LED are at the same voltage and you get no photons. When you bring the pin LOW, the LED has one side HIGH (common cathode to the power supply) and the other side LOW (arduino pin pulling down through the resistor) and will light up.

This is why Groove wrote (100-30). He wanted 30% on duty cycle, but the pin needs to be LOW for 30% and HIGH for 70% to get that. analogWrite specifies the HIGH percentage, so he subtracted his target percentage from the maximum, which effectively "inverts" the signal.

In my code, I simply made the up button subtract and the down button add, which does the same thing. You will note that if you try this, the LED will start fully bright, and then only go down, because fadered is initialized to 0. If you want the LED to start off and then only go brighter, then you need to initialize fadered = 255.

:-/ :-[ Thank you guys. I'm always in a hurry to do things which leads to mistakes and me thinking i know more then i actually do. Worst yet is i tend to be slow on the up take. I had to really stare at the code and figure out why it was working. I have allot to learn about everything here. Time to take a step back and have a good read threw the A Complete Beginners Guide to the Arduino and any other resource i can get my hands on.

I do need to apologize. I had gotten things to work but in my mind i thought there couldn't possibly be a better way of doing it. Even though i asked for help and suggestions i just shot them down. Thanks again for forcing the correct information into my thick skull.

(common cathode to the power supply)

"anode"

@digimike: You weren't entirely wrong when you talked about negative numbers, but the earlier code worked as side-effect of the range of numbers you can represent in a byte.

However, it was a side-effect, and although you can rely on it to work in some cases, using it as a general rule will come back to bite you on the ass at some later date. Best to learn good habits early-on.

Yes i see that now. I am one that wants to have things as efficient as possible and that just wasn’t it.

In the corrections that brtech gave me he put the the argument that prevents the fade value from going below 0 in the middle of the if statement. So the main if statement is executed and 5 is subtracted from the fade value only to be set back to 0 in the next line.

 r_btn_up = digitalRead(redup);    //check button state
    if(r_btn_up == LOW) {
      // if button is pressed increase brightness by 5
      fadered -=5;
        if (fadered < 0) { fadered = 0; } // don't let fadered get below zero
      analogWrite(redled, fadered);  // lights LED at current brightness level
      delay(250);  // allows time so button won't be detected multiple times
    }

But my preference is to have that same sort of argument at the beginning of the main if statement. This way the if the fade value isn’t greater then 0 it won’t even execute that section of code. Correct me if i’m wrong but that seams a bit more efficient to me.

r_btn_up = digitalRead(redup);    //check button state
    if(r_btn_up == LOW && fadered > 0) {
      // if button is pressed increase brightness by 5
      fadered -=5;
        analogWrite(redled, fadered);  // lights LED at current brightness level
      delay(250);  // allows time so button won't be detected multiple times
    }

Now for a more relevant question. For the sake of keeping the code as small as possible. Does it matter the amount of code there is?
For example i end up using less characters in the code to add the " && fadered > 0" to the initial if statement rather then having “if (fadered < 0) { fadered = 0; }” in the middle? Or does it not matter once the code is compiled?

Does it matter the amount of code there is?

The answer to that question is probably "No", but generally, the less there is, the less there is to go wrong, and the less there is to have to read to understand.

You have three lots of code (one set for each channel) which are essentially the same, except for the detail of the physical resources each channel uses. Factoring up this code would result in code that, once proven to work for one channel, could be expanded to as many channels as you have resources, with little risk of cut-and-paste programming errors, simply by defining the appropriate resources.

Also, you have static variables for each condition of the button presses, but you have no need to keep these values. They're "ints" (two bytes on the Arduino) too, but they hold only the condition "HIGH" or "LOW".

On a PC program with gigbytes of memory, these would be trivial, but on a microcontroller, these are potentially important savings.

Going threw the interactive traffic light project in the Complete Beginners Guide to the Arduino i learned that i can use "byte" rather then "int" and save the extra byte in the code. I also learned the button state can be defined with "boolean" since its just looking for true/false (HIGH/LOW) like you mentioned. But "byte" would do just as good here and save the extra byte that "int" would use.

Not that i need the savings now or ever will need it but i do want to learn this the right way and use data types as they are intended to be used.

Just thought i would update what i’ve got. I went threw and streamlined the code a bit. Then added serial connectivity to the PC so that the brightness values of each color can be reported to the PC. Before adding the serial communication the streamlining of the code saved me 46 bytes. The serial communication added another 1914 bytes to the code. Its interesting to see how big of a difference some bits of code make in the file size.

Well here is the code which now takes 3530 bytes. Its the full code for controlling the RGB not just the test code for a single color LED.

/*
  RGB Color Wheel w/ Serial Comunication
  
  Indivigually control the brightness of each color in an RGB LED 
  using 6 pushbuttons attached to pins 2 thru 7. The pushbuttons
  on the even number pins will brighten the corosponding
  LED and the odd numbered ones will dim them. RGB will be attached
  to pins 9, 10, and 11. 
  
  The Circuit:
  * RBGB LED with common anode on +5V
  * Red cathode connected to pin 9 threw 220 Ohm resistor
  * Blue cathode connected to pin 9 threw 470 Ohm resistor
  * Green cathode connected to pin 9 threw 1000 Ohm resistor
  * pushbutton 1 attached to pin 2 from ground
  * pushbutton 2 attached to pin 3 from ground
  * pushbutton 3 attached to pin 4 from ground
  * pushbutton 4 attached to pin 5 from ground
  * pushbutton 5 attached to pin 6 from ground
  * pushbutton 6 attached to pin 7 from ground
  
  If the RGB LED in use has a common cathode the the roles of the 
  buttons become reversed and the brightness of the LED will be
  full on at the start of code. 
  
  created 13 Jan 2010
  by digimike
  modified 16 jan 2010
  by digimike
  */
  
boolean ledpin[] = {9, 10, 11};  // assign LEDs to pins
    
boolean button[] = {2, 3, 4, 5, 6, 7};  // assign pushbuttons to pins
  
boolean buttonstate = 0;
    
int fadered = 255;    // starting brightness values for each led
int fadegreen = 255;  // 255 sets the LEDs to the off position
int fadeblue = 255;   // when an RGB with a common anode is in use
 
void setup () 
{     
  Serial.begin(9600); // designates serial comunication rate
  for(int x=0; x<6; x++)
  {
    pinMode(button[x], INPUT);  //initialize pushbutton pins as input:
  }
  for(int x=0; x<6; x++)
  {
    digitalWrite(button[x], HIGH);  // pushbuttons are read as high till pressed
  }
  analogWrite(ledpin[0], fadered);    //lights the LED at current brightness
  analogWrite(ledpin[1], fadegreen);    //lights the LED at current brightness
  analogWrite(ledpin[2], fadeblue);    //lights the LED at current brightness    
  }
  
void loop() 
{
  for(int x=0; x<6; x++)
  {
    buttonstate = digitalRead(button[x]);    //check button state
    if(buttonstate == LOW && fadered >0 && button[x] == 2) 
    {
      // if button is pressed increase brightness by 5
      fadered -=5;
      analogWrite(ledpin[0], fadered);  // lights LED at current brightness level
      delay(250);  // allows time so button won't be detected multiple times 
    }
    
    if(buttonstate == LOW && fadered < 255 && button[x] == 3) 
    {
      // if button is pressed decrease brightness by 5
      fadered +=5;
      analogWrite(ledpin[0], fadered);  // lights LED at current brightness level
      delay(250);  // allows time so button won't be detected multiple times
    }
    
    if (buttonstate == LOW && fadegreen > 0 && button[x] == 4) 
    {
      // if button is pressed increase brightness by 5
      fadegreen -=5;
      analogWrite(ledpin[1], fadegreen);  // lights LED at current brightness level
      delay(250);  // allows time so button won't be detected multiple times
    }  
        
    if (buttonstate == LOW && fadegreen < 255 && button[x] == 5) 
    {  
      // if button is pressed decrease brightness by 5
      fadegreen +=5;
      analogWrite(ledpin[1], fadegreen);  // lights LED at current brightness level
      delay(250);  // allows time so button won't be detected multiple times
    }
    
    if (buttonstate == LOW && fadeblue > 0 && button[x] == 6) 
    {  
      // if button is pressed increase brightness by 5
      fadeblue -= 5;
      analogWrite(ledpin[2], fadeblue);  // lights LED at current brightness level
      delay(250);  // allows time so button won't be detected multiple times
    }
    
    if (buttonstate == LOW && fadeblue < 255 && button[x] == 7) 
    {  
      // if button is pressed decrease brightness by 5
      fadeblue += 5;
      analogWrite(ledpin[2], fadeblue);  // lights LED at current brightness level
      delay(250);  // allows time so button won't be detected multiple times
    }
    if(buttonstate == LOW)  // checks if any button has ben pressed
    {  // prints brightness levels to the PC. 0 being full on and 255 being off
      Serial.print("Red LED level is at: ");
      Serial.println(fadered);
      Serial.print("Green LED level is at: ");
      Serial.println(fadegreen);
      Serial.print("Blue LED level is at: ");
      Serial.println(fadeblue);
    }
  }
}