for loop without delay?

hello everyone, so im currently working on a project where i have a bunch of for loops and i need to switch between them when a button is pushed. i have most of the code fiqured out, but what i cant get is to get the for loop to be non blocking, and thats because of the delay() used, how can i get the for loop to be non blocking?

here are my for loops

 if (warning_state == HIGH)
  {
    for (int i = 0; i <= 7; i++) {
        digitalWrite(ledPins[i], LOW); // turns all lights off
      }
    //center 2 on outer 3 flash with center of 3 on.
    for (int i = 0; i <= 7; i++) {
      // digitalWrite(ledPins[i], LOW);
      for (int j = 0; j <= 5; j++) {
        digitalWrite(ledPins[1], LOW);
        digitalWrite(ledPins[6], LOW);
        digitalWrite(ledPinscustom[j], HIGH);
      }
      delay(150);
      for (int k = 0; k <= 5; k++) {
        digitalWrite(ledPins[0], LOW);
        digitalWrite(ledPins[7], LOW);
        digitalWrite(ledPinscustom2[k], HIGH);
      }
      delay(150);
    } //end for loop

    //Turns off all leds
    for (int i = 0; i <= 7; i++) {
      digitalWrite(ledPins[i], LOW);
    }
    delay(150);// end for loop

    //strobe, out to in, with 1 each side lit.
    for (int i = 0; i <= 4; i++) {
      for (int i = 0; i <= 3; i++) {
        digitalWrite(ledPins[i], HIGH);
        digitalWrite(ledPins[7 - i], HIGH);
        delay(50);
        digitalWrite(ledPins[i], LOW);
        digitalWrite(ledPins[7 - i], LOW);
        delay(50);
      }
    }//end for loop

    //Turns off all leds
    for (int i = 0; i <= 7; i++) {
      digitalWrite(ledPins[i], LOW);
    }
    delay(150);// end for loop

    //half and half fast
    for (int i = 0; i <= 5; i++) {
      for (int i = 0; i <= 4; i++) {
        digitalWrite(ledPins[i], HIGH);
      }
      for (int i = 4; i <= 7; i++) {
        digitalWrite(ledPins[i], LOW);
      }
      delay(200);
      for (int i = 0; i <= 4; i++) {
        digitalWrite(ledPins[i], LOW);
      }
      for (int i = 4; i <= 7; i++) {
        digitalWrite(ledPins[i], HIGH);
      }
      delay(200);
    }//end for loop

    //Turns off all leds
    for (int i = 0; i <= 7; i++) {
      digitalWrite(ledPins[i], LOW); //Turns on LED #i each time this runs
    }
    delay(200);// end for loop

    //LEDs strobe, center out, 1 each side lit.
    for (int i = 0; i <= 4; i++) {
      for (int i = 4; i >= 0; i--) {
        digitalWrite(ledPins[i ], HIGH); //Turns on LED #i each time this runs
        digitalWrite(ledPins[7 - i], HIGH); //Turns on LED #i each time this runs
        delay(50);
        digitalWrite(ledPins[i ], LOW); //Turns on LED #i each time this runs
        digitalWrite(ledPins[7 - i], LOW); //Turns on LED #i each time this runs
        delay(50);
      }
    } //end for loop
  }
  warning_last = warning_current;

  if (left_state == HIGH)
  {
    for (int i = 0; i <= 7; i++) {
        digitalWrite(ledPins[i], LOW); // turns all lights off
      }
    //slow arrow right to left
    for (int i = 0; i <= 7; i++) {
      digitalWrite(ledPins[i], HIGH);
      delay(500);
    }
  }
  left_last = left_current;

  if (center_state == HIGH)
  {
    for (int i = 0; i <= 7; i++) {
        digitalWrite(ledPins[i], LOW); // turns all lights off
      }
    //center out
    for (int i = 3; i >= 0; i--) {
      digitalWrite(ledPins[i], HIGH); //Turns on LED #i each time this runs
      digitalWrite(ledPins[7 - i], HIGH); //Turns on LED #i each time this runs
      delay(500);
    }
  }
  center_last = center_current;

  if (right_state == HIGH)
  {
    for (int i = 0; i <= 7; i++) {
        digitalWrite(ledPins[i], LOW); // turns all lights off
      }
    //slow arrow left to right
    for (int i = 7; i >= 0; i--) {
      digitalWrite(ledPins[i], HIGH);
      delay(500);
    }
    for (int i = 0; i <= 7; i++) {
      digitalWrite(ledPins[i], LOW); // turns all lights off
    }
  }
  right_last = right_current;
}

