Embedded Systems
Arduino setup() and loop() explained
Every Arduino sketch has two functions. setup() runs once, when the board powers up or resets: it gets things ready, like setting pin modes and starting the serial port. loop() runs next, then again and again, for as long as the board has power: it's where the sketch reads inputs and drives outputs.
void setup() {
pinMode(LED_BUILTIN, OUTPUT); // L, on pin 13
Serial.begin(9600); // start the serial monitor
Serial.println("Ready"); // said once
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(100); // on for 100 ms
digitalWrite(LED_BUILTIN, LOW);
delay(900); // off for 900 ms
}
That sketch says Ready once, then flashes L once a second, forever.
What happens behind them
Arduino writes the rest of the program for you. Stripped down, it's this:
int main() {
init(); // set up the chip's timers
setup(); // your code, once
for (;;) {
loop(); // your code, forever
}
}
So loop() isn't magic: it's an ordinary function called inside a loop that never ends.
Live experiment
Meet the board
The board starts unplugged and asleep. Tap the USB socket to plug it in, and the starter program blinks L. Then tap round the board to find its six parts: the USB socket, the microcontroller, L, the digital pins, the analog pins and 5V and GND.
“Meet the board” is lesson 1 of 6 in Blink Bay, Embedded Systems World 1. Free with an account. It’s open as soon as you sign up.
What goes where
In setup(): anything that only needs doing once. pinMode(), Serial.begin(), a welcome message, starting a sensor.
In loop(): anything that should keep happening. Reading buttons and sensors, deciding what to do, writing to LEDs and motors. Read a sensor only in setup() and you get one reading, at power-on, and never another.
Above setup(): variables that must remember something between passes, like a count or the time of the last blink. A variable declared inside loop() is made fresh on every pass, so it can't keep a running total.
The syntax rules
- Each statement ends with a semicolon,
; - A block of statements sits between
{and} //starts a comment, a note the board ignores- A function call passes its arguments in brackets:
delay(100)
The compiler is strict: Delay and delay are different names, and a missing ; stops the upload with a message naming the line.
Once the sketch is uploaded, the board runs it by itself, even with the computer unplugged, starting from setup() every time it powers up.
Free lesson
Now build it yourself
Each lesson comes in three short parts: see the idea, try it on a live board, then build it yourself, with quick checks as you go.
“Meet the board” is lesson 1 of 6 in Blink Bay, Embedded Systems World 1. Free with an account. It’s open as soon as you sign up.
Or start from the very first lesson, no account neededPractice questions
Three quick questions from the lessons. Pick an answer to check it.
Show the answer
Answer: loop(). setup() runs once when the board starts. loop() runs next, then again and again, for as long as the board has power.
- Why not “The pins”? The pins are the board's connections, not part of the program. loop() is the code that repeats.
- Why not “Upload”? Upload copies the program onto the board once. It isn't part of the program that runs.
- Why not “setup()”? setup() runs only once, when the board starts or resets. loop() is the part that repeats.
Show the answer
Answer: // wait. Everything after // on a line is a comment, a note for people. The board skips it.
- Why not “(900);”? (900); gives delay its argument and ends the statement. Without it the line wouldn't even compile.
- Why not “delay”? delay is the function the line calls, so the board runs it and waits.
Show the answer
Answer: it must keep its value from one pass of loop() to the next. A variable made inside loop() is thrown away at the end of every pass. Above setup(), it lives for as long as the board runs.
- Why not “it makes the program faster”? Where a variable lives doesn't change the speed. It changes how long its value lasts.
- Why not “loop() can't hold numbers”? loop() can hold numbers, but a variable made inside it is made fresh on every pass and starts again.
- Why not “setup() needs it first”? setup() doesn't use the count at all. It sits above setup() so it survives from one pass of loop() to the next.
“Meet the board” is lesson 1 of 6 in Blink Bay, Embedded Systems World 1. Free with an account. It’s open as soon as you sign up.
Questions people ask
Can an Arduino sketch run without loop()?
No: both setup() and loop() must exist, or it won't compile. They can be empty, though. A program that does everything once can put it all in setup() and leave loop() empty, and the board then idles in loop() forever.
When does setup() run again?
Whenever the board restarts: at power-on, when you press its reset button, and after every upload. On an Uno, opening the serial monitor usually resets the board too, so setup() runs again.
How fast does loop() repeat?
As fast as its code allows. An empty loop() comes round hundreds of thousands of times a second on a 16 MHz Uno, and each digitalRead or digitalWrite adds a few microseconds. A delay() inside it sets the pace instead.
Related topics
- What is a microcontroller?A tiny computer on one chip that reads buttons and sensors and switches lights and motors.
- The Arduino Blink sketch, explained line by lineFour lines that blink an LED, the sum behind the blink rate, and what happens when it's too fast to see.
- millis() vs delay() on ArduinoWhy delay() freezes your sketch, and how millis() runs several jobs at once.
- How to count button presses on an ArduinoCount the change, not the hold, keep the count above setup(), and use % for every Nth press.