Can anyone Help me out with Code for a RGB LED Throbbing/Breathing effect

Im Trying to help a friend of mine with a RGB LED Control system for giant kaleidoscopes hes building, he is looking for a specific effect and Im having trouble finding anything similar on the web:

He wants a "Breathing" "Pulsating" or "Throbbing" effect that dims right down to near or complete darkness before building up again in next colour in sequence.
Ive found some code for a nice breathing effect on a single colour LED :

int ledPin = 13;
int x = 0;

void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop() {
  int outVal = yforx(x);
  analogWrite(ledPin, outVal);
  delay(18);
  x++;
}

int yforx(int x) {
  return (-240*abs(sin(x*0.01)))+255; //sine wave
}

And Ive also found code for changing between 7 colours:

/*************************** 
Author: Seth Leeper 
Version: 1 
Purpose: To cycle the tri-color LED 
contained within the Sparkfun starter kit 
through every available color combination with 
a fade in/fade out effect. 
************************************/ 

int RED = 5;    // RED pin of the LED to PWM pin 9 
int GREEN = 6;  // GREEN pin of the LED to PWM pin 10 
int BLUE = 7;   // BLUE pin of the LED to PWM pin 11 

int DELAY_TIME = 15;  //changes speed of fading 
int MAX_BRIGHT = 255; //sets maximum brightness, 255 max brightness 
int COLOR_MIX = 0; //variable to change the colors that are mixed in switch statement 

void fade_in(int x) //loop that gradually turns the LED on using PWM 
{ 
    int counter; 
    
    for(counter = 0; counter < x; counter++) 
    { 
        led_mixer(COLOR_MIX, counter); 
        delay(DELAY_TIME); 
    } 
} 

void fade_out(int x) //loop that gradually turns the LED off using PWM 
{ 
    int counter; 
    
    for(counter = x; counter > 0; counter--) 
    { 
        led_mixer(COLOR_MIX, counter); 
        delay(DELAY_TIME); 
    } 
} 

void led_mixer(int color, int x) //uses switch statement to mix color combinations 
{ 
    switch(color) 
    { 
      case 0: 
        analogWrite(RED, x); 
        break; 
      case 1: 
        analogWrite(GREEN, x); 
        break; 
      case 2: 
        analogWrite(BLUE, x); 
        break; 
      case 3: 
        analogWrite(BLUE, x); 
        analogWrite(GREEN, x); 
        break; 
      case 4: 
        analogWrite(RED, x); 
        analogWrite(BLUE, x); 
        break; 
      case 5: 
        analogWrite(RED, x); 
        analogWrite(GREEN, x); 
        break; 
      default: 
        analogWrite(GREEN, x); 
        analogWrite(BLUE, x); 
        analogWrite(RED, x); 
      break; 
    } 
} 

void setup() 
{ 
  // nothing for setup 
} 

void loop() //loop forever 
{ 
  fade_in(MAX_BRIGHT); //gradually turn the LED on to max brightness 
  fade_out(MAX_BRIGHT); //gradually turn off the LED 
  COLOR_MIX++; //increment to the next color combination 
  
  if(COLOR_MIX == 7) //if all color combinations have been displayed, reset the cycle 
  { 
    COLOR_MIX = 0; 
  } 
}

Im just having problems combining the two programs, im not looking for a smooth fade, If I was I would have plenty of code to pick from, Problem is that I need the brightness to die right down before next colour comes in,
Can anyone offer any assistance or point me in the direction of something similar thats already out there?
Thanks.

P.S. Im new to arduino and havnt time to learn it all from scratch as ive other projects to work on so im trying to use code I can find on net and modify it to save some time but Im starting to realise this is harder than I thought! :slight_smile:

Haha... well, I think I may have a segment of code that'll help. I spent about 2 hours sequencing these values and making sure they work right... originally, this was a massive block of sequential code where each step in the sequence was hard-coded. It rolls 3 sequential LEDs "down" in sequence, then back "up" to the top as a cute little startup animation using the 33.3/45/78 RPM indicator LEDs in my Arduino-controlled record player :slight_smile:

