Bird
Raised Fist0
Arduinoprogramming~20 mins

Multiple timed events with millis() in Arduino - Practice Problems & Coding Challenges

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
Challenge - 5 Problems
🎖️
Millis Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
Predict Output
intermediate
2:00remaining
Output of multiple timed events with millis()
What will be the output on the serial monitor after running this Arduino code for about 3500 milliseconds?
Arduino
unsigned long previousMillis1 = 0;
unsigned long previousMillis2 = 0;
const long interval1 = 1000;
const long interval2 = 2000;

void setup() {
  Serial.begin(9600);
}

void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis1 >= interval1) {
    previousMillis1 = currentMillis;
    Serial.println("Event 1");
  }

  if (currentMillis - previousMillis2 >= interval2) {
    previousMillis2 = currentMillis;
    Serial.println("Event 2");
  }
}
AEvent 1\nEvent 1\nEvent 2\nEvent 1
BEvent 1\nEvent 2\nEvent 1\nEvent 2
CEvent 1\nEvent 1\nEvent 1\nEvent 2
DEvent 1\nEvent 2\nEvent 1\nEvent 1
Attempts:
2 left
💡 Hint
Think about how often each event triggers based on its interval and the elapsed time.
🧠 Conceptual
intermediate
1:30remaining
Understanding millis() rollover
What happens when the Arduino millis() function reaches its maximum value and rolls over to zero? How should you write your timing code to handle this correctly?
AThe millis() stops counting and timing code freezes until reset.
BThe millis() resets to zero and timing code breaks unless you reset the Arduino.
CThe millis() resets to zero and timing code using subtraction with unsigned longs still works correctly.
DThe millis() returns negative values causing errors in timing calculations.
Attempts:
2 left
💡 Hint
Think about how unsigned arithmetic works in C++.
🔧 Debug
advanced
2:30remaining
Why does this multiple event timing code fail?
This Arduino code is supposed to blink two LEDs at different intervals using millis(), but only one LED blinks. What is the problem?
Arduino
unsigned long previousMillis1 = 0;
unsigned long previousMillis2 = 0;
const long interval1 = 500;
const long interval2 = 1000;

void setup() {
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
}

void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis1 >= interval1) {
    previousMillis1 = currentMillis;
    digitalWrite(9, !digitalRead(9));
  }

  if (currentMillis - previousMillis2 >= interval2) {
    previousMillis2 = currentMillis;
    digitalWrite(10, !digitalRead(10));
  }
}
AThe intervals are too close, causing timing conflicts.
BBoth if statements use the same previousMillis variable, so the second condition never becomes true separately.
CdigitalRead() cannot be used inside loop for LEDs.
DpinMode() must be called inside loop, not setup.
Attempts:
2 left
💡 Hint
Check how previousMillis is updated in both conditions.
📝 Syntax
advanced
1:30remaining
Identify the syntax error in this millis() timing code
Which option contains the correct syntax to check if 1000 milliseconds have passed using millis()?
Aif (millis() - previousMillis >= 1000) { previousMillis = millis(); }
Bif (millis() - previousMillis => 1000) { previousMillis = millis(); }
Cif (millis() - previousMillis = 1000) { previousMillis = millis(); }
Dif (millis() - previousMillis >= 1000); { previousMillis = millis(); }
Attempts:
2 left
💡 Hint
Check the comparison operators and semicolon placement.
🚀 Application
expert
3:00remaining
Implement three independent timed events with millis()
You want to toggle three LEDs connected to pins 3, 5, and 6 at intervals of 300 ms, 700 ms, and 1500 ms respectively using millis(). Which code snippet correctly implements this without blocking?
A
unsigned long prev1=0, prev2=0, prev3=0;
void loop() {
  unsigned long now=millis();
  if(now - prev1 >= 300) { prev1=now; digitalWrite(3, LOW); }
  if(now - prev2 >= 700) { prev2=now; digitalWrite(5, LOW); }
  if(now - prev3 >= 1500) { prev3=now; digitalWrite(6, LOW); }
}
B
unsigned long prev=0;
void loop() {
  unsigned long now=millis();
  if(now - prev >= 300) { prev=now; digitalWrite(3, !digitalRead(3)); }
  if(now - prev >= 700) { prev=now; digitalWrite(5, !digitalRead(5)); }
  if(now - prev >= 1500) { prev=now; digitalWrite(6, !digitalRead(6)); }
}
C
unsigned long prev1=0, prev2=0, prev3=0;
void loop() {
  unsigned long now=millis();
  if(now - prev1 >= 300) { prev1=now; digitalWrite(3, HIGH); }
  if(now - prev2 >= 700) { prev2=now; digitalWrite(5, HIGH); }
  if(now - prev3 >= 1500) { prev3=now; digitalWrite(6, HIGH); }
}
D
unsigned long prev1=0, prev2=0, prev3=0;
void loop() {
  unsigned long now=millis();
  if(now - prev1 >= 300) { prev1=now; digitalWrite(3, !digitalRead(3)); }
  if(now - prev2 >= 700) { prev2=now; digitalWrite(5, !digitalRead(5)); }
  if(now - prev3 >= 1500) { prev3=now; digitalWrite(6, !digitalRead(6)); }
}
Attempts:
2 left
💡 Hint
Each LED needs its own timer variable and toggling the state.

