Index
In Arduino, managing timing is essential for controlling the flow of a program and coordinating tasks. There are two common ways to handle timing:
- delay(): Pauses the program for a specified amount of time, which can be useful but blocks other code from running.
- millis(): A non-blocking alternative that allows other code to run while keeping track of elapsed time.
1. delay()
: Basic Timing with Blocking
The delay()
function pauses the entire program for a set amount of milliseconds (1 second = 1000 milliseconds). This can be helpful for simple timing tasks but is limiting if you want multiple things to happen simultaneously.
Example 1: Blinking an LED with delay()
In this example, an LED blinks every second using delay()
.
const int ledPin = 13; // Built-in LED on pin 13
void setup() {
pinMode(ledPin, OUTPUT); // Set LED pin as an output
}
void loop() {
digitalWrite(ledPin, HIGH); // Turn the LED on
delay(1000); // Wait for 1 second (1000 ms)
digitalWrite(ledPin, LOW); // Turn the LED off
delay(1000); // Wait for 1 second
}
Explanation
digitalWrite(ledPin, HIGH);
turns the LED on.delay(1000);
waits for 1 second.digitalWrite(ledPin, LOW);
turns the LED off, followed by anotherdelay(1000);
to keep it off for 1 second.
Limitations: During the delay()
period, the Arduino is unresponsive and cannot perform other tasks.
2. Non-blocking Timing with millis()
The millis()
function provides a way to keep track of elapsed time without stopping the program. It returns the number of milliseconds since the Arduino started running the program. This allows us to track time intervals and control timing without blocking other code from running.
Example 2: Blinking an LED with millis()
(Non-blocking)
This example accomplishes the same task (blinking an LED) but uses millis()
instead, allowing other code to run in parallel.
const int ledPin = 13; // Built-in LED on pin 13
unsigned long previousMillis = 0; // Stores the last time the LED was updated
const long interval = 1000; // Interval at which to blink (1000 ms)
void setup() {
pinMode(ledPin, OUTPUT); // Set LED pin as an output
}
void loop() {
unsigned long currentMillis = millis(); // Get the current time
// Check if the interval has passed
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis; // Save the last time the LED was updated
// Toggle the LED state
int ledState = digitalRead(ledPin); // Read the current state of the LED
digitalWrite(ledPin, !ledState); // Set it to the opposite state
}
// Other code can run here without being affected by the LED timing
}
Explanation
unsigned long currentMillis = millis();
: Reads the current time in milliseconds.if (currentMillis - previousMillis >= interval)
: Checks if the specified interval (1 second) has passed since the last time the LED changed state.previousMillis = currentMillis;
: UpdatespreviousMillis
to the current time.digitalWrite(ledPin, !ledState);
: Toggles the LED’s state, switching it from on to off or vice versa.
This approach allows other tasks to execute in the loop()
function without being paused by delay()
.
Combining millis()
with Multiple Timers
Using millis()
also allows you to run multiple timers simultaneously. Here’s an example where two LEDs blink at different intervals without interfering with each other.
Example 3: Two LEDs with Different Intervals
const int ledPin1 = 12; // LED on pin 12
const int ledPin2 = 13; // LED on pin 13
unsigned long previousMillis1 = 0;
unsigned long previousMillis2 = 0;
const long interval1 = 500; // Blink interval for LED 1 (500 ms)
const long interval2 = 1000; // Blink interval for LED 2 (1000 ms)
void setup() {
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
}
void loop() {
unsigned long currentMillis = millis();
// Timer for LED 1
if (currentMillis - previousMillis1 >= interval1) {
previousMillis1 = currentMillis;
digitalWrite(ledPin1, !digitalRead(ledPin1)); // Toggle LED 1
}
// Timer for LED 2
if (currentMillis - previousMillis2 >= interval2) {
previousMillis2 = currentMillis;
digitalWrite(ledPin2, !digitalRead(ledPin2)); // Toggle LED 2
}
}
Explanation
Each LED has its own previousMillis
and interval
, allowing them to blink independently. This lets multiple events be timed without any blocking.
Key Takeaways
delay()
is useful for simple timing but stops other code from running.millis()
offers a non-blocking approach to timing, ideal for running multiple tasks simultaneously.
Using millis()
enables more responsive and versatile projects, particularly useful when you need multiple actions to happen at different intervals.