0

I want to implement three effects which display every 5 seconds. I know that using delay() is not a good method so I want to use milis(). Duration times of the effects are different from each other. How can I assure "non-freezing" or displaying 2 or 3 effects at the same time? Should I measure the time of display of every effect and on its base adjust intervals or is there another solution? What do you think?

EDIT:

Here is my code:

void loop() {
   unsigned long currentMillis = millis();

   if(currentMillis - previousMillis >= interval) {
     previousMillis = currentMillis;
     i++;

    switch (i){
      case 1: 
        meteorRain(0xff,0xff,0xff,10, 64, true, 30); // efekt spadającej gwiazdy
        Serial.print("meteorrain: ");
        Serial.print(previousMillis);
        Serial.print("\n");
        break;

      case 2: 
         colorWipe(0x90,0x90,0x90, 50);
         colorWipe(0x00,0x00,0x00, 50);
         Serial.print("colorwipe: ");
        Serial.print(previousMillis);
        Serial.print("\n");
         break;

      case 3:
         MyEffect();   
         Serial.print("My effect: ");
        Serial.print(previousMillis);
        Serial.print("\n");
         break;
    }      
    if (i>3) i=0;
    }
}

I've ommited the code of effects (it doesn't matter, I think).

  • show us what you have tried so far, do you have some code working for one of the effect (or the 3 of them ?) so we can know what to expect ? also, if your 3 effects all trigger every 5 seconds, can't we call that one big effect with 3 different actions that triggers every 5 seconds ? – Neil Mar 10 at 10:14
  • Are these effects executed on different LED strips at the same time or sequentially on the same LED strip? – chrisl Mar 10 at 10:22
  • Sequentially on the same LED strip. – Marco Svizzeri Mar 10 at 11:17
  • So you don't want to have multiple effects at the same time, as you wrote in your question? Or do you divide the LED strip into different parts, which should display the corresponding effect simultaneously? I don't understand, what the end result should look like – chrisl Mar 10 at 11:41
  • If you intend to show every effect sequentially for a time interval (by looking on the code one can assume that) then, there is nothing wrong with the code, except the execution of an effect would last longer than the time interval. If that's not your intention, I do not understand your question for the same reasons @chrisl has mentioned. – Peter Paul Kiefer Mar 10 at 14:51
0

I'd take a look at Mark Kriegsmans FastLED example "DemoReel100". This example shows how to delegate to multiple functions.

First, I'll explain that example a bit: You set up an array of function pointers plus a variable for the current index.

typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = { rainbow, rainbowWithGlitter, confetti, sinelon, juggle, bpm };
uint8_t gCurrentPatternNumber = 0; 

All the functions (rainbow, juggle, etc) just need to work on your leds[] array that you gave to FastLED.addLeds() in your setup() -- I assume that your functions already fulfill that requirement. But: All functions must have the same argument list (in this case: they must be defined like void rainbow() { leds[x] = CHSV(a,b,c); }), so you might need to wrap them in another function.

Then, in your loop, you call your effect functions like this while calling nextPattern() every 10 seconds:

void loop()
{
  // Call the current pattern function once, updating the 'leds' array
  gPatterns[gCurrentPatternNumber]();

  // send the 'leds' array out to the actual LED strip
  FastLED.show();  
  // insert a delay to keep the framerate modest
  FastLED.delay(1000/FRAMES_PER_SECOND); 

  // do some periodic updates
  EVERY_N_SECONDS( 10 ) { nextPattern(); } // change patterns periodically
}

#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
void nextPattern()
{
  gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
}

EVERY_N_SECONDS is a macro defined in the FastLED library; it basically does what you did with currentMillis, previousMillis and interval (There's also EVERY_N_MILLISECONDS and some other related macros).

That's the example so far, now we need to work with differing "effect switch times".

The easiest method in code would be to find the greatest common factor of all switch times -- let's say you want the rainbow() effect to last for 10 seconds, the juggle() effect for 15 and the bpm() effect for 5 seconds. All those switch times are a multiple of 5, so we put that as the switch delay: EVERY_N_SECONDS(5). Now, to get higher runtimes, we just put those functions multiple times into the array:

SimplePatternList gPatterns = { rainbow, rainbow, juggle, juggle, juggle, bpm };

There's another way, which gives you the option of setting the effect durations directly. First, we need an array of durations of the same length than our effect function array and a variable to remember where we are in the durations:

SimplePatternList gPatterns = { rainbow, juggle, bpm };
int[] gPatternDurations = { 10, 13, 73 };
int effectDurationLeft = gPatternDurations[0];

Then, we reduce the "effect switch resolution" down to 1 second and put a bit of logic around the nextPattern() call:

  EVERY_N_SECONDS( 1 ) {
    if( effectDurationLeft == 0 ) {
      nextPattern();
      effectDurationLeft = gPatternDurations[gCurrentPatternNumber]; 
    } else {
      effectDurationLeft -= 1;
    }
  }

Now you could set your pattern durations by editing the gPatternDurations array.

Please be aware that I did not test the code above. Syntax Errors may occur :)

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.