Bird
Raised Fist0
Arduinoprogramming~10 mins

Blink without delay pattern in Arduino - Step-by-Step Execution

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
Concept Flow - Blink without delay pattern
Start
Read current time
Check if interval passed?
Do nothing
Save current time
Repeat loop
The program repeatedly checks the time and toggles the LED only when the set interval has passed, avoiding delay pauses.
Execution Sample
Arduino
const int ledPin = 13;
unsigned long previousMillis = 0;
const long interval = 1000;

void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    digitalWrite(ledPin, !digitalRead(ledPin));
  }
}
This code toggles an LED on pin 13 every 1000 milliseconds without stopping the program.
Execution Table
StepcurrentMillispreviousMillisCondition (currentMillis - previousMillis >= interval)ActionLED State
1000 - 0 >= 1000 → FalseNo toggleOFF
25000500 - 0 >= 1000 → FalseNo toggleOFF
3100001000 - 0 >= 1000 → TrueToggle LED ON, previousMillis=1000ON
4150010001500 - 1000 >= 1000 → FalseNo toggleON
5200010002000 - 1000 >= 1000 → TrueToggle LED OFF, previousMillis=2000OFF
6250020002500 - 2000 >= 1000 → FalseNo toggleOFF
7300020003000 - 2000 >= 1000 → TrueToggle LED ON, previousMillis=3000ON
ExitN/AN/ALoop runs foreverNo exitN/A
💡 The loop runs continuously; no exit condition.
Variable Tracker
VariableStartAfter Step 1After Step 2After Step 3After Step 4After Step 5After Step 6After Step 7Final
previousMillis000100010002000200030003000
LED StateOFFOFFOFFONONOFFOFFONON
Key Moments - 3 Insights
Why doesn't the LED toggle every time loop() runs?
Because the condition checks if the set interval has passed since the last toggle (see execution_table rows 1, 2 vs 3). It only toggles when enough time has passed.
Why do we save currentMillis to previousMillis after toggling?
Saving currentMillis resets the timer for the next interval (see execution_table rows 3, 5, 7). Without this, the condition would always be true and the LED would toggle continuously.
What happens if we use delay() instead of this pattern?
Using delay() pauses the whole program, stopping other code from running. This pattern lets the program keep running while waiting.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, what is the LED state after step 5?
AOFF
BBlinking rapidly
CON
DUnchanged from start
💡 Hint
Check the 'LED State' column at step 5 in the execution_table.
At which step does the condition first become true?
AStep 2
BStep 3
CStep 1
DStep 4
💡 Hint
Look at the 'Condition' column in execution_table and find the first 'True'.
If interval was changed to 500, how would the action at step 2 change?
ANo toggle, same as before
BProgram would stop
CToggle LED ON at step 2
DLED would stay OFF forever
💡 Hint
Compare currentMillis - previousMillis at step 2 with new interval 500.
Concept Snapshot
Blink without delay pattern:
- Use millis() to track time without stopping code.
- Check if (currentMillis - previousMillis) >= interval.
- If true, toggle LED and update previousMillis.
- Loop runs continuously without delay.
- Allows multitasking and responsive programs.
Full Transcript
This example shows how to blink an LED without using delay. The program uses millis() to get the current time in milliseconds. It compares this time with the last time the LED was toggled, stored in previousMillis. If the difference is equal or greater than the interval (1000 ms), it toggles the LED and updates previousMillis. Otherwise, it does nothing and keeps looping. This way, the program never pauses and can do other tasks while blinking the LED.

Practice

(1/5)
1. What is the main advantage of using the Blink without delay pattern in Arduino programming?
easy
A. It allows the Arduino to perform other tasks while blinking an LED.
B. It makes the LED blink faster than usual.
C. It uses less power than the delay() function.
D. It requires fewer lines of code than delay().

Solution

  1. Step 1: Understand delay() limitation

    The delay() function pauses the whole program, stopping other tasks.
  2. Step 2: millis() allows multitasking

    Using millis() tracks time without stopping the program, so other code runs simultaneously.
  3. Final Answer:

    It allows the Arduino to perform other tasks while blinking an LED. -> Option A
  4. Quick Check:

    Blink without delay = multitasking [OK]
Hint: Remember millis() tracks time without stopping code [OK]
Common Mistakes:
  • Thinking delay() lets other code run
  • Believing blink speed is faster with millis()
  • Assuming millis() uses less power
