The Arduino For Loop: How you can use it the Right Way and easily repeat blocks of
code saving processor memory and simplifying access to array data. Avoid
off by one errors and how you can create an infinite for loop.
The Arduino for loop lets you repeat code:
Save rewriting code with a for-loop.
Avoid off by one errors - very easy to miss.
Count up or down (and use the loop variable inside code).
Find out where you can use for-loops.
Access array data with a for-loop.
The 'for loop' is one of those bread-and butter functions
that you will use all the time in your code. Microcontrollers are good
at repetitive tasks but instead writing out the same code many
times, the for-loop repeats a section of code a specific number
of times.
Where to use for-loops
You can use for loops anywhere inside a function, so you can
use them in the standard Arduino setup(), and loop() functions, and
within
your own functions. You can even use for loops inside other for loops
which is typically used for multidimensional array access.
The following example shows a for-loop that loops round
printing the numbers 0 to 9. It is placed into the setup() function
since you only want to perform the for-loop action one time - otherwise
if you place it within the loop() function it repeatedly outputs
information - making you head spin (try it and see)!
Code example showing an Arduino for loop with the for-loop inside the setup() function.
Copy the code into the Arduino IDE. Compile and run the program. Start the serial monitor to see the output.
voidsetup(void){
Serial.begin(9600);
Serial.println("Arduino for loop");
for(inti=0;i<10;i++)Serial.println(i);
}
voidloop(void){
}
This is not the place you should
normally use a for loop (you can though) - its only here to stop
multiple output.
How the Arduino for loop works
The Arduino for loop provides a mechanism to repeat a section
of code depending on the value of a variable.
You set the initial
value of the variable, the condition to exit the loop (testing the variable), and the action on
the variable each time around the loop.
Initialiser section:
The initial value of the control variable.
Condition Section:
The condition to stop the loop.
Iterator Section:
The loop variable action (increment or decrement).
These three elements are parameters to the for loop and are separated by semicolons:
for ( <initialiser code> ; <condition test expression> ; <iterator expression> ) {
<body code>
}
On 4/5/24 I changed the above to:
for ( <initialiser code> ; <condition test expression> ; <iterator statement> ) {
<body code>
}
This better describes what the for-loop syntax is doing. See "how to increment by two" for more on the iterator statement.
Arduino Loop Counter Control Variable
The other important point about for-loops is that they need a loop control variable - in the example
this is the variable 'i' - which can be of any type, but the integer type is most commonly used.
This variable is used as a loop counter and is used to decide when to exit the loop.
The code shown previously is the standard way to write a for-loop
in which the loop variable starts at zero and is incremented 10 times.
for(inti=0;i<10;i++)Serial.println(i);
Note: The value of 'i' goes from 0 to 9 which is 10 times round the loop.
Note: The value of 'i' after the loop is completed is 10. A little bit
counter intuitive, but to stay in the loop, 'i' can only range from 0 to
9, at 10 it exits. You can use the 'i' variable in later code as well.
Parameters of the Arduino for loop
Initialise
int i = 0;
First of all the variable 'i' is created (if it does not already exist) and set to zero.
This section of the for-loop is only executed once at the beginning.
Test
i < 10;
Next the loop variable is tested. Here, if it is smaller than 10 then carry on - otherwise the loop is exited.
This is executed every time around the loop.
Iterator
i++;
The loop control variable (loop counter) is increased by one.
This is executed every time around the loop - at the end brace that
defines the end of the for-loop (or the end of the single line statement
- as in the example above).
Arduino For loop Output
So the for-loop executes the code "Serial.print(i)" 10 times with value of 'i' going through 0 to 9.
And this is the output:
Arduino for loop
0
1
2
3
4
5
6
7
8
9
To see why you start the control variable from zero you should look at
the section on arrays and for-loops.
Why not start from initializer = 1?
For a different way of doing a similar action you could allow the control variable to change from 1 through 10.
for(inti=1;i<=10;i++)Serial.println(i);
This would print out 1 through 10. It is still 10 iterations but starting from 1.
Note: Here 'i' ranges from 1 to 10 i.e. 10 times round the loop.
At the end of the loop code (outside curly braces) the value of 'i' will
be 11, because when 'i' reaches 11 the statement 'i<=10' is false so
the loop is exited.
Note: This time at the end of the loop, 'i' has the value 11.
Although you can write for for-loop this way, you should use the
initialiser starting from zero as this means you won't get an off by one
error when you access an array!
Warning: You can write a for-loop with an iniaitiliser int i=1 ... but you will get off-by one errors when you access an array. See array access.
Arduino for-loop body code
The body of the for loop can either be a single statement of a block of
code between curly braces. So you could write the loop as follows:
voidsetup(void){
Serial.begin(9600);
Serial.println("Arduino for loop");
for(inti=0;i<7;i++){
Serial.print("i is : ");
Serial.println(i);
}
}
voidloop(void){
}
Notice how there are two statements - ending in semicolons and both
are enclosed by curly braces. Compare this to the previous example that
used only one statement ending in a semi-colon.
In this case the output is:
Arduino for loop
i is : 0
i is : 1
i is : 2
i is : 3
i is : 4
i is : 5
i is : 6
Test Yourself
Q: Here's a question for you. What is the value of i after the loop has finished executing?
The value of i is (click to find out)
I has the value 7 since to stay in the loop 'i' had to be smaller
than 7. When i equals 7, the condition is met to exit the loop.
Q: Another question. Can you use i later on in the program?
Can I use the variable i later? (click to find out)
Yes you can. It is a standard variable just like any other. It is
best not to do this too often as you will want to keep the variable 'i'
just for looping. This is just a convenience for you to remember that
the variable 'i'' may be used for other loops throughout the code.
How to setup a count down for loop
You can create a for loop that counts down by changing all three
parameters in the for loop. Lets say you want to count down from 10 to 1
(ten iterations round the loop).
voidsetup(void){
Serial.begin(9600);
Serial.println("Arduino count down for loop");
for(inti=10;i>=1;i--){
Serial.print("i is : ");
Serial.println(i);
}
}
voidloop(void){
}
Here's the count down output:
Arduino count down for loop
i is : 10
i is : 9
i is : 8
i is : 7
i is : 6
i is : 5
i is : 4
i is : 3
i is : 2
i is : 1
Test Yourself
Q: Here's the same question for you. What is the value of i after the loop has finished executing?
The value of i is (click to find out)
I has the value 0 since 'i' had to be greater than or equal to 1 to stay in the loop.
Arduino For loop Array Example
The reason that you start with the control loop variable at zero is
that arrays are defined starting from index zero. If you don't use zero
as an initial starting point then you can get an off by one error -
meaning you can write to a array location that does not exist. For an
array of 10 values only indices 0..9 are valid.
Arrays are made up of contiguous memory elements (of type char - a
byte) and are allocated by the compiler. You can have an array of any
type so:
char char_array[10];// Allocates 10 char of 1bytes each = 10 bytes.
int int_array[10]; // Allocates 10 integers of 2 bytes each = 20 bytes.
The first will occupy 10 bytes, while the second will occupy 20
bytes. It's up to you to ensure that you don't go beyond the last
allocated byte! (In C++ there are more protections that automatically
stop this but the advantage of C is that is simple and does not bloat
code).
TIP: You can use the function sizeof() to find out the number of bytes in a type.
Note: Note: Even if the array position does not exist, the loop will still
write data to that location - meaning you are overwriting other
variables - an extremely bad idea!
Here's an example of setting up an array initialising each element
with a random number. Then printing out the array values in turn.
intmyarray[10];
voidsetup(void){
Serial.begin(9600);
for(inti=0;i<10;i++)myarray[i]=random(100);
Serial.println("Arduino for loop");
for(inti=0;i<10;i++){
Serial.print("i is : ");
Serial.print(i);
Serial.print(" array value is ");
Serial.println(myarray[i]);
}
}
voidloop(void){
}
The interesting part of the code is that you must write
zero and ten within the loop definition. It looks wrong as you only need
the loop iterator to go from zero to nine but because of the "less
than" operator - that is exactly what happens. You can think of the
"<10" as defining the total number of elements within the array.
Standard form of a for loop
The standard form of the for loop initialises the control variable to
0. For exiting the loop the condition tests whether the variable is
smaller than the number of loops needed. You don't have to use this but
it makes life easier when dealing with arrays.
The value of 'i' goes from 0 to 9 for the code within the curly
braces. So it traverses 10 values. The reason it is easier for array use
is that arrays start from index zero [jump to array example].
TIP: it is best to use the standard form of the Arduino for-loop so
that you never access an array value incorrectly.
The standard form is this:
for(inti=0;i<10;i++){
<block of code to execute>}
At the end of the loop code (outside curly braces) the value of 'i'
will be 10, because when 'i' reaches 10 the statement 'i<10' is false
so the loop is exited.
Note: At the end of the loop 'i' has the value 10.
Initialising the For Loop (in pure C)
In the examples above the for-loop initialisation code is used as follows:
inti=0;
The variable is both declared and initialised - this is a C++ feature.
In C code you can't declare the variable within the for loop structure. It must be declared outside the for loop.
This is because C compilers want all the RAM assigned before messing
around creating the fixed program code. In C++ an extra stage of
processing allows the RAM and program data to be assigned on the fly. So
for pure 'C' code you will find the following code structure:
Note: You can use either form in C++ code i.e. when coding for Arduino.
You might want to
follow the standard C form as you can't declare a variable twice in the
same code block. So if you copy and paste some loop code into existing
code, you would have to look back and remove the extra declarations.
That or wait for the compiler to complain, which it will!
Breaking out of a for loop
Sometimes you will want to get out of a for loop because something changed in the system,
or program, that means you want to stop iterating through the loop
early, before it reaches the natural end condition. There are a few
reasons you may want to do this:
The data/collection being looped over was modified, so continuing the loop could cause errors or unexpected behavior.
Some external event occurred that makes continuing the loop
pointless or undesirable. For example, the user clicked a cancel button.
An error or exception was encountered during an iteration that you want to stop on instead of continuing.
To allow for this early exit, C/C++ gives you the break statement
that you can use inside the loop body to immediately "break out" of the
loop. This prevents the remaining iterations from executing.
TIP: You can also use the function break to exit a while loop.
Example Sketch showing use of break
This code will appear output dots for 10 seconds unless you press the
button when it breaks out of the loop. If you don't press the button,
you'll get the processing complete message. Then it restarts.
constint BUTTON_PIN = 2 ;
constint NUM_ITERATIONS = 1000;
voidsetup(){
pinMode(BUTTON_PIN, INPUT_PULLUP);
Serial.begin(9600);
}
voidloop(){
int iterationsComplete = 0;
for(int i=0; i<NUM_ITERATIONS; i++){
processData();
iterationsComplete++;
if(buttonPressed()){
break;
}
delay(10); // This for-loop will take 10 seconds if NUM_ITERATIONS is 1000.
// Show something
if(iterationsComplete % 80 == 0)Serial.println();
elseSerial.print(".");
}
if(iterationsComplete < NUM_ITERATIONS){
Serial.println("Processing cancelled by button press");
An interesting property of the for-loop is that what I have called an "Iterator Section" part of the for-loop with the following semantics:
for ( <initialiser code> ; <condition test expression> ; <iterator statement> ) {
<body code>
}
The very interesting part is that you can put any valid C/C++
statements into the iterator section. So to increment by 2 you can
write:
for(inti=0;i<10;i+=2){
<blockofcodetoexecute>
}
Or in non-short form:
for(inti=0;i<10;i=i+2){
<blockofcodetoexecute>
}
An extra bit of for-loop syntax (Advanced)
Following on from the previous section, where I said "you can put any
valid C/C++
statements into the iterator". This is factually true. It is not often
used but is valid C/C++ code. All you do is separate the iterator
statements using commas. Here's an example
for(inti=0;i<10;i++,j--,k*=2){
// loop body
}
Those last three statements are all "iterator statements" and they are
executed at the end of the loop. You can use any valid C/C++ code into
iterator statements - even function calls!
The upshot is that you can write very confusing code, but it is powerful - use it sparingly if at all!.
Does a for loop block Arduino?
Yes: Once you start a for loop you are stuck in that for-loop unless...
...unless you break out of it! See the break statement above.
In short, if your program is iterating over a 1000 character string
using a for-loop, it won't stop until it reaches the end.
However there are two things:
With interrupts active ( In Arduino they default to on - allowing
timers to work etc.). So in the background an interrupt will
trigger e.g. a serial character was received / millis() is
updated, and those actions are not blocked.
You can get out of a for-loop using break. However you have to
decide when and how to use the break statement to get out of the loop.
How many times the loop function runs
One frequently asked question is:
"How many times loop function runs in Arduino IDE:"
You can see from the previous examples exactly how the loop variables
are controlled to set the number of times a loop will execute.
How many times the main loop runs is a different matter:
The loop function in Arduino code is what is known as an infinite
loop which is can either be written using a while structure or a for
loop structure:
Infinite While loop
The while loop is used slightly differently to the for loop and does not have an iterator.
while(1) { // Do something forever }
Infinite For loop
The format of the infinite for loop is slightly strange:
for(;;) { // Do something forever }
The code operates exactly the same as the while loop. The two semicolons
just mean that the initialiser, the conditional test and the iterator
are void i.e. they do not exist. The compiler just leaves these parts
out, and all that is left is the assembler jump back instruction. So the
loop continues forever.
Either of these looping structures could be used in the Arduino code.
The are known as infinite loops but this really is just qualified by
the lifetime of the program. This is from the start time, when you
either apply power or press reset. It obviously end when power is
removed or rest is pressed again.
So to answer the question
"How many times the main loop function runs in the Arduino IDE"
The answer is - "it depends!"
It depends on the crystal speed of the Arduino (16MHz). This defines
how many instructions per seconds can be executed. And it depends
on how long the power is applied. The last factor is how much code is
executed within the main loop().
So it depends on:
Processor clock speed,
How long power is applied,
How much code is within loop().
When you add more instructions inside loop(), mode code must be executed so the loop time increases.
Measuring Loop Time
You can measure the loop time e.g. using microseconds timer but
collect the data in a variable and then compute the average. If you use a
Serial.print statement within the measurement it will give a larger the
time period - as that code itself will take a long time.
To do it add a condition that prints out the data after 100 loops.
However, even the test itself will take time but it will be a small
proportion of the time if the main code is substantial.
How to get accurate DHT22 digital humidity sensor readings with an Arduino. Did you know it also measures temperature as Well? Find out why, in this page...
A PIR sensor lets your Arduino sense movement without contact. This tutorial covers PIR sensor basics, connecting one to an Arduino board and coding a motion detector.
Arduino Hall Effect Sensor: Add magnetic sensing superpowers to your Arduino projects with an easy-to-use hall effect sensor. With full code and layout...
Comments
Have your say about what you just read! Leave me a comment in the box below.
Don’t see the comments box? Log in to your Facebook account, give Facebook consent, then return to this page and refresh it.