Bird
Raised Fist0
Arduinoprogramming~15 mins

delay() function behavior 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 - delay() function behavior
What is it?
The delay() function in Arduino pauses the program for a specific number of milliseconds. When you call delay(1000), the program stops doing anything else for 1 second. This is useful when you want to wait before doing the next action. However, during this pause, the Arduino cannot do other tasks.
Why it matters
Without delay(), controlling timing in Arduino programs would be very hard. It helps beginners easily add pauses between actions, like blinking an LED or waiting for a sensor. But if used carelessly, delay() can make the program unresponsive, which is a common problem in real projects. Understanding delay() helps you write better, more responsive Arduino code.
Where it fits
Before learning delay(), you should know basic Arduino programming and how the loop() function works. After mastering delay(), you can learn about non-blocking timing methods like millis() and interrupts to make your programs more efficient.
Mental Model
Core Idea
delay() stops everything in the program for a set time, like pressing pause on a video player.
Think of it like...
Imagine you are cooking and you set a timer to wait before adding the next ingredient. During that waiting time, you do nothing else but watch the clock until the timer rings. delay() works the same way for the Arduino.
┌───────────────┐
│ Start program │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ delay(1000)ms │  <-- Program waits here, does nothing else
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ Continue code │
└───────────────┘
Build-Up - 7 Steps
1
FoundationWhat delay() Does Simply
🤔
Concept: delay() pauses the program for a given number of milliseconds.
In Arduino, delay(1000) means stop everything for 1000 milliseconds (1 second). The program does not move forward until this time passes. For example, blinking an LED with delay(1000) turns it on, waits 1 second, then turns it off.
Result
The LED blinks on and off every second.
Understanding that delay() literally stops the program helps you see why nothing else happens during that time.
2
FoundationMilliseconds and Timing Units
🤔
Concept: delay() uses milliseconds as its unit of time.
1 second equals 1000 milliseconds. So delay(500) waits for half a second. This unit lets you control timing very precisely, from tiny pauses to long waits.
Result
You can control how long the Arduino waits by changing the number inside delay().
Knowing the unit helps you set the right pause length for your project needs.
3
Intermediatedelay() Blocks All Other Actions
🤔Before reading on: Do you think the Arduino can read sensors or respond to buttons during delay()? Commit to yes or no.
Concept: delay() stops the entire program, so no other code runs during the wait.
When delay() runs, the Arduino cannot check inputs, update outputs, or run other code. This means if you press a button during delay(), the program won't notice until delay() finishes.
Result
The program appears frozen during delay(), missing inputs or events.
Understanding delay() blocks everything explains why programs can feel unresponsive if delay() is overused.
4
IntermediateUsing delay() in loop() for Simple Timing
🤔Before reading on: Will using delay() inside loop() make the LED blink smoothly or cause pauses? Commit to your answer.
Concept: delay() inside loop() creates simple timed actions by pausing between steps.
A common pattern is to turn an LED on, delay, turn it off, delay, then repeat. This creates a blinking effect with fixed timing.
Result
The LED blinks on and off with a steady rhythm controlled by delay().
Using delay() in loop() is an easy way to add timing but limits what else the program can do.
5
AdvancedLimitations of delay() in Complex Programs
🤔Before reading on: Do you think delay() is good for multitasking Arduino projects? Commit to yes or no.
Concept: delay() is blocking and prevents multitasking or responsive behavior.
In projects needing to read sensors, control motors, or respond quickly, delay() causes problems because it stops all code. This can make the device slow or miss important events.
Result
Programs using delay() heavily can feel slow or unresponsive.
Knowing delay() blocks code helps you understand why advanced projects use other timing methods.
6
AdvancedAlternatives to delay(): millis() and Non-blocking Code
🤔
Concept: Using millis() lets you track time without stopping the program.
millis() returns how many milliseconds since the Arduino started. By checking this value repeatedly, you can do actions at intervals without pausing. This keeps the program responsive.
Result
Programs can do many things at once, like blinking LEDs and reading sensors simultaneously.
Understanding delay() limitations motivates learning millis() for better control and multitasking.
7
ExpertHow delay() Works Internally in Arduino
🤔Before reading on: Do you think delay() uses hardware timers or just a simple loop? Commit to your answer.
Concept: delay() uses a busy-wait loop checking the system clock to pause execution.
Inside delay(), Arduino reads the system timer repeatedly until the requested time passes. It does not use interrupts or hardware timers to pause, so the CPU is fully occupied doing nothing else.
Result
The CPU cannot do other tasks during delay(), causing blocking behavior.
Knowing delay() uses busy-waiting explains why it blocks and wastes CPU cycles.
Under the Hood
delay() works by reading the Arduino's internal clock repeatedly in a loop until the specified milliseconds have passed. It does not yield control or use interrupts, so the CPU is busy checking time and cannot run other code. This is called a blocking or busy-wait delay.
Why designed this way?
delay() was designed as a simple, easy-to-understand function for beginners to control timing without complexity. Using busy-waiting avoids hardware timer setup, making it straightforward but at the cost of blocking. More advanced timing methods require more complex code and understanding.
┌───────────────┐
│ delay(ms)     │
├───────────────┤
│ start_time =  │
│ current clock │
├───────────────┤
│ while (current │
│ clock - start  │
│ < ms) {       │
│   keep checking│
│   clock       │
│ }             │
└───────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does delay() allow other code like sensor reading to run during the wait? Commit yes or no.
Common Belief:delay() pauses only the current task but lets other parts of the program run.
Tap to reveal reality
Reality:delay() blocks the entire program, so no other code runs until the delay finishes.
Why it matters:Believing delay() is non-blocking leads to bugs where inputs or events are missed during delay.
Quick: Can delay() handle very long waits without issues? Commit yes or no.
Common Belief:delay() can pause for any length of time without problems.
Tap to reveal reality
Reality:delay() uses an unsigned long for milliseconds, so very long delays can overflow or cause unexpected behavior.
Why it matters:Using very long delays can cause timing errors or program crashes.
Quick: Is delay() the best way to handle multitasking in Arduino? Commit yes or no.
Common Belief:delay() is suitable for multitasking and responsive programs.
Tap to reveal reality
Reality:delay() blocks all code, making multitasking impossible; millis() or interrupts are better for that.
Why it matters:Using delay() in multitasking projects causes unresponsive behavior and missed events.
Quick: Does delay() consume no CPU while waiting? Commit yes or no.
Common Belief:delay() puts the CPU to sleep, saving power during the wait.
Tap to reveal reality
Reality:delay() keeps the CPU busy checking time, so it uses full power during the delay.
Why it matters:Misunderstanding this can lead to inefficient power use in battery-powered projects.
Expert Zone
1
delay() uses a busy-wait loop which means the CPU is fully occupied and cannot enter low-power sleep modes during delay.
2
Stacking multiple delay() calls can cause cumulative blocking, making timing unpredictable in complex programs.
3
Some Arduino cores or boards may implement delay() differently, for example using hardware timers to reduce blocking, but standard Arduino uses busy-wait.
When NOT to use
Avoid delay() in projects needing multitasking, real-time responsiveness, or low power. Instead, use millis() for non-blocking timing or hardware timers and interrupts for precise control.
Production Patterns
In real-world Arduino projects, delay() is often used only in simple startup sequences or debugging. Production code relies on millis() loops or state machines to keep the device responsive and efficient.
Connections
Event Loop in JavaScript
Opposite pattern: delay() blocks execution, while event loops avoid blocking to handle many tasks.
Understanding delay() blocking helps appreciate why event-driven programming avoids pauses to keep apps responsive.
Real-Time Operating Systems (RTOS)
Builds-on: RTOS provide multitasking and precise timing without blocking, solving delay() limitations.
Knowing delay() limitations clarifies why RTOS are used in advanced embedded systems for better control.
Human Attention Span
Analogy to human waiting: delay() is like staring at a clock doing nothing, while better timing methods let you multitask.
Recognizing delay() as a blocking wait mirrors how humans lose productivity when forced to wait without doing anything else.
Common Pitfalls
#1Using delay() for long waits in interactive programs.
Wrong approach:void loop() { delay(5000); // wait 5 seconds // check button press here }
Correct approach:unsigned long lastTime = 0; void loop() { if (millis() - lastTime >= 5000) { lastTime = millis(); // check button press here } }
Root cause:Misunderstanding that delay() blocks all code, preventing timely input checks.
#2Assuming delay() allows other code to run during wait.
Wrong approach:void loop() { delay(1000); readSensor(); // expecting this to run during delay }
Correct approach:void loop() { readSensor(); // use millis() to time actions without blocking }
Root cause:Belief that delay() is non-blocking and multitasking-friendly.
#3Using delay() inside interrupt service routines (ISRs).
Wrong approach:ISR() { delay(100); // delay inside interrupt }
Correct approach:ISR() { // set a flag and handle delay in main loop }
Root cause:Not knowing delay() relies on interrupts and cannot be used inside ISRs.
Key Takeaways
delay() pauses the entire Arduino program for a set number of milliseconds, blocking all other code.
Because delay() blocks, the Arduino cannot respond to inputs or run other tasks during the wait.
delay() is simple and useful for beginners but limits responsiveness in complex projects.
For multitasking or responsive programs, use millis() or hardware timers instead of delay().
Understanding delay() internals reveals why it blocks and helps choose better timing methods.

Practice

(1/5)
1. What does the delay(1000); function do in an Arduino program?
easy
A. Pauses the program for 1000 milliseconds (1 second)
B. Stops the program permanently
C. Speeds up the program by 1000 times
D. Restarts the Arduino board

Solution

  1. Step 1: Understand the delay() parameter

    The number inside delay() is the time in milliseconds to pause the program.
  2. Step 2: Interpret delay(1000)

    1000 milliseconds equals 1 second, so the program pauses for 1 second.
  3. Final Answer:

    Pauses the program for 1000 milliseconds (1 second) -> Option A
  4. Quick Check:

    delay(1000) = 1 second pause [OK]
Hint: delay(x) pauses for x milliseconds, 1000ms = 1 second [OK]
Common Mistakes:
  • Thinking delay stops the program forever
  • Confusing milliseconds with seconds
  • Assuming delay speeds up the program
2. Which of the following is the correct syntax to pause an Arduino program for half a second?
easy
A. delay(0.5);
B. delay = 500;
C. delay(500s);
D. delay(500);

Solution

  1. Step 1: Check correct function usage

    delay() takes an integer number of milliseconds inside parentheses.
  2. Step 2: Validate each option

    A uses delay(0.5); which is a float and incorrect. B assigns delay which is invalid. C uses delay(500); which is correct for 500 milliseconds. D uses '500s' which is invalid syntax.
  3. Final Answer:

    delay(500); -> Option D
  4. Quick Check:

    delay(500) is correct syntax [OK]
Hint: Use delay(milliseconds); with integer inside parentheses [OK]
Common Mistakes:
  • Using decimal numbers instead of integers
  • Assigning delay like a variable
  • Adding units like 's' inside delay()
3. What will be the output on the Serial Monitor after running this Arduino code?
void setup() {
  Serial.begin(9600);
  Serial.println("Start");
  delay(2000);
  Serial.println("End");
}
void loop() {}
medium
A. Start and End printed immediately together
B. Only Start is printed, End never prints
C. Start immediately, then End after 2 seconds
D. No output because delay stops Serial

Solution

  1. Step 1: Analyze Serial prints and delay

    "Start" prints immediately, then delay(2000) pauses 2 seconds before next line.
  2. Step 2: Understand delay effect on output

    After 2 seconds pause, "End" prints. Both lines appear but with 2 seconds gap.
  3. Final Answer:

    Start immediately, then End after 2 seconds -> Option C
  4. Quick Check:

    delay pauses program, output delayed [OK]
Hint: delay pauses code, so output after delay appears later [OK]
Common Mistakes:
  • Thinking delay stops Serial output completely
  • Assuming both prints happen instantly
  • Believing delay affects only loop(), not setup()
4. Identify the problem in this Arduino code snippet:
void setup() {
  pinMode(13, OUTPUT);
}
void loop() {
  digitalWrite(13, HIGH);
  delay(1000)
  digitalWrite(13, LOW);
  delay(1000);
}
medium
A. pinMode should be in loop()
B. Missing semicolon after delay(1000)
C. digitalWrite needs delay before it
D. delay() cannot be used in loop()

Solution

  1. Step 1: Check syntax line by line

    delay(1000) is missing a semicolon at the end, causing a syntax error.
  2. Step 2: Validate other statements

    pinMode is correctly in setup(), digitalWrite and delay usage is correct except missing semicolon.
  3. Final Answer:

    Missing semicolon after delay(1000) -> Option B
  4. Quick Check:

    Every statement must end with ; [OK]
Hint: Check for missing semicolons after delay() calls [OK]
Common Mistakes:
  • Putting pinMode inside loop unnecessarily
  • Thinking delay() can't be in loop
  • Forgetting semicolons after statements
5. You want to blink an LED connected to pin 9 exactly 3 times with 0.5 second ON and 0.5 second OFF, then stop. Which code snippet correctly uses delay() to do this?
hard
A. for(int i=0; i<3; i++) { digitalWrite(9, HIGH); delay(500); digitalWrite(9, LOW); delay(500); }
B. while(true) { digitalWrite(9, HIGH); delay(500); digitalWrite(9, LOW); delay(500); }
C. digitalWrite(9, HIGH); delay(1500); digitalWrite(9, LOW); delay(1500);
D. for(int i=0; i<=3; i++) { digitalWrite(9, HIGH); delay(1000); digitalWrite(9, LOW); delay(1000); }

Solution

  1. Step 1: Understand blinking requirements

    LED must turn ON and OFF 3 times, each ON and OFF lasting 0.5 seconds (500 ms).
  2. Step 2: Analyze each option

    A uses a for loop 3 times with 500ms delay ON and OFF, matching requirements. B loops forever, no stop. C delays 1500ms which is too long and only blinks once. D loops 4 times (i<=3) with 1000ms delays, wrong timing and count.
  3. Final Answer:

    for(int i=0; i<3; i++) { digitalWrite(9, HIGH); delay(500); digitalWrite(9, LOW); delay(500); } -> Option A
  4. Quick Check:

    Loop 3 times with 500ms delay ON/OFF [OK]
Hint: Use for loop with delay(500) ON and OFF, repeat 3 times [OK]
Common Mistakes:
  • Using infinite loops instead of fixed count
  • Wrong delay times for ON/OFF
  • Looping one extra time with <= instead of <