2. Which of the following code snippets correctly initializes the variable to store the last time the LED was toggled in the Blink without delay pattern?
easy
A. unsigned long previousMillis = 0;
B. int previousMillis = 0;
C. float previousMillis = 0.0;
D. boolean previousMillis = false;

Solution

  1. Step 1: Identify correct data type for millis()

    millis() returns an unsigned long value representing milliseconds.
  2. Step 2: Match variable type to millis()

    To store millis() values, use unsigned long to avoid overflow and negative values.
  3. Final Answer:

    unsigned long previousMillis = 0; -> Option A
  4. Quick Check:

    Use unsigned long for time tracking [OK]
Hint: Use unsigned long for millis() time variables [OK]
Common Mistakes:
  • Using int which can overflow quickly
  • Using float which is unnecessary and imprecise
  • Using boolean which can't store time
3. What will be the output behavior of the following Arduino code snippet using Blink without delay pattern?
const int ledPin = 13;
unsigned long previousMillis = 0;
const long interval = 1000;
bool ledState = false;

void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    ledState = !ledState;
    digitalWrite(ledPin, ledState ? HIGH : LOW);
  }
}
medium
A. The LED will blink rapidly without delay.
B. The LED on pin 13 will blink on and off every 1 second without stopping other code.
C. The LED will stay on permanently after 1 second.
D. The program will cause a compile error due to bool type.

Solution

  1. Step 1: Analyze timing logic

    The code checks if 1000 ms passed since last toggle, then flips ledState.
  2. Step 2: Understand LED toggle and output

    ledState toggles true/false every second, controlling LED on/off without delay blocking.
  3. Final Answer:

    The LED on pin 13 will blink on and off every 1 second without stopping other code. -> Option B
  4. Quick Check:

    Millis timing toggles LED every 1 second [OK]
Hint: Look for millis() interval check to predict blink timing [OK]
Common Mistakes:
  • Thinking bool causes compile error
  • Assuming LED stays on permanently
  • Confusing rapid blinking with 1-second interval
4. Identify the error in this Blink without delay code snippet:
const int ledPin = 13;
unsigned long previousMillis = 0;
const long interval = 1000;

void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    digitalWrite(ledPin, !digitalRead(ledPin));
  }
}
medium
A. The code will cause a runtime error due to digitalWrite logic.
B. Using > instead of >= in the if condition causes timing issues.
C. The variable previousMillis should be int, not unsigned long.
D. digitalRead() cannot be used on output pins.

Solution

  1. Step 1: Check use of digitalRead on output pin

    digitalRead() on an output pin is unreliable and not recommended for toggling.
  2. Step 2: Understand proper toggle method

    Better to track LED state in a variable rather than reading output pin state.
  3. Final Answer:

    digitalRead() cannot be used on output pins. -> Option D
  4. Quick Check:

    Don't use digitalRead on output pins [OK]
Hint: Avoid digitalRead on pins set as OUTPUT [OK]
Common Mistakes:
  • Thinking > vs >= causes major error
  • Believing previousMillis type is wrong
  • Assuming digitalWrite logic causes runtime error
5. You want to blink two LEDs independently using the Blink without delay pattern: LED1 every 500 ms and LED2 every 1000 ms. Which approach correctly manages both LEDs without blocking the program?
hard
A. Toggle LED1 every 500 ms and LED2 every 1000 ms using nested for loops.
B. Use one previousMillis variable and toggle both LEDs at the same time every 500 ms.
C. Use two separate previousMillis variables and check each interval independently in loop().
D. Use delay(500) for LED1 and delay(1000) for LED2 in sequence inside loop().

Solution

  1. Step 1: Understand independent timing needs

    Each LED needs its own timer variable to track its blinking interval separately.
  2. Step 2: Avoid blocking delays and incorrect loops

    Using delay() or nested loops blocks code and prevents independent blinking.
  3. Final Answer:

    Use two separate previousMillis variables and check each interval independently in loop(). -> Option C
  4. Quick Check:

    Separate timers for independent blinking [OK]
Hint: Track each LED's time separately with its own variable [OK]
Common Mistakes:
  • Using one timer for both LEDs
  • Using delay() which blocks code
  • Trying nested loops for timing