Bird
Raised Fist0
Arduinoprogramming~15 mins

setup() and loop() execution model in Arduino - Deep Dive

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Overview - setup() and loop() execution model
What is it?
In Arduino programming, the setup() and loop() functions control how your program runs. setup() runs once when the board starts, setting things up like pins or communication. loop() runs repeatedly after setup(), letting your program keep doing tasks over and over. This model makes Arduino programs simple and easy to understand.
Why it matters
This model exists to make microcontroller programming straightforward and predictable. Without it, you would have to manage starting and repeating tasks manually, which is complex and error-prone. It helps beginners write programs that react continuously, like blinking lights or reading sensors, without complicated code.
Where it fits
Before learning this, you should know basic programming concepts like functions and statements. After this, you can learn about handling inputs, outputs, and timing in Arduino. This model is the foundation for all Arduino sketches and understanding it is key to building interactive projects.
Mental Model
Core Idea
setup() runs once to prepare, then loop() runs forever to keep the program alive and responsive.
Think of it like...
It's like waking up in the morning (setup) to get ready, then doing your daily routine repeatedly (loop) until bedtime.
┌───────────────┐
│   Power On    │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│   setup()     │  ← runs once
└──────┬────────┘
       │
       ▼
┌───────────────┐
│    loop()     │  ← runs repeatedly
└──────┬────────┘
       │
       └─────────> (back to loop())