It executes blindingly fast without the delay - in fact, it runs so fast you can't even see it run at all. With the delay in there the way it is now, it completes the whole animation in about 1 second.

  // startup animation
  unsigned int thisBlip = 1; // 1 to begin the loop
  byte fadeDirection = 1;
  while (thisBlip) {
    if (thisBlip > 0 && thisBlip <= 255) analogWrite(3, constrain(thisBlip-0,0,255));
    else if (thisBlip > 255 && thisBlip < 511) analogWrite(3, constrain(255-(thisBlip-255),0,255));
    if (thisBlip > 127 && thisBlip <= 383) analogWrite(5, constrain(thisBlip-128,0,255));
    else if (thisBlip > 383 && thisBlip < 638) analogWrite(5, constrain(255-(thisBlip-383),0,255));
    if (thisBlip > 255 && thisBlip <= 511) analogWrite(6, constrain(thisBlip-256,0,255));
    else if (thisBlip > 511 && thisBlip < 766) analogWrite(6, constrain(255-(thisBlip-511),0,255));
    if (fadeDirection) thisBlip++;
    else thisBlip--;
    if (thisBlip > 638) fadeDirection = 0; // you can adjust 638 to change the ending point, goes up to 766 to make the last LED fade completely out at the end before going back "up" and going back through the sequence to the top again. at 638 it reverses when the last LED is full brightness.
    delay(1);
  }
  digitalWrite(3,LOW);
  digitalWrite(5,LOW);
  digitalWrite(6,LOW);

Adapt the pin numbers (3, 5, 6) to your RGB pins, and adjust delay(1) to your desired "rate", and it very well should cycle though the RGB pins very smoothly :slight_smile:

Fast reply, Thanks, will have a go with that now. wow ,Is that the complete code, very short, nice!

Im getting an error " expected unqualified Id before "while" but its probably me doing something stupid.

Strange, compiles OK for me. Maybe you have something above/below the block that's messed up? Or did you change something in it?

Yes its probably me, Im really only just learning to code, last code i learned was BASIC years and years ago. I just pasted yours into new sketch but i changed pins to 9,10,11 .

When i took on this project I thought I would find some ready made code that would be very close to what I wanted but seems I can only find single colour breathing/throbbing code, and none seem easy to modify to RGB.

Basically im looking for a standard 7 colour RGB fade but with more of a gap between the colours (after the fade out), I know there must be hundreds of ways to code this effect but not sure which to take, maybe to have a "Black" (Red=0 Green=0 Blue=0) colour in between each colour fade would be a good way but I dont know enough to achieve this in code, yet, but I'm learning.

Well, since it fades through-then-back-through, it will exit the loop and turn all the colors off at the end of the loop (digitalWrite(x,LOW);). If you're doing that in a loop, you can just add a "delay(1000);" to add a 1 second "off" period at the end of each sequence. If you want to pause after each color transition, that may get a little more complicated... but you should be able to set a "if (thisBlip == XX) delay(1000);" conditional (equal, only fires once per cycle) in the loop to catch when each color is fully "on", and pause it there for a second.

Still curious about that compile error. Did you get that resolved? If not, can you post the whole thing you've got in the program?

edit: ooh, 7 colors, that's a little more complex, it'd have to fade through each color combination instead of just going 1->2, 2, 2->3, 3 (3 colors, I think). You can probably just dick with the numbers and expand the sequence with more combinations, like having two analogWrite() with the same calculated value, for those colors that need both red and green (pink), or blue and green (cyan), or red/green (yellow), for example...

well as im such a noob i literally just pasted your code into a new blank sketch and changed the pin numbers to my pins on my mega, im really only at the copy and paste stage with my coding!
Im trying to figure out how to combine it with the colour fading code but im so far off being capable yet!

Edit: even 3 colours would do at this stage as im losing hope.

BTW: thanks for all the help

Even A hardcoded version on a loop would do me as this does not need to be dynamic , just dont know where to start.

Any idea how I would modify this to dim more in between colours as its almost what i want just not enough "breathing"

int RED = 5;    // RED pin of the LED to PWM pin 9 
int GREEN = 6;  // GREEN pin of the LED to PWM pin 10 
int BLUE = 7;   // BLUE pin of the LED to PWM pin 11 

