3 LED 'Float' fade/pulse overlapping help.

Hi all, I searched around and tried to find some way to accomplish this with just the PWM outputs and LEDs rather than any sort of ribbon or external prefab LED setup. There isnt a need for mathematically acurate rates, this is purely for an aesthetic project.

I’m looking to have 3 LEDs pulsing/fading at different rates, but overlapping (parallel) rather than sequentially (series).

LED1 |-------_____|
LED1 |
------|
LED1 |-----__|

Not exactly like that, but I think it portays it somewhat more than just in words.

My code is outputting it more like this:
LED1 |-------_____| LED1 |------|LED1 |-----__|

I’m currently trying this using ‘float’ and sin fucntions that I found on this tutorial.
(Pulse a LED - SparkFun Electronics)

Any ideas/help would be greatly appreciated.

Code:

const int LED1 = 3; 
const int LED2 = 5; 
const int LED3 = 6; 

void setup()
{
}

void loop()
{
/*LED 1 */ 
  float in1, out1;
  
  for (in1 = 0; in1 < 6.283; in1 = in1 + 0.0009)
  {
    out1 = sin(in1) * 127.5 + 127.5;
    analogWrite(LED1,out1);
  }
/*LED 2 */ 
  float in2, out2;
  
  for (in2 = 0; in2 < 6.283; in2 = in2 + 0.0008)
  {
    out2 = sin(in2) * 127.5 + 127.5;
    analogWrite(LED2,out2);
  }
/*LED 3 */  
  float in3, out3;
  
  for (in3 = 0; in3 < 6.283; in3 = in3 + 0.0007)    
  {  
    out3 = sin(in3) * 127.5 + 127.5;
    analogWrite(LED3,out3);
  }
  
}

You need to implement a state machine. This means replacing those for loops with an increment that you can call once and then it returns instead of hogging all the time for each LED in turn. See my http://www.thebox.myzen.co.uk/Tutorial/State_Machine.html Or Robin2's several things at once http://forum.arduino.cc/index.php?topic=223286.0

There are lots of ways of doing this sort of thing. One way is to pre-compute the sine table, and to then use a phase accumulator (good Google search term there) to step through the table.

Thank you Grumpy_Mike and AWOL, I'll look into and try these out!

Unfortunately, the state machine does not seem to function with a sine output, and the phase accumulator is a tremendous amount that I don’t quite understand or see how it works with what I am trying to do.

I’ve tried moving things around a lot, and no matter what, it’s just constant on.

I like the idea of using the void function to call the task, but I can’t figure out how to just use an if/then statement to trigger the sine output.

Does anyone have any other ideas?

Below is a simplified version that I attempted with using the state machine with just 1 LED to output/pulse.

const int LED1 = 3; 

int nextTime = 500;  // Do this every second or 500 milliseconds
long int goTime;


void setup()
{
goTime = millis();
}

void loop()
{

/*LED 1 */    
  if(millis() >= goTime) functionGo();



}

void functionGo()
{
  float in, out;
    for (in = 0; in < 6.283; in = in + 0.0001)
    out = sin(in) * 127.5 + 127.5;
    analogWrite(LED1,out);
    goTime = millis() + nextTime;
}

You need to get rid of the “for” loop, and handle the incements explicitly

This is your code, as I read it

void functionGo()
{
  float in, out;
    for (in = 0; in < 6.283; in = in + 0.0001)
    {
       out = sin(in) * 127.5 + 127.5;
    }
    analogWrite(LED1,out);
    goTime = millis() + nextTime;
}

Do you see the problem?

Unfortunately, the state machine does not seem to function with a sine output,

Yes it does!

It is you that is failing to understand the state machine concept.

The function should just output the next sample, change the time when it is called again and then exit. Do not use loops inside the function.

Programming it like this means you can out put as many waveforms as you can, outputting one sample at a time for each waveform.

You can also try some hardcoding to get rid of the calculations.

I think this will do exactly what you want. I use it to drive the RGB LEDs on my Nixie project. Several options are available including random cycling of all three colors.

Colors don't appear to mix well using the 5mm RGB LEDs commonly available. I prefer sequentially cycling all three colors for a more pleasing effect.

https://github.com/jgillick/arduino-LEDFader