Build-Up - 7 Steps
1
FoundationUnderstanding setup() function role
🤔
Concept: setup() is the place to put code that runs once at the start.
When your Arduino board powers on or resets, it runs the setup() function exactly one time. This is where you initialize things like pin modes, start serial communication, or set initial values. For example: void setup() { pinMode(13, OUTPUT); // Set pin 13 as output } This prepares the board before doing anything else.
Result
The board is ready with configured settings before running the main program repeatedly.
Knowing setup() runs once helps you separate initialization from ongoing tasks, preventing repeated setup actions that waste time or cause errors.
2
FoundationUnderstanding loop() function role
🤔
Concept: loop() contains code that runs over and over forever.
After setup() finishes, Arduino calls loop() repeatedly in a cycle. This is where you put code that needs to run continuously, like checking sensors or blinking LEDs. For example: void loop() { digitalWrite(13, HIGH); // Turn LED on delay(1000); // Wait 1 second digitalWrite(13, LOW); // Turn LED off delay(1000); // Wait 1 second } This code blinks an LED on pin 13 forever.
Result
The program keeps running the loop() code repeatedly, creating ongoing behavior.
Understanding loop() runs forever lets you design programs that react and update continuously without extra control structures.
3
IntermediateHow setup() and loop() work together
🤔Before reading on: do you think setup() can run multiple times during normal operation, or only once? Commit to your answer.
Concept: setup() runs once to prepare, then loop() runs repeatedly to perform tasks.
The Arduino execution model is simple: first, setup() runs once to get everything ready. Then, loop() runs over and over without stopping. This means any code that should only happen once goes in setup(), and code that should happen repeatedly goes in loop(). If you put repeated code in setup(), it won't run again unless the board resets. If you put one-time code in loop(), it will run many times, which might cause problems.
Result
Programs behave predictably with clear separation of initialization and ongoing actions.
Knowing this separation prevents bugs where initialization code runs too often or repeated code runs too little.
4
IntermediateWhat happens if loop() finishes early
🤔Before reading on: do you think loop() runs once and stops, or restarts automatically? Commit to your answer.
Concept: loop() restarts automatically after finishing, creating an endless cycle.
When loop() reaches its end, Arduino immediately calls it again from the start. This means your program never stops running unless the board resets or loses power. You don't need to write your own loops inside loop() unless you want nested repetition. For example, this loop() runs a print statement repeatedly: void loop() { Serial.println("Hello"); delay(1000); } It prints "Hello" every second forever.
Result
loop() runs continuously, so your program stays active and responsive.
Understanding loop() restarts automatically helps you avoid infinite loops inside loop() that block other code.
5
IntermediateUsing delay() inside loop() and its effects
🤔Before reading on: does delay() pause the whole program or just part of it? Commit to your answer.
Concept: delay() pauses the entire program, stopping all code during the wait.
delay(milliseconds) stops the Arduino from doing anything else for the given time. This means no other code runs during delay(). For example, delay(1000) pauses for 1 second. While delay() is simple, it can cause problems if you want your program to do multiple things at once, like reading sensors while blinking LEDs. Example: void loop() { digitalWrite(13, HIGH); delay(1000); // LED on 1 second digitalWrite(13, LOW); delay(1000); // LED off 1 second } During delay(), the Arduino can't respond to inputs.
Result
Program pauses during delay(), which can make it unresponsive to other events.
Knowing delay() blocks code helps you plan better timing strategies for responsive programs.
6
AdvancedHow Arduino main() calls setup() and loop()
🤔Before reading on: do you think setup() and loop() are special keywords or called by hidden code? Commit to your answer.
Concept: Arduino's hidden main() function calls setup() once, then loop() repeatedly behind the scenes.
Behind the scenes, Arduino provides a main() function in its core library. This main() runs when the board powers on. It calls setup() once to initialize, then enters an infinite loop calling loop() repeatedly. Simplified main() looks like this: int main() { init(); // hardware setup setup(); while (true) { loop(); } return 0; } This means setup() and loop() are user-defined functions called by Arduino's system code.
Result
Your code fits into Arduino's hidden main() structure, making programming simpler.
Understanding this hidden main() clarifies why setup() and loop() must have exact names and signatures.
7
ExpertSurprising behavior with long-running loop() code
🤔Before reading on: if loop() takes a long time to finish, does Arduino run other system tasks in between? Commit to your answer.
Concept: If loop() runs too long, Arduino can't perform background tasks or respond quickly, causing delays or watchdog resets.
Because Arduino calls loop() repeatedly, if your loop() code takes a long time without returning, the system can't do other background work like USB communication or watchdog timer resets. For example, a loop() with a long for-loop or blocking code delays everything else. This can cause USB serial to freeze or watchdog timers to reset the board unexpectedly. Best practice is to keep loop() code short and use non-blocking techniques for long tasks.
Result
Long loop() code can cause system instability or unresponsive behavior.
Knowing loop() should be fast helps you write stable, responsive Arduino programs and avoid subtle bugs.
Under the Hood
Arduino's runtime environment includes a hidden main() function that initializes hardware, calls setup() once, then repeatedly calls loop() in an infinite cycle. This loop is managed by the microcontroller's program counter and stack, which handle function calls and returns. The microcontroller executes instructions sequentially, and the Arduino core libraries provide functions like delay() that use hardware timers to pause execution. The loop() function's repeated calls keep the program alive and responsive without needing explicit loops from the user.
Why designed this way?
This design was created to simplify programming for beginners by hiding complex startup and looping code. Early microcontroller programming required manual setup and infinite loops, which were error-prone and confusing. Arduino's model abstracts this, letting users focus on what to do once (setup) and what to do repeatedly (loop). It balances simplicity with flexibility, making embedded programming accessible to artists, students, and hobbyists.
┌───────────────┐
│   Reset/Power │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│   init()      │  ← hardware setup
└──────┬────────┘
       │
       ▼
┌───────────────┐
│   setup()     │  ← user initialization
└──────┬────────┘
       │
       ▼
┌─────────────────────────────┐
│ while (true) {               │
│   loop();                   │  ← user repeated code
│ }                           │
└─────────────────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does setup() run every time loop() repeats? Commit to yes or no before reading on.
Common Belief:setup() runs every time loop() runs, so initialization repeats constantly.
Tap to reveal reality
Reality:setup() runs only once at the very start; loop() runs repeatedly after that.
Why it matters:If you put initialization code in loop() thinking setup() runs repeatedly, your program may reset hardware or variables unnecessarily, causing bugs or slowdowns.
Quick: Does delay() allow other code to run while waiting? Commit to yes or no before reading on.
Common Belief:delay() pauses only part of the program, letting other code run simultaneously.
Tap to reveal reality
Reality:delay() blocks the entire program, stopping all code execution during the wait.
Why it matters:Using delay() can make your program unresponsive to inputs or events, which is bad for interactive or real-time applications.
Quick: Can you rename setup() or loop() to other names and still have Arduino call them? Commit to yes or no before reading on.
Common Belief:You can name setup() and loop() anything you want; Arduino will find and run them.
Tap to reveal reality
Reality:Arduino requires exact function names setup() and loop() to call them automatically.
Why it matters:Renaming these functions breaks the program flow, causing your code not to run as expected.
Quick: Does loop() run in parallel with other Arduino system tasks? Commit to yes or no before reading on.
Common Belief:loop() runs alongside other system tasks simultaneously, so long code in loop() is fine.
Tap to reveal reality
Reality:loop() runs alone; long or blocking code inside it delays or blocks system tasks.
Why it matters:Long loop() code can freeze USB communication or cause watchdog resets, leading to unstable programs.
Expert Zone
1
The hidden main() function is part of Arduino's core, written in C++, which means setup() and loop() must have exact signatures to link correctly.
2
Using non-blocking timing methods like millis() instead of delay() allows loop() to run quickly and handle multiple tasks smoothly.
3
Some advanced boards or frameworks extend the loop() model with multitasking or event-driven approaches, but the basic setup()/loop() remains the foundation.
When NOT to use
This model is not suitable for complex multitasking or real-time operating systems where tasks must run truly in parallel. In such cases, use RTOS frameworks or Arduino-compatible OS layers that support threads or interrupts for concurrency.
Production Patterns
In real projects, setup() is used to initialize sensors, communication, and hardware states once. loop() handles reading inputs, updating outputs, and managing timing with non-blocking code. Developers often structure loop() with state machines or event checks to keep programs responsive and maintainable.
Connections
Event Loop in JavaScript
Both use a repeating cycle to handle tasks continuously.
Understanding Arduino's loop() helps grasp how JavaScript's event loop keeps programs responsive by running callbacks repeatedly.
Operating System Scheduler
Arduino's loop() is a simple form of task scheduling, running user code repeatedly without preemption.
Knowing this shows how complex OS schedulers evolved from simple infinite loops to manage multitasking.
Daily Routine Planning
setup() and loop() mirror how people prepare once then repeat daily tasks.
This connection helps appreciate how programming models reflect natural human patterns of preparation and repetition.
Common Pitfalls
#1Putting initialization code inside loop() causing repeated resets.
Wrong approach:void loop() { pinMode(13, OUTPUT); // Wrong: runs every loop digitalWrite(13, HIGH); delay(1000); digitalWrite(13, LOW); delay(1000); }
Correct approach:void setup() { pinMode(13, OUTPUT); // Correct: runs once } void loop() { digitalWrite(13, HIGH); delay(1000); digitalWrite(13, LOW); delay(1000); }
Root cause:Misunderstanding that setup() runs only once and loop() runs repeatedly.
#2Using delay() for timing in programs needing responsiveness.
Wrong approach:void loop() { digitalWrite(13, HIGH); delay(5000); // Blocks for 5 seconds digitalWrite(13, LOW); delay(5000); }
Correct approach:unsigned long previousMillis = 0; const long interval = 5000; void loop() { unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; // Toggle LED here } }
Root cause:Not knowing delay() blocks all code, preventing multitasking.
#3Renaming setup() or loop() causing code not to run.
Wrong approach:void initialize() { // setup code } void repeat() { // loop code }
Correct approach:void setup() { // setup code } void loop() { // loop code }
Root cause:Not realizing Arduino requires exact function names to call user code.
Key Takeaways
Arduino programs start by running setup() once to prepare hardware and variables.
After setup(), loop() runs repeatedly forever, allowing continuous program behavior.
delay() pauses the entire program, so use it carefully to avoid unresponsiveness.
Behind the scenes, Arduino has a hidden main() that calls setup() and loop(), making programming simpler.
Keeping loop() code short and non-blocking ensures your program stays responsive and stable.

Practice

(1/5)
1. What is the main purpose of the setup() function in an Arduino program?
easy
A. To stop the Arduino program
B. To run code repeatedly forever
C. To reset the Arduino board
D. To run code once at the start to prepare the Arduino

Solution

  1. Step 1: Understand the role of setup()

    The setup() function runs only once when the Arduino starts. It is used to prepare things like pin modes or initial settings.
  2. Step 2: Compare with other options

    loop() runs repeatedly, so To run code repeatedly forever is incorrect. Options A and D describe actions not done by setup().
  3. Final Answer:

    To run code once at the start to prepare the Arduino -> Option D
  4. Quick Check:

    setup() runs once = C [OK]
Hint: Remember: setup() runs once, loop() runs forever [OK]
Common Mistakes:
  • Thinking setup() runs repeatedly
  • Confusing setup() with loop()
  • Believing setup() resets the board
2. Which of the following is the correct way to declare the loop() function in Arduino?
easy
A. int loop() {}
B. void loop() {}
C. void loop(void) {}
D. loop() void {}

Solution

  1. Step 1: Recall Arduino function syntax

    Arduino functions like loop() are declared with return type void and empty parentheses: void loop() {}.
  2. Step 2: Check each option

    void loop() {} matches correct syntax. int loop() {} wrongly uses int return type. void loop(void) {} is valid C++ but less common in Arduino examples. loop() void {} has incorrect order.
  3. Final Answer:

    void loop() {} -> Option B
  4. Quick Check:

    Standard Arduino loop syntax = A [OK]
Hint: Use 'void loop()' exactly as Arduino expects [OK]
Common Mistakes:
  • Using wrong return type like int
  • Swapping order of function name and return type
  • Adding parameters inside loop()
3. What will be the output on the Serial Monitor when running this Arduino code?
void setup() {
  Serial.begin(9600);
  Serial.println("Start");
}

void loop() {
  Serial.println("Looping");
  delay(1000);
}
medium
A. Start and Looping printed once each
B. Only Looping printed repeatedly
C. Start printed once, then Looping printed every second
D. No output because Serial.begin() is missing

Solution

  1. Step 1: Analyze setup() output

    Serial.begin(9600) starts serial communication. Serial.println("Start") prints "Start" once at the beginning.
  2. Step 2: Analyze loop() output

    loop() prints "Looping" every 1000 milliseconds (1 second) repeatedly.
  3. Final Answer:

    Start printed once, then Looping printed every second -> Option C
  4. Quick Check:

    setup() once, loop() repeats = B [OK]
Hint: setup() prints once, loop() repeats output [OK]
Common Mistakes:
  • Thinking loop() runs once
  • Missing Serial.begin() call
  • Ignoring delay causing fast prints
4. Identify the error in this Arduino code:
void setup() {
  pinMode(13, OUTPUT);
}

void loop() {
  digitalWrite(13, HIGH);
  delay(1000);
  digitalWrite(13, LOW);
  delay(1000)
}
medium
A. Missing semicolon after delay(1000) in loop()
B. pinMode should be in loop(), not setup()
C. digitalWrite cannot be used with pin 13
D. delay() cannot be used inside loop()

Solution

  1. Step 1: Check syntax line by line

    In loop(), the line delay(1000) is missing a semicolon at the end.
  2. Step 2: Verify other parts

    pinMode is correctly placed in setup(). digitalWrite works with pin 13. delay() is allowed in loop().
  3. Final Answer:

    Missing semicolon after delay(1000) in loop() -> Option A
  4. Quick Check:

    Syntax error = missing semicolon [OK]
Hint: Check every line ends with a semicolon [OK]
Common Mistakes:
  • Placing pinMode in loop() unnecessarily
  • Assuming digitalWrite can't use pin 13
  • Thinking delay() is disallowed in loop()
5. You want to blink an LED connected to pin 9 exactly 5 times when the Arduino starts, then stop blinking. Which code correctly uses setup() and loop() to do this?
hard
A. Use a counter in setup() to blink 5 times; leave loop() empty
B. Blink 5 times inside loop() without a counter
C. Blink 5 times inside loop() using a counter, then stop blinking
D. Blink 5 times inside setup(), then keep blinking in loop()

Solution

  1. Step 1: Understand blinking 5 times only once

    Since blinking 5 times is a one-time task, it should be done in setup() which runs once.
  2. Step 2: Keep loop() empty to stop further blinking

    Leaving loop() empty prevents repeated blinking after the initial 5 times.
  3. Final Answer:

    Use a counter in setup() to blink 5 times; leave loop() empty -> Option A
  4. Quick Check:

    One-time task in setup() = A [OK]
Hint: One-time actions go in setup(), repeated in loop() [OK]
Common Mistakes:
  • Blinking in loop() without stopping
  • Not using a counter to limit blinks
  • Putting one-time code in loop() causing repeats