int DELAY_TIME = 15;  //changes speed of fading 
int MAX_BRIGHT = 255; //sets maximum brightness, 255 max brightness 
int COLOR_MIX = 0; //variable to change the colors that are mixed in switch statement 

void fade_in(int x) //loop that gradually turns the LED on using PWM 
{ 
    int counter; 
    
    for(counter = 0; counter < x; counter++) 
    { 
        led_mixer(COLOR_MIX, counter); 
        delay(DELAY_TIME); 
    } 
} 

void fade_out(int x) //loop that gradually turns the LED off using PWM 
{ 
    int counter; 
    
    for(counter = x; counter > 0; counter--) 
    { 
        led_mixer(COLOR_MIX, counter); 
        delay(DELAY_TIME); 
    } 
} 

void led_mixer(int color, int x) //uses switch statement to mix color combinations 
{ 
    switch(color) 
    { 
      case 0: 
        analogWrite(RED, x); 
        break; 
      case 1: 
        analogWrite(GREEN, x); 
        break; 
      case 2: 
        analogWrite(BLUE, x); 
        break; 
      case 3: 
        analogWrite(BLUE, x); 
        analogWrite(GREEN, x); 
        break; 
      case 4: 
        analogWrite(RED, x); 
        analogWrite(BLUE, x); 
        break; 
      case 5: 
        analogWrite(RED, x); 
        analogWrite(GREEN, x); 
        break; 
      default: 
        analogWrite(GREEN, x); 
        analogWrite(BLUE, x); 
        analogWrite(RED, x); 
      break; 
    } 
} 

void setup() 
{ 
  // nothing for setup 
} 

void loop() //loop forever 
{ 
  fade_in(MAX_BRIGHT); //gradually turn the LED on to max brightness 
  fade_out(MAX_BRIGHT); //gradually turn off the LED 
  COLOR_MIX++; //increment to the next color combination 
  
  if(COLOR_MIX == 7) //if all color combinations have been displayed, reset the cycle 
  { 
    COLOR_MIX = 0; 
  } 
}

All Arduino sketches have two parts: setup() and loop() at a minimum.

setup() runs only once at the start, when you first plug it in or reset it. It does just what it says: it "sets up" things that are used in the loop.

loop() runs continuously, around and around, until you unplug it.

So in your case...

void setup() {
  pinMode(9,OUTPUT); // set up LEDs as outputs.
  pinMode(10,OUTPUT);
  pinMode(11,OUTPUT);
}
void loop() {
 // startup animation
  unsigned int thisBlip = 1; // 1 to begin the loop
  byte fadeDirection = 1;
  while (thisBlip) {
    if (thisBlip > 0 && thisBlip <= 255) analogWrite(3, constrain(thisBlip-0,0,255));
    else if (thisBlip > 255 && thisBlip < 511) analogWrite(3, constrain(255-(thisBlip-255),0,255));
    if (thisBlip > 127 && thisBlip <= 383) analogWrite(5, constrain(thisBlip-128,0,255));
    else if (thisBlip > 383 && thisBlip < 638) analogWrite(5, constrain(255-(thisBlip-383),0,255));
    if (thisBlip > 255 && thisBlip <= 511) analogWrite(6, constrain(thisBlip-256,0,255));
    else if (thisBlip > 511 && thisBlip < 766) analogWrite(6, constrain(255-(thisBlip-511),0,255));
    if (fadeDirection) thisBlip++;
    else thisBlip--;
    if (thisBlip > 766) {
      delay(1000); // hold 1 second at one end of the sequence
      fadeDirection = 0; // you can adjust 638 to change the ending point, goes up to 766 to make the last LED fade completely out at the end before going back "up" and going back through the sequence to the top again. at 638 it reverses when the last LED is full brightness.
    }
    delay(1);
  }
  digitalWrite(3,LOW);
  digitalWrite(5,LOW);
  digitalWrite(6,LOW);
  delay(1000); // hold 1 second at the beginning of the sequence before looping
}

Ok, nice one, thanks, that has helped alot, ive modded it too this now

