Hey everyone,
I’m a bit confused about the delay() and millis() functions in Arduino. What’s the difference between them, and when should I use millis() instead of delay()?
In-depth explanation of delay() VS millis() in Arduino:
What is delay()?
The delay(ms) function is a simple way to pause your program for a specific duration (in milliseconds). While using delay(), the microcontroller does nothing except wait, effectively blocking all other code execution.
Example: Blinking an LED using delay()
Here’s a basic example of using delay() to blink an LED every second:
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
}
This works, but there's a major drawback: nothing else can run while delay() is active. If you need to read a sensor, receive serial input, or perform another task during the delay, it won’t be possible.
What is millis()?
The millis() function returns the number of milliseconds since the Arduino board was powered on or reset. Unlike delay(), millis() does not stop program execution. Instead, it allows you to track elapsed time while still performing other tasks.
Example: Blinking an LED without delay() using millis()
Instead of stopping everything for a delay, we can check if enough time has passed and then toggle the LED.
const int ledPin = 13;
unsigned long previousMillis = 0; // Store the last time LED was updated
const long interval = 1000; // Blink interval (1 second)
void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
unsigned long currentMillis = millis(); // Get the current time
// Check if 1000ms (1 second) has passed since the last LED update
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis; // Save the last time LED changed state
digitalWrite(ledPin, !digitalRead(ledPin)); // Toggle LED state
}
}
In this example:
The LED toggles every second without blocking the loop.
Other code can run simultaneously, such as reading sensors, handling inputs, or controlling motors.
When should you use millis() instead of delay()?
You should use millis() when:
1. You need to run multiple tasks at once (e.g., read sensors while controlling LEDs).
2. You need a responsive program that can handle inputs in real time.
3. You want to avoid blocking the execution of other parts of the code.
4. You are working with interrupts, communication protocols, or multitasking logic.
delay() is only suitable for very simple programs where no other tasks need to run during the wait time.
Multitasking with millis()
Let’s say we want to:
1. Blink an LED every 1 second.
2. Read a button press every 100ms.
3. Print a message every 2 seconds.
Using millis(), we can handle all three tasks without blocking execution:
const int ledPin = 13;
const int buttonPin = 2;
unsigned long previousLedMillis = 0;
unsigned long previousButtonMillis = 0;
unsigned long previousMessageMillis = 0;
const long ledInterval = 1000;
const long buttonInterval = 100;
const long messageInterval = 2000;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
Serial.begin(9600);
}
void loop() {
unsigned long currentMillis = millis();
// Blink LED every 1 second
if (currentMillis - previousLedMillis >= ledInterval) {
previousLedMillis = currentMillis;
digitalWrite(ledPin, !digitalRead(ledPin));
}
// Check button state every 100ms
if (currentMillis - previousButtonMillis >= buttonInterval) {
previousButtonMillis = currentMillis;
if (digitalRead(buttonPin) == LOW) {
Serial.println("Button Pressed!");
}
}
// Print a message every 2 seconds
if (currentMillis - previousMessageMillis >= messageInterval) {
previousMessageMillis = currentMillis;
Serial.println("Hello from Arduino!");
}
}
This allows everything to run independently without interference, making the code much more efficient and responsive.
@ankunegi Thank you for such a detailed explanation. Is there any downside to using millis()? I mean, why should I even use delay() then, when millis() is a better option?
Great question! This is something a lot of people new to Arduino run into. Here’s a simple breakdown:
- delay() pauses the entire program for the specified amount of time (in milliseconds). So, if you use delay(1000), your Arduino will do nothing for 1 second. This is fine for very simple tasks, like blinking an LED.
- millis(), on the other hand, doesn’t stop the program. It simply returns the number of milliseconds that have passed since the Arduino was powered on or reset. You can use it to keep track of time without pausing the rest of your code.
When to use each:
- Use delay() if your program only has one task and you don’t mind it pausing everything else (e.g., blinking an LED with nothing else happening).
- Use millis() when you need your code to be non-blocking. This is essential for projects that involve multiple tasks happening simultaneously (e.g., reading a sensor while controlling an LED).
Let me know if you need an example code for better clarity!