Colors don't appear to mix well using the 5mm RGB LEDs commonly available

Try light sandpaper on the LED to make more of a diffuser. Some people dip them in solvent for the same effect.

You can always use a diffuser like a 0.5mm sheet of styrene or even paper.

MitchSF: I think this will do exactly what you want.

This is [u]exactly[/u] what I want, and there is plenty to tinker with. : ] Thank you so much!

Happy to help.

Here is the function I use to interface with the library. It’s part of a much larger program and will need some changes.

/////////////////////////////////////////////////////////////////
// LED
/////////////////////////////////////////////////////////////////

void led(int ledBright, int ledMode) {

  int ledBr = 26 * ledBright;
  if (ledBr == 26) ledBr = 2; // correct for lowest setting
  static int lastMode = -1;

  if (ledMode == lastMode && ledMode != 0 && ledMode > 5) return; // run once for static modes
  lastMode = ledMode;

  switch (ledMode) {

    case 0: { // all off
        analogWrite(redRGB, LOW);
        analogWrite(greenRGB, LOW);
        analogWrite(blueRGB, LOW);
      }
      break;
    case 1:  { // RGB Cycle
        static byte j = 0;
        LEDFader *led = &leds[j];
        ledBr = ledBr + rgbCorrect[j];
        led->update();
        if (led->is_fading() == false) { // Set new fade
          if (led->get_value() == 0) { // Up
            j++;
            if (j == 3) j = 0;
            LEDFader *led = &leds[j];

            led->fade(ledBr, ledCycle);
          }
          else {
            led->fade(0, ledCycle); // Down
          }
        }
        break;
      }

    case 2: { // Mix Cycle
        for (byte i = 0; i < 3; i++) {
          LEDFader *led = &leds[i];
          led->update();
          if (led->is_fading() == false) { // Set new fade
            int rndCycle = random(1000, 3000); // between 1 - 3 seconds
            if (led->get_value() == 0) { // Up
              byte ledBr = random(100, 240) + rgbCorrect[i];
              led->fade(ledBr, rndCycle);
            }
            else led->fade(0, rndCycle); // Down
          }
        }
        break;
      }

    case 3: { // red cycle
        analogWrite(greenRGB, LOW);
        analogWrite(blueRGB, LOW);
        ledBr = ledBr + rgbCorrect[0];
        LEDFader *led = &leds[0];
        led->update();
        if (led->is_fading() == false) { // Set new fade
          if (led->get_value() == 0) { // Up
            led->fade(ledBr, ledCycle);
          }
          else led->fade(0, ledCycle); // Down
        }
        break;
      }

    case 4: { // green cycle
        analogWrite(redRGB, LOW);
        analogWrite(blueRGB, LOW);
        ledBr = ledBr + rgbCorrect[1];
        LEDFader *led = &leds[1];
        led->update();
        if (led->is_fading() == false) { // Set new fade
          if (led->get_value() == 0) { // Up
            led->fade(ledBr, ledCycle);
          }
          else led->fade(0, ledCycle); // Down
        }
        break;
      }

    case 5: { // blue cycle
        analogWrite(redRGB, LOW);
        analogWrite(greenRGB, LOW);
        ledBr = ledBr + rgbCorrect[2];
        LEDFader *led = &leds[2];
        led->update();
        if (led->is_fading() == false) { // Set new fade
          if (led->get_value() == 0) { // Up
            led->fade(ledBr, ledCycle);
          }
          else led->fade(0, ledCycle); // Down
        }
        break;
      }

    case 6: { // static red
        ledBr = ledBr + rgbCorrect[0];
        analogWrite(redRGB, ledBr);
        analogWrite(greenRGB, 0);
        analogWrite(blueRGB, 0);
      }
      break;
    case 7: { // static green
        ledBr = ledBr + rgbCorrect[1];
        analogWrite(redRGB, 0);
        analogWrite(greenRGB, ledBr);
        analogWrite(blueRGB, 0);
      }
      break;
    case 8: { // static blue
        ledBr = ledBr + rgbCorrect[2];
        analogWrite(redRGB, 0);
        analogWrite(greenRGB, 0);
        analogWrite(blueRGB, ledBr);
      }
      break;
  }
}