Millis() not working to stop process

I've looked through many posts and discussion on this particular topic and have come up lacking.

Code in question:

void theaterChaseRainbow(int cycles, int speed, unsigned long duration){ // TODO direction, duration
  duration = 10000L;
  unsigned long start = millis();
  
  for (int j=0; j < 256 * cycles; j++) {     // cycle all 256 colors in the wheel

    for (int q=0; q < 3; q++) {
      for (int i=0; i < NUM_LEDS; i=i+3) {
        int pos = i+q;
        leds[pos] = Wheel( (i+j) % 255);    //turn every third pixel on
      }
      FastLED.show();

      delay(speed);

      for (int i=0; i < NUM_LEDS; i=i+3) {
        leds[i+q] = CRGB::Black;  //turn every third pixel off
      }
    }
    unsigned long current = millis();
    unsigned long delta = current-start;
    
    if(delta > duration) {
      return;
    }
  }
}

No matter what I do the millis seems to be clocking wait to fast, i.e. I set the delay to 10000ms and it is done in a something like 1000ms

If I chose to print out millis(), i.e. I add the line

mySerial.println(millis())

everything slows down nicely.

if I do something like:

mySerial.println(delta);

I get a single rather oddly long value something like 4294963562

Why is millis behaving like this? Enquiring minds want to know.

A code snippet will not suffice.

How big can "cycles" get?

Yeah that shouldn’t happen. This sounds awfully like something is wrong elsewhere.

Are you sure you aren’t overrunning your LED array?

So we need to see all the code OR a small example you have created from your code, a complete program that compiles, runs and exhibits the same undesirable behaviour.

Also, fastLED will have an impact on millis() timing. Probably not an issue, but you should google it to see how they get along.

a7

If NUM_LEDS is not a multiple of 3, your code will write outside of the leds array, this is called buffer overflow and will cause all sorts of strange behaviors or even crash your program. Always make sure an array index is never greater than the array size - 1.

That is an interesting note for sure, I hadn't considered that, it definitly isn't a multiple of 3, I could be banging into other parts of memory that are causing issues.

It is an int, but I'm generally keeping it at 1 or 2.

And always greater than or equal to zero…

If you have assignments to you led array all over the place, you could replace them all with a function call, a function which takes pixel number and color as arguments.

Isolating to one place where you could do all the bounds checking you need.

Either ignore or complain about attempts to write outside your array that come through this one function.

a7

#include <FastLED.h>
#include <SoftwareSerial.h>


#define NUM_LEDS 54 // Fifty leds(to make the marquee effect not overrun memory.
#define FORWARD 0   // Binary directions
#define BACKWARD 1
#define SLOW 250    // Some speed values
#define MEDIUM 50
#define FAST 5

#define DATA_PIN 3 // Pixle PIN

CRGB leds[NUM_LEDS];
SoftwareSerial mySerial(10, 11); // Connect BT


boolean direction = FORWARD;

void setup() {
  mySerial.begin(38400); //BT interface
  Serial.begin(9600);     // Local serial
  Serial.println("Starting...");  
  
}

void loop() {
  
  int cnt;
  char result;
  unsigned int d1, d2, d3;
 
  //Setup FastLED
  //Make it Orange
    FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS);
    for(int i = 0; i<NUM_LEDS; i++) {
        leds[i].r = 250;
        leds[i].g = 118;
        leds[i].b = 5;
 
      }
      FastLED.show();
  //Setup an infinite loop inside of Loop.. why? I don't know
  // I copied this from the internets and didn't clean it up yet.
  for(;;) {
    
    //Wait for something to show up on the serial port
    while(!mySerial.available());

    result = (char)mySerial.read(); //Get character off the fifo
    Serial.println(result); //debug code
    Serial.println("-");

    //RED!!!
    if(result == 'r') {
      Serial.println(":r");
      for(int i = 0; i<NUM_LEDS; i++) {
        leds[i].r = 255;
        leds[i].g = 0;
        leds[i].b = 0;
      }
    }
    //GREEN!
    if(result == 'g') {
      Serial.println(":g");
      for(int i = 0; i<NUM_LEDS; i++) {
        leds[i].r = 0;
        leds[i].g = 255;
        leds[i].b = 0;
 
      }
    }
    //BLUE
    if(result == 'b') {
      Serial.println(":b");
      for(int i = 0; i<NUM_LEDS; i++) {
        leds[i].r = 0;
        leds[i].g = 0;
        leds[i].b = 255;
      }
    }
    
    //Wipe!
    if(result == 'a') {
      mySerial.println("Wipe!"); //Let the sender know what they did.
      colorWipe(randomColor(),50, direction);
      direction = !direction;
    }

    //Chaser
    if(result == 't') {
      mySerial.println("Theatre Chase Rainbow"); //Let the sender know what they did.
      theaterChaseRainbow(1,MEDIUM,10000);
    }
    
   
    
    //Actually make the lights go.
    FastLED.show();
    
    }
}

//Stuff I copied from github somewhere
void colorWipe(CRGB c, int speed, int direction){
  for(int i=0; i<NUM_LEDS; i++){
    if(direction == FORWARD){
      leds[i] = c;
    }
    else{
      leds[NUM_LEDS-1-i] = c;
    }
    FastLED.show();
    delay(speed);
  }
}
CRGB Wheel(byte WheelPos) {
  if(WheelPos < 85) {
    return CRGB(WheelPos * 3, 255 - WheelPos * 3, 0);
  } 
  else if(WheelPos < 170) {
    WheelPos -= 85;
    return CRGB(255 - WheelPos * 3, 0, WheelPos * 3);
  } 
  else {
    WheelPos -= 170;
    return CRGB(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}
CRGB randomColor(){
  return Wheel(random(256)); 
}

void theaterChaseRainbow(int cycles, int speed, unsigned long duration){ // TODO direction, duration
  duration = 10000L;
  unsigned long start = millis();
  
  for (int j=0; j < 256 * cycles; j++) {     // cycle all 256 colors in the wheel

    for (int q=0; q < 3; q++) {
      for (int i=0; i < NUM_LEDS; i=i+3) {
        int pos = i+q;
        leds[pos] = Wheel( (i+j) % 255);    //turn every third pixel on
      }
      FastLED.show();

      delay(speed);

      for (int i=0; i < NUM_LEDS; i=i+3) {
        leds[i+q] = CRGB::Black;  //turn every third pixel off
      }
    }
    unsigned long current = millis();
    unsigned long delta = current-start;
    mySerial.println(delta);
    if(delta > duration) {
      return;
    }
  }
}

Good idea. This is mostly an attempt to put together some fun effects that can be controlled by bluetooth for my kids holloween costume.

You are getting a lot of random guesses because you have only shared a snippet of your code. You need to write a complete working example of your code that presents the problem. It is not millis(), it is not delay(unsigned long) and it is not writing to memory past your array. You can remark out the for(int i=0) loop to check that... but, you pass 3 parameters to the function, which are unknown to us on the forum. You reference additional globals, including the array, and class member functions that are not presented to the forum. It was said before, and I just said it, but you need to present more code, and you can simplify your code the the example as well.

Put this code in setup() and lose the nested infinite loop in loop()

The removal of the loop seems to have done it.
I'm guessing that the increment of millis requires the system to hit the outside of the loop.

No, that is not true. millis() will increment in the background through interrupts.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.