Practice

(1/5)
1. What is the main advantage of using millis() for timing multiple events in Arduino instead of delay()?
easy
A. It resets the Arduino automatically.
B. It stops the program until the time passes.
C. It makes the program run slower.
D. It allows the program to run other tasks while waiting.

Solution

  1. Step 1: Understand delay() behavior

    delay() pauses the whole program, stopping all other actions.
  2. Step 2: Understand millis() advantage

    millis() returns elapsed time without stopping the program, so other tasks can run simultaneously.
  3. Final Answer:

    It allows the program to run other tasks while waiting. -> Option D
  4. Quick Check:

    millis() enables multitasking [OK]
Hint: Remember: delay() stops, millis() doesn't [OK]
Common Mistakes:
  • Thinking millis() pauses the program
  • Confusing delay() with non-blocking timing
  • Believing millis() resets Arduino
2. Which of the following is the correct way to declare a variable to store the last time an event occurred using millis()?
easy
A. unsigned long lastEventTime = 0;
B. int lastEventTime = 0;
C. float lastEventTime = 0.0;
D. char lastEventTime = '0';

Solution

  1. Step 1: Identify the correct data type for time

    Since millis() returns an unsigned long value, the variable must be unsigned long.
  2. Step 2: Check variable initialization

    Initializing to 0 is correct to mark the start time.
  3. Final Answer:

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

    Use unsigned long for millis() times [OK]
Hint: Use unsigned long for time variables with millis() [OK]
Common Mistakes:
  • Using int which can overflow quickly
  • Using float which is not precise for time
  • Using char which is for characters, not numbers
3. What will be the output of the following Arduino code snippet if millis() returns 5000 at the moment of checking?
unsigned long previousMillis = 3000;
unsigned long interval = 1500;

if (millis() - previousMillis >= interval) {
  Serial.println("Event triggered");
} else {
  Serial.println("Waiting");
}
medium
A. Waiting
B. No output
C. Event triggered
D. Compilation error

Solution

  1. Step 1: Calculate elapsed time

    Elapsed time = 5000 (current millis) - 3000 (previousMillis) = 2000 ms.
  2. Step 2: Compare elapsed time with interval

    Interval is 1500 ms. Since 2000 >= 1500, the condition is true, so "Event triggered" should print.
  3. Final Answer:

    Event triggered -> Option C
  4. Quick Check:

    Elapsed time 2000 >= 1500 triggers event [OK]
Hint: Subtract previousMillis from millis() to check elapsed time [OK]
Common Mistakes:
  • Mixing up >= and > operators
  • Forgetting to subtract previousMillis
  • Assuming output without calculation
4. Identify the error in this code snippet that tries to blink two LEDs at different intervals using millis():
unsigned long previousMillis1 = 0;
unsigned long previousMillis2 = 0;
const long interval1 = 1000;
const long interval2 = 2000;

void loop() {
  if (millis() - previousMillis1 >= interval1) {
    digitalWrite(LED1, !digitalRead(LED1));
    previousMillis1 = millis();
  }
  if (millis() - previousMillis1 >= interval2) {
    digitalWrite(LED2, !digitalRead(LED2));
    previousMillis2 = millis();
  }
}
medium
A. LED pins are not defined.
B. Second if condition uses previousMillis1 instead of previousMillis2.
C. Intervals should be unsigned long, not long.
D. digitalWrite cannot toggle LEDs.

Solution

  1. Step 1: Check timing variables in conditions

    The second if condition incorrectly uses previousMillis1 instead of previousMillis2, causing wrong timing for LED2.
  2. Step 2: Understand impact of error

    This mistake means LED2 timing depends on LED1 timing, so LED2 won't blink at its own interval.
  3. Final Answer:

    Second if condition uses previousMillis1 instead of previousMillis2. -> Option B
  4. Quick Check:

    Each event needs its own previousMillis variable [OK]
Hint: Use separate previousMillis for each timed event [OK]
Common Mistakes:
  • Reusing the same previousMillis variable for multiple events
  • Not updating previousMillis after event
  • Confusing interval variables
5. You want to control three LEDs blinking at 500ms, 1000ms, and 1500ms intervals respectively without using delay(). Which approach correctly manages all three timed events using millis()?
hard
A. Use three separate previousMillis variables and check each with its own interval inside loop().
B. Use one previousMillis variable and reset it after each LED toggles.
C. Use delay(500) and toggle all LEDs together.
D. Use millis() only once and toggle LEDs based on dividing millis() by intervals.

Solution

  1. Step 1: Understand independent timing needs

    Each LED needs its own timer to blink independently at different intervals.
  2. Step 2: Evaluate options

    Use three separate previousMillis variables and check each with its own interval inside loop(), allowing independent timing without blocking.
  3. Final Answer:

    Use three separate previousMillis variables and check each with its own interval inside loop(). -> Option A
  4. Quick Check:

    Separate timers for each event [OK]
Hint: Assign each event its own timer variable for independent control [OK]
Common Mistakes:
  • Using one timer for all events causing sync issues
  • Using delay which blocks other events
  • Trying to calculate toggles from one millis() value without state