void setup() {
  pinMode(9,OUTPUT); // set up LEDs as outputs.
  pinMode(10,OUTPUT);
  pinMode(11,OUTPUT);
}
void loop() {
 // startup animation
  unsigned int thisBlip = 1; // 1 to begin the loop
  byte fadeDirection = 1;
  while (thisBlip) {
    if (thisBlip > 0 && thisBlip <= 255) analogWrite(9, constrain(thisBlip-0,0,255));
    else if (thisBlip > 255 && thisBlip < 511) analogWrite(9, constrain(255-(thisBlip-255),0,255));
    if (thisBlip > 127 && thisBlip <= 383) analogWrite(10, constrain(thisBlip-128,0,255));
    else if (thisBlip > 383 && thisBlip < 638) analogWrite(10, constrain(255-(thisBlip-383),0,255));
    if (thisBlip > 255 && thisBlip <= 511) analogWrite(11, constrain(thisBlip-256,0,255));
    else if (thisBlip > 511 && thisBlip < 766) analogWrite(11, constrain(255-(thisBlip-511),0,255));
    if (fadeDirection) thisBlip++;
    else thisBlip--;
    if (thisBlip > 766) {
      delay(1000); // hold 1 second at one end of the sequence
      fadeDirection = 0; // you can adjust 638 to change the ending point, goes up to 766 to make the last LED fade completely out at the end before going back "up" and going back through the sequence to the top again. at 638 it reverses when the last LED is full brightness.
    }
    delay(1);
  }


  digitalWrite(9,LOW);
  digitalWrite(10,LOW);
  digitalWrite(11,LOW);
  delay(1000); // hold 1 second at the beginning of the sequence before looping
}

Its looking good but i need to invert it as its fading back to full on white between colours, My led strip must be wired the other way

Whoops! Good catch, I forgot to change the analogWrite's to 9/10/11. Unfortunately I don't have an RGB LED to play with, so I really don't know what else to change... I wouldn't think it would be going full on white between colors, since only up to two are supposed to be on at a time. Maybe you've got negative logic on the pins (ground controlling each pin), so LOW would be on. Hmm... I'll play around with the code and see if I can make it work in reverse...

Thanks, yes my led strips are common anode, yours must have been common cathode. cheers . even just seeing your code has helped alot, i must do more research :slight_smile:

Alright, I flipped around the inversions in the if/else conditions, now it inverts going up instead of down :slight_smile:

void setup() {
  pinMode(9,OUTPUT); // set up LEDs as outputs.
  pinMode(10,OUTPUT);
  pinMode(11,OUTPUT);
}
void loop() {
  // startup animation
  digitalWrite(9,HIGH);
  digitalWrite(10,HIGH);
  digitalWrite(11,HIGH);
  unsigned int thisBlip = 1; // 1 to begin the loop
  byte fadeDirection = 1;
  while (thisBlip) {
    if (thisBlip > 0 && thisBlip <= 255) analogWrite(9, constrain(255-thisBlip,0,255));
    else if (thisBlip > 255 && thisBlip < 511) analogWrite(9, constrain(thisBlip-255,0,255));
    if (thisBlip > 127 && thisBlip <= 383) analogWrite(10, constrain(255-(thisBlip-128),0,255));
    else if (thisBlip > 383 && thisBlip < 638) analogWrite(10, constrain(thisBlip-383,0,255));
    if (thisBlip > 255 && thisBlip <= 511) analogWrite(11, constrain(255-(thisBlip-256),0,255));
    else if (thisBlip > 511 && thisBlip < 766) analogWrite(11, constrain(thisBlip-511,0,255));
    if (fadeDirection) thisBlip++;
    else thisBlip--;
    if (thisBlip > 766) {
      delay(1000); // hold 1 second at one end of the sequence
      fadeDirection = 0; // you can adjust 638 to change the ending point, goes up to 766 to make the last LED fade completely out at the end before going back "up" and going back through the sequence to the top again. at 638 it reverses when the last LED is full brightness.
    }
    delay(1);
  }
  digitalWrite(9,HIGH);
  digitalWrite(10,HIGH);
  digitalWrite(11,HIGH);
  delay(1000); // hold 1 second at the beginning of the sequence before looping
}