but what i cant get is to get the for loop to be non blocking

You never will. The for loop is going to iterate some number of times. That, by its very nature, is blocking code.

The loop() function already loops. On any given pass, it might do something, or it might not.

That something might be to increment an index value, and do something with it, if the time is right.

This has been discussed pretty extensively here: https://forum.arduino.cc/index.php?topic=500272.0

gfvalvo, that was my origional post for this problem, they have helped me with all of my other problems, but no working answer was given for this problem.

pauls, what would be the best way to replace these for loops then?

Manage a state-machine. Have loop() call a single function for each state machine to progress it. Thus all the things with state get to run in pseudo-parallel and each can respond to external events and timeouts without being blocked by the others.

d.raymond: gfvalvo, that was my origional post for this problem,

Please click Report to Moderator and ask to have your two Threads merged so we don't waste time and duplicate ourselves.

...R

i am a C# guy, i may steer you wrong, and i am making assumptions here, i assume you want the loops to break when a button is pushed, so you can begin another loop in response to that button push ?

If this is the case, if i were using c# i would do something like this.

for(int i =0;i<150;i++)
{
if(button*.JustPressed())*

  • break;*
    _ if(button*.JustReleased())_
    _
    break;_
    _
    // Do the rest of my loop work here*_
    }
    If i completely misunderstood your question, then i blame obama.

dcosper: If this is the case, if i were using c# i would do something like this.

IMHO it would be much better not to use FOR in the first place. Just allow loop() to do the iterations. Then there will be no loop from which a break-out is required.

...R

Unsure what you mean by not using for in the main loop, it is a very common practice.

it is a very common practice.

For people who don't mind it's blocking nature.

so the question again is how do i keep my patterns but make them non blocking? without using for loops?

PaulS:
For people who don’t mind it’s blocking nature.

True, however it is very easy to exit for and while loops, as well as skip items you do not want to process, i understand this may not be the optimal way but seeing as how the op is asking questions about it, i would assume he has yet to learn an optimal way, so i would suggest using break and continue in your loops when and if an action is performed outside your loop

for(int i = 0;i<1000;i++)
{
if(mybutton.wasPushed())
break; // stop this loop

if(currentItem.isBad)
continue; // skip this item
}

I would think this would be the answer to the OP’s question, however, a state machine would be preferable, i myself am writing a screen state machine, or learning too i am a c# guy

so what yall are saying is i should put an if statement before my delay to see if another button has been pushed then break the loop or continue?

The correct way to do what you are asking about is a State Machine

Arudino Discussion State Machine

However to answer your immediate question in your for loops

for(int i = 0;i<1000;i++)
{
if(someActionIsPerformedDuringThisLoop)
{
// do the functions you want to do inside here
// if you want to turn all led’s off do it now

break; // now break out of this for loop and begin the code block directly under us
}
}

every time i try something it makes my code completely quit working.

If you bothered looking at your old thread here:http://forum.arduino.cc/index.php?topic=500272.0 you would find your program is already written for you.

dcosper:
Unsure what you mean by not using for in the main loop, it is a very common practice.

Not when you need to jump out of the FOR

…R

In general - to turn blocking code with delays into non-blocking code, each point where a delay() appears becomes a state in a state machine.

Since you have delays inside loops, those loop variables have to become static in order to persist between invocations of loop. Easiest way to do this is to make 'em global.

One way to do this - horrifying as it may be - is to use a load of gotos;

Each

void loop() {
...
    for (int i = 7; i >= 0; i--) {
      digitalWrite(ledPins[i], HIGH);
      delay(500);
    }
...
}

becomes:

enum DelayState {
  NONE, point1, point2, point3, // etc ...
} delayState = NONE;

int i;
uint32_t delayMs;

void loop() {
  switch(delayState) {
    case NONE: break; // top of the loop
    case point1: goto delay1;
    case point2: goto delay2;
    // etc
  }

  
  ...
    for (i = 7; i >= 0; i--) {
      digitalWrite(ledPins[i], HIGH);
      delayMs = millis();
      delayState = point2;
      delay2:
      if(millis()-delayMs < 500) return;
    }
  ...

  delayState = NONE; //top of the loop
}

You can re-use the ‘i’ variable for all your loops: they aren’t running simultaneously.

I much prefer to use classes and state machines explicitly. Go see the url in my sig for a bit of a write-up that I did on how to do this. The thing is: it requires a bit of a re-think about how your code does what it does.

Protothreads might work for you. They basically do what @PaulMurrayCbr suggests but hide the state machinery behind macros.