In Arduino, time-related functions allow you to manage delays, measure intervals, and execute actions based on timing. These functions are critical for applications like blinking LEDs, managing sensor data, or creating clocks.
This tutorial introduces the built-in time functions in Arduino, explains how to use them, and provides practical examples.
Table of Contents
1. What Are Time Functions in Arduino?
Time functions in Arduino allow you to:
- Create delays.
- Measure elapsed time.
- Perform tasks at specific intervals.
2. Built-in Time Functions
2.1 millis()
- Returns the number of milliseconds since the Arduino board started running the current program.
- Rolls over to 0 after approximately 50 days.
Example: Print Milliseconds
void setup() { Serial.begin(9600); } void loop() { Serial.println(millis()); // Print the elapsed time in milliseconds delay(1000); // Wait for 1 second }
2.2 micros()
- Returns the number of microseconds since the program started.
- Rolls over to 0 after approximately 70 minutes.
Example: Print Microseconds
void setup() { Serial.begin(9600); } void loop() { Serial.println(micros()); // Print the elapsed time in microseconds delay(1000); // Wait for 1 second }
2.3 delay()
- Pauses the program for a specified number of milliseconds.
- Blocks further code execution during the delay.
Example: Blink an LED Using delay()
const int ledPin = 13; void setup() { pinMode(ledPin, OUTPUT); } void loop() { digitalWrite(ledPin, HIGH); // Turn LED on delay(1000); // Wait for 1 second digitalWrite(ledPin, LOW); // Turn LED off delay(1000); // Wait for 1 second }
2.4 delayMicroseconds()
- Pauses the program for a specified number of microseconds.
- Useful for high-speed operations.
Example: Generate a Square Wave
const int ledPin = 13; void setup() { pinMode(ledPin, OUTPUT); } void loop() { digitalWrite(ledPin, HIGH); delayMicroseconds(500); // Wait for 500 microseconds digitalWrite(ledPin, LOW); delayMicroseconds(500); // Wait for 500 microseconds }
3. Using millis() for Non-Blocking Timing
millis() is commonly used for non-blocking timing. Unlike delay(), it allows other parts of the program to run during the interval.
Example: Non-Blocking LED Blink
const int ledPin = 13; unsigned long previousMillis = 0; const long interval = 1000; // 1 second void setup() { pinMode(ledPin, OUTPUT); } void loop() { unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; // Save the last time the LED was toggled digitalWrite(ledPin, !digitalRead(ledPin)); // Toggle LED } }
4. Practical Examples
4.1 Blinking an LED at Different Intervals
const int ledPin1 = 13; const int ledPin2 = 12; unsigned long previousMillis1 = 0; unsigned long previousMillis2 = 0; const long interval1 = 500; // Blink every 500ms const long interval2 = 1000; // Blink every 1000ms void setup() { pinMode(ledPin1, OUTPUT); pinMode(ledPin2, OUTPUT); } void loop() { unsigned long currentMillis = millis(); if (currentMillis - previousMillis1 >= interval1) { previousMillis1 = currentMillis; digitalWrite(ledPin1, !digitalRead(ledPin1)); } if (currentMillis - previousMillis2 >= interval2) { previousMillis2 = currentMillis; digitalWrite(ledPin2, !digitalRead(ledPin2)); } }
4.2 Measuring Time Intervals
unsigned long startTime; void setup() { Serial.begin(9600); startTime = millis(); // Record the start time } void loop() { unsigned long elapsedTime = millis() - startTime; // Calculate elapsed time Serial.print("Elapsed Time: "); Serial.print(elapsedTime); Serial.println(" ms"); delay(1000); // Update every second }
4.3 Simple Stopwatch
const int startStopButton = 2; const int resetButton = 3; unsigned long startTime = 0; unsigned long elapsedTime = 0; bool running = false; void setup() { pinMode(startStopButton, INPUT_PULLUP); pinMode(resetButton, INPUT_PULLUP); Serial.begin(9600); } void loop() { if (digitalRead(startStopButton) == LOW) { delay(200); // Debounce if (!running) { startTime = millis() - elapsedTime; // Start or resume stopwatch running = true; } else { elapsedTime = millis() - startTime; // Pause stopwatch running = false; } } if (digitalRead(resetButton) == LOW) { delay(200); // Debounce elapsedTime = 0; running = false; } unsigned long displayTime = running ? millis() - startTime : elapsedTime; Serial.print("Elapsed Time: "); Serial.print(displayTime); Serial.println(" ms"); delay(100); // Refresh display }
5. Best Practices for Using Time Functions
- Use millis() for Non-Blocking Code:
- Avoid delay() in critical applications where other tasks need to run simultaneously.
- Handle millis() Rollover:
- millis() resets to 0 after ~50 days, but using subtraction (currentMillis – previousMillis) ensures rollover doesn’t cause issues.
- Optimize Microsecond Delays:
- Use delayMicroseconds() for short delays; avoid delay() for intervals under 1ms.
- Avoid Long Blocking Delays:
- Long delay() calls can make the program unresponsive. Use millis() for better control.
- Synchronize Timing for Multiple Tasks:
- Maintain separate timing variables for different tasks.
Conclusion
Time functions in Arduino are essential for creating responsive and efficient applications. Whether you’re blinking LEDs, measuring time intervals, or designing non-blocking programs, understanding how to use millis(), micros(), and delay() effectively will help you build robust projects.
For more details, visit the official Arduino reference.