Brilliant, That is working perfect, nice one, youve made things so much easier! Thanks a mill :smiley:

Sweet! And you can make it pause on each color step using the values in the "if" statements, for example:

if (thisBlip == 127) delay(500);
if (thisBlip == 255) delay(500);
if (thisBlip == 383) delay(500);
if (thisBlip == 511) delay(500);
if (thisBlip == 638) delay(500);

... inside the while() loop, and it'll pause 1/2 second on each mid-step transition, probably making it even cooler to watch :wink:

Now I want an RGB LED of my own! LOL...

Well if your looking for RGB LEDs in a strip the 5050 SMD led strips are really cool, can get 5mtr waterproof one for about $40, they can be cut every 9cm , thats what im using , also using some simpler strips without controllers with the arduino instead.

Ya those extra delays look cool, :slight_smile:

Oh my GOD, those LEDs look flippin' incredible!! I watched "Animusic" a while back and watched a sequence where some big electronic "brain" was sending out "pulses" and "streams" of light through tubes or wires to different instruments to make a tune (when the stream/pulse hit it, it made a sound, but you watched the pulse/stream move along the tube to it). These would be AMAZING for creating a similar effect without CG... I mean, the possibilities there are just "wow".

Yep, you're definitely on the track to making some cool stuff with that. :smiley:

Cheers, ya the 5050 strips are the buisness. I must check out that Animusic, sounds interesting. The effect i have now with your code i actually more than i had hoped for as it cycles through the colours on each breath, not just limited to one colour per breath.

Also There is another part to this RGB LED system that I would like to combine into same code so it can all be run from one arduino if possible:

The other system is basically a RGB strip with 3 linear potentiometers controlling PWM, one controlling each colour. Now I have found some code that does what I want but Im not sure how to combine 2 different programs without the delays/loops in one program interfering with the other program. I suppose it would mean coding without delays, It might be easier to just buy 2 arduinos as they are relatively cheap. Here is the code i found:

1. 
2.// Init the Pins used for PWM
3.const int redPin = 9;
4.const int greenPin = 10;
5.const int bluePin = 11;
6. 
7.// Init the Pins used for 10K pots
8.const int redPotPin = 0;
9.const int greenPotPin = 1;
10.const int bluePotPin = 2;
11. 
12.// Init our Vars
13.int currentColorValueRed;
14.int currentColorValueGreen;
15.int currentColorValueBlue;
16. 
17.void setup()
18.{
19.  pinMode(redPin, OUTPUT);
20.  pinMode(greenPin, OUTPUT);
21.  pinMode(bluePin, OUTPUT);
22.}
23. 
24.void loop()
25.{
26.// Read the voltage on each analog pin then scale down to 0-255 and inverting the value for common anode
27.  currentColorValueRed = (255 - (analogRead(redPotPin) / 4)); 
28.  currentColorValueBlue = (255 - (analogRead(bluePotPin) / 4));
29.  currentColorValueGreen = (255 - (analogRead(greenPotPin) / 4));
30. 
31.// Write the color to each pin using PWM and the value gathered above
32.  analogWrite(redPin, currentColorValueRed);
33.  analogWrite(bluePin, currentColorValueBlue);
34.  analogWrite(greenPin, currentColorValueGreen);
35. 
36.}
37.

BTW : If anyone else has any ideas for coding the RGB throb/breathing effect I would be interested in hearing them, as im learning all the while.

While FalconFours code for the breathing effect is cool its not quite what my friend wanted for his kaleidoscopes as it cycles through the colours during each "breath", hes was looking specifically for one colour per "breath",

So for example
red fades in , then fades out but as it gets to 10% then the blue and red start fading in together (purple),then they fade out together but as they get to 10% then the blue starts ramping up on its own, then it fades out and as it gets to 10% the green starts to fade in ...etc. . even just 3 or 5 colours would do.

Hardcoded 7 colour with an changeable delay would be cool, Im just not sure where to start as I havnt the skill to start a program from scratch. Obviously if i could have each seperate "breath" move slowly along the LED strip that would be a really amazing effect but that would require shift registers or god knows what so im just trying to get a simpler version running for now!