Learn

The Arduino for loop, with eight LEDs to chase

Intermediate

Or see every lesson.

  • 455parts on the bench
  • 43boards running now
  • 1.00xreal time, on every board
Arduino Uno: an LED chaser on a 74HC595live0.000 s 0.00x
Click to open it in the editor
Four for loops: the bar fills, the bar empties, the dot runs right, the dot runs back.

A for loop runs the same lines a set number of times. for (int i = 0; i < 8; i++) runs its block eight times, with i counting 0, 1, 2 up to 7, and it is how a sketch walks along a row of LEDs, plays a list of notes or reads a row of sensors without writing the same line eight times.

The circuit above is an Uno driving eight LEDs through a 74HC595 shift register. Press Run. A bar fills from the left one lamp at a time, empties again, and then a single dot runs to the right and back. That whole animation is four for loops, one after the other, inside loop().

Below are the three parts of a for, then counting down and in steps, a loop inside a loop, break and continue, and the three mistakes that catch everyone, each run on an Uno with the output it printed.

Want the step-by-step version? The lesson "A loop over a list" walks through this with checkpoints.

Open the lesson

The three parts

Inside the brackets are three parts separated by semicolons. The first runs once, before anything else: int i = 0 makes a counter and starts it at zero. The second is checked before every pass, and the loop keeps going only while it is true: i < 5. The third runs at the end of every pass: i++ adds one.

So the loop below runs with i at 0, then 1, 2, 3 and 4, and printed "0 1 2 3 4". When i reaches 5 the condition is false, the loop stops and the sketch carries on after the closing brace. The counter only exists inside the loop. Use i after the brace and the build stops: the Arduino IDE says 'i' was not declared in this scope, and Mokxi’s clang says use of undeclared identifier 'i'.

Count to five
void setup() {
  Serial.begin(9600);
  for (int i = 0; i < 5; i++) {
    Serial.print(i);
    Serial.print(' ');
  }
  Serial.println();
}

void loop() {
}

The chaser’s four loops

Here is the sketch running above. show() sends one byte to the shift register, one bit per lamp. The first loop counts n up from 1 to 8 and lights the first n lamps, so the bar grows. The second counts down from 7 to 0 with n--, so the bar shrinks. The last two move a single lit bit right and then back, and the return trip stops at 1, not 0, so the end lamps are not shown twice in a row.

Change BAR_MS to 300 and press Run to slow the bar down, or change the 8 in the first loop to 4 and the bar only reaches halfway. The loops do the counting; you only change the limits.

firmware/uno/examples/chaser (the loop() running above)
void loop() {
  // the bar fills from the left, then empties
  for (int n = 1; n <= 8; n++) {
    show((uint8_t)((1u << n) - 1u));
    delay(BAR_MS);
  }
  for (int n = 7; n >= 0; n--) {
    show((uint8_t)((1u << n) - 1u));
    delay(BAR_MS);
  }
  // then a single dot runs to the right and back
  for (int n = 0; n < 8; n++) {
    show((uint8_t)(1u << n));
    delay(DOT_MS);
  }
  for (int n = 6; n >= 1; n--) {
    show((uint8_t)(1u << n));
    delay(DOT_MS);
  }
}

Counting down, in steps, and a loop inside a loop

The three parts can be anything. for (int i = 10; i > 0; i -= 3) starts at 10, takes three off each time and printed "10 7 4 1". The step does not have to land on the limit; the loop just stops once the condition fails.

Put one loop inside another and the inner one runs all the way through for every pass of the outer one. The sketch below printed a times table, "1 2 3", "2 4 6" and "3 6 9", one row per pass of row. This is how you scan a keypad, light an LED matrix or walk a grid of anything.

A loop inside a loop
void setup() {
  Serial.begin(9600);
  for (int row = 1; row <= 3; row++) {
    for (int col = 1; col <= 3; col++) {
      Serial.print(row * col);
      Serial.print(' ');
    }
    Serial.println();
  }
}

void loop() {
}

break and continue

continue skips the rest of this pass and goes straight on to the next one. break leaves the loop altogether. In the sketch below, 2 is skipped and the loop ends when i reaches 5, so out of ten passes it printed "0 1 3 4". break is the usual way out of a search: loop over the sensors, and stop at the first one that is over the limit.

Skip one, stop early
void setup() {
  Serial.begin(9600);
  for (int i = 0; i < 10; i++) {
    if (i == 2) continue;
    if (i == 5) break;
    Serial.print(i);
    Serial.print(' ');
  }
  Serial.println();
}

void loop() {
}

Three mistakes, made on purpose

One too many. for (int i = 0; i <= 8; i++) looks like eight passes and is nine: we counted the passes and the board printed 9. With eight LEDs numbered 0 to 7, the ninth pass reaches for a lamp that is not there. Count from 0 and use < with the number of things, and the loop is right.

A loop that never ends. A byte holds 0 to 255, so for (byte i = 250; i < 256; i++) can never fail its test: after 255, i++ wraps to 0. The board printed 250 to 255 and then 0, 1, 2 and kept going. The build tab warned about it: result of comparison of constant 256 with expression of type 'byte' (aka 'unsigned char') is always true. Use an int for the counter unless you have a reason not to.

A loop that stops the world. A for loop with a delay in it holds up everything else until it finishes. Five passes of delay(100) took half a second, 499 ms by the board’s own clock, and for that half second the sketch could not read a button or update anything. For a short animation that is fine. For a sketch that must keep listening, let loop() itself be the loop and count the steps with millis(), as the blink without delay page shows.

Questions

What is the difference between loop() and a for loop?

loop() is the function the Arduino runs over and over forever after setup(). A for loop is a statement inside your code that runs its block a set number of times and then lets the sketch carry on. Most sketches have for loops inside loop().

Why does my for loop run one time too many?

Usually the condition says <= where it should say <. for (int i = 0; i <= 8; i++) runs nine times, with i from 0 to 8. Counting from 0, the condition for eight passes is i < 8.

Why is my for loop infinite?

Either the counter never changes, or its type cannot reach the limit. A byte counter with i < 256 wraps from 255 back to 0 forever, and the compiler warns that the comparison is always true. Use an int.

How do I exit a for loop early?

Use break. It leaves the loop at once and the sketch carries on after the closing brace. continue is its partner: it skips the rest of one pass and goes on to the next.

Can I use a for loop to fade an LED?

Yes. for (int b = 0; b <= 255; b++) { analogWrite(9, b); delay(5); } fades an LED on pin 9 up in about 1.3 seconds. The PWM fade page has the full sketch, and how to do it without blocking.

Sources

Where the facts on this page come from

Build this for real

Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.