Arduino Basic Tutorial

millis() and delay() Function in Arduino With Examples

Introduction:

millis() and delay() Function in Arduino With Examples- Arduino, the popular open-source electronics platform, has revolutionized the world of DIY projects and automation. From simple blinking LEDs to complex robotic systems, Arduino provides a versatile environment for enthusiasts and professionals to bring their ideas to life. Central to Arduino programming is the management of time and delays, crucial for the precise control and synchronization of various components. In this article, we will explore millis() and delay() functions in Arduino.




millis() function in Arduino

The millis() function is a crucial tool in Arduino programming, offering precise timing control and enabling the implementation of non-blocking behavior. By understanding the benefits of millis(), developers can design more responsive and efficient applications. In this article, we will delve into the reasons for using millis() in Arduino and explore its advantages in detail.

Arduino boards are often employed in projects where timing is critical, such as controlling actuators, sampling sensors, or coordinating multiple tasks. However, using blocking functions like delay() can disrupt the desired timing and hinder responsiveness. This is where the millis() function comes into play.

The millis() function returns the number of milliseconds that have passed since the Arduino board started running. It relies on the microcontroller’s internal clock and provides a precise time reference for timing operations. Here are some key reasons why millis() is widely used in Arduino programming:

Non-Blocking Behavior:

 Unlike the delay() function, which halts the program’s execution, millis() allows for non-blocking programming. Non-blocking behavior ensures that the Arduino remains responsive, even during time-critical operations. By leveraging millis(), developers can create multitasking applications, where multiple tasks can be executed concurrently or at specific intervals.



Precise Timing Control:

The millis() function provides accurate timing control, making it suitable for applications that require precise synchronization or time-dependent operations. By comparing the current time obtained from millis() with predefined intervals, developers can trigger events, sample sensors, or control actions with high accuracy.

Avoiding Timing Drift:

Accurate timing is essential for many applications, but the internal clock of Arduino boards may not be perfectly precise. Using delay() can introduce timing inaccuracies and drift over time. On the other hand, millis() continuously updates based on the internal clock, compensating for any drift and providing a more reliable timing reference.

Real-Time Applications:

Arduino projects often involve real-time requirements, where timely response to external events or inputs is crucial. The non-blocking nature of millis() allows developers to handle events promptly without delaying other critical operations. This is particularly important for applications such as robotics, automation, and control systems.

Flexibility and Modularity:

By using millis() and non-blocking programming techniques, Arduino programs can be designed in a modular and flexible manner. Instead of relying on fixed delays, tasks can be scheduled and executed independently, providing modularity and allowing for easier modification and expansion of the codebase.

Energy Efficiency:

In battery-powered projects, optimizing power consumption is essential. Using millis() and non-blocking techniques can help minimize the time the Arduino spends in active states, allowing it to enter low-power modes when tasks are not actively running. This helps conserve energy and prolong battery life.

To fully leverage the advantages of millis() in Arduino programming, developers typically follow a non-blocking programming approach. This involves defining variables to store the last execution time of tasks, continuously checking the elapsed time using millis(), and executing tasks when the desired time intervals have passed.

By avoiding delay() and embracing millis(), developers can create more responsive, efficient, and versatile Arduino applications. The non-blocking behavior provided by millis() allows for multitasking, precise timing control, real-time responsiveness, modularity, and energy efficiency. Whether it’s controlling actuators, sampling sensors, or coordinating multiple tasks, millis() is an invaluable tool in the Arduino programmer’s arsenal.

In conclusion, millis() empowers Arduino developers to achieve accurate timing control, responsiveness, and concurrency in their projects. By adopting non-blocking programming techniques and utilizing millis(), applications can be designed to handle multiple tasks simultaneously, respond promptly to external events, and provide precise timing synchronization. This flexibility and control contribute to the development of robust and efficient Arduino applications across a wide range of domains.



Arduino millis() Function Programming examples:

Example: Blinking LED using Millis() Function in Arduino:

In this example, an LED is blinked without using the delay() function, allowing for non-blocking behavior.

In this example, the LED is blinked at a 1-second interval using the millis() function. By comparing the current time with the previous time stored in the previousMillis variable, the LED state is toggled when the interval has elapsed. Other tasks can be executed concurrently without blocking the program execution.

Example: using millis() function in Arduino implement Debouncing a Button Input

This example demonstrates how to debounce a button input using the millis() function to avoid false triggering caused by mechanical switch bouncing.

Explanation:

The BUTTON_PIN constant is defined with a value of 2, indicating that the button is connected to digital pin 2 on the Arduino board.

The DEBOUNCE_DELAY constant is defined with a value of 50, representing the debounce delay in milliseconds. It is used to ensure stable button readings by introducing a small delay to filter out any bouncing or noise when the button is pressed or released.

The lastButtonStateChangeTime variable is declared as an unsigned long to store the time of the last button state change.

The buttonState variable is declared as a bool to store the current debounced button state, initialized as HIGH (not pressed).

Inside the loop() function:

The raw button state is read using digitalRead(BUTTON_PIN) and stored in rawButtonState.

If the raw button state is different from the debounced button state, it means the button state has changed. In this case, the lastButtonStateChangeTime is updated to the current time using millis() to record the time of the state change.

After the debounce delay has passed, which is determined by comparing the difference between the current time and lastButtonStateChangeTime to DEBOUNCE_DELAY, the debounced button state is updated with the raw button state. This ensures a stable button state after the debounce delay.

You can add your button action code inside the respective conditions (buttonState == LOW for button pressed, buttonState == HIGH for button released) to perform the desired actions based on the button’s state.

Using the millis() function for debouncing allows you to achieve stable button readings without blocking the execution of other tasks, making your Arduino program more responsive.



Example: Timing a Task Execution using millis() function in Arduino:

This example demonstrates how to time the execution of a specific task using the millis() function.

In this example, a task is executed for a specific duration using the millis() function. When the task is not running, it is started by recording the start time. The task runs until the specified duration has passed, and then it is reset to allow for subsequent executions. Other tasks can be performed concurrently while the timing and execution of this specific task are managed.

These examples showcase how the millis() function can be used in various Arduino programming scenarios, such as non-blocking blinking, button debouncing, and timing task execution. By utilizing millis(), developers can achieve precise timing control, non-blocking behavior, and implement time-dependent operations effectively.

delay() Function in Arduino

Using the delay() function in Arduino can lead to unresponsive behavior and limit the ability to perform multiple tasks concurrently. To avoid these drawbacks, it is advisable to skip the use of delay() and adopt non-blocking programming techniques. This article will delve into the reasons behind skipping delay() and explain the benefits of non-blocking programming in Arduino.

Arduino boards are often used in projects where responsiveness and multitasking are crucial. Whether it’s reading inputs, responding to events, or executing various functions, the ability to handle multiple tasks simultaneously is highly desirable. However, the delay() function can hinder this multitasking capability.

When delay() is executed, it pauses the program for a specified duration, during which no other code can be executed. This means that the Arduino becomes unresponsive and unable to perform any tasks until the delay period elapses. This behavior is not ideal for applications where timely response and concurrency are necessary.

By adopting non-blocking programming techniques, Arduino programs can overcome the limitations imposed by delay() and achieve better responsiveness and multitasking capabilities. One of the key tools in non-blocking programming is the millis() function.

The millis() function returns the number of milliseconds since the Arduino board started running. It can be used to track time intervals and compare them to execute tasks at specific times without blocking the execution of other code.




Instead of relying on delay(), non-blocking programming utilizes the millis() function to monitor the elapsed time and decide when to perform specific tasks. By comparing the current time with predefined time intervals, tasks can be executed independently, allowing for multitasking behavior.

To implement non-blocking programming, variables are defined to store the time intervals for each task and to track the last time each task was executed. Inside the loop() function, the current time is obtained using millis(), and based on the time intervals defined, tasks are executed when the appropriate time has passed.

Unlike delay(), non-blocking programming allows the Arduino to continue executing other code while tasks are being performed. This improves responsiveness and ensures that the Arduino can handle multiple tasks simultaneously without becoming unresponsive.

In addition to responsiveness, another advantage of skipping delay() is the ability to achieve precise timing in time-critical operations. The internal clock of the Arduino may not be perfectly accurate, and using delay() can introduce timing inaccuracies and drift. Non-blocking programming techniques, on the other hand, provide more precise control over timing, enabling accurate execution of time-sensitive operations.

Real-time requirements further highlight the drawbacks of using delay(). In applications where the Arduino needs to respond promptly to events or time-sensitive inputs, delay() can disrupt the desired real-time behavior. By adopting non-blocking programming, the Arduino can handle inputs, events, and tasks in a timely manner, maintaining responsiveness and meeting the requirements of real-time applications.

Moreover, non-blocking programming techniques enable the implementation of multitasking behavior in Arduino. With limited resources, such as memory and processing power, Arduino boards can benefit from executing multiple tasks concurrently. By using millis() and non-blocking programming, tasks can be scheduled and executed independently, providing the illusion of parallel execution.

In summary, skipping the use of delay() in Arduino and adopting non-blocking programming techniques offers several advantages. It allows for better responsiveness, as the Arduino can continue executing tasks while avoiding unresponsive periods. Precise timing control is achievable, ensuring accurate execution of time-critical operations. Real-time requirements can be met, with the Arduino being able to promptly respond to events and inputs. Additionally, multitasking behavior can be implemented, leveraging the limited resources of Arduino boards more efficiently.

By embracing non-blocking programming and leveraging the power of the millis() function, Arduino projects can be enhanced in terms of responsiveness, timing accuracy, real-time capabilities, and multitasking. These benefits enable the development of more robust and versatile applications, making the most out of the Arduino platform.



Arduino delay() Function Programming examples:

Example 1: blink an LED based on button input using the delay() function

Explanation:

In this example, an LED is connected to pin 13, and a button is connected to pin 2. The setup() function is responsible for setting the LED pin as an output and the button pin as an input. The loop() function continuously reads the state of the button using digitalRead(). If the button is pressed (i.e., the button pin reads HIGH), it turns on the LED, waits for 1 second using delay(), turns off the LED, and then waits for another 1 second before repeating the process. If the button is not pressed, the LED remains off.

When the button is pressed, the LED will blink with a 1-second interval. If the button is not pressed, nothing happens. This example demonstrates a basic implementation of blinking an LED based on a button input using the delay() function.

Example: Control Servo using delay() function in Arduino:

Explanation:

This example demonstrates servo motor control. It sets the servo motor to 90 degrees, waits for 1 second, sets the servo to 0 degrees, and then waits for another 1 second before repeating the process.



Example: Send command to Serial monitor using delay() function in Arduino:

Explanation:

This example showcases serial communication. It continuously sends the message “Hello, World!” over the serial port at a baud rate of 9600, with a delay of 1 second between each message.

Example: using delay() function in Arduino implement Button Debouncing:

Explanation:

This example demonstrates button debouncing, which is used to handle the erratic behavior of buttons. It reads the state of a button connected to pin 2, introduces a delay of 100 milliseconds using delay(), and performs certain actions when the button is pressed, avoiding false triggers caused by button bouncing.

Example: how to create Sequential LED Lighting using delay() function in Arduino:

Explanation:

This example sequentially lights up four LEDs connected to pins 2, 3, 4, and 5. It turns on each LED one by one, introduces a delay of 500 milliseconds using delay(), and then turns off the LED before moving to the next one.

These examples demonstrate various use cases of the delay() function in Arduino programming, including timing events, controlling actuators, serial communication, button debouncing, and sequential actions.



Example: Multiple Tasks with Different Intervals

Here’s an example where multiple tasks with different time intervals are executed concurrently using non-blocking programming:

Explanation:

 In this example, we have two tasks: Task 1 and Task 2, with intervals of 1000 milliseconds (1 second) and 500 milliseconds respectively. We use two variables, task1PreviousMillis and task2PreviousMillis, to store the previous time when each task was executed.

Inside the loop() function, we use the millis() function to get the current time in milliseconds. We then check if enough time has elapsed since the previous execution of each task by subtracting the previous time from the current time and comparing it to the respective interval.

If the elapsed time exceeds the interval for a particular task, we update the previous time with the current time and perform the actions associated with that task.

By using this approach, you can handle multiple tasks with different intervals without blocking the execution of other tasks or the main loop using delay(). This technique is commonly known as non-blocking programming and allows your Arduino program to be more responsive and handle multiple tasks simultaneously.

what does millis() do in Arduino?

In Arduino programming, the millis() function is used to obtain the number of milliseconds that have passed since the Arduino board started running. It provides a way to keep track of time without using delay functions that would block the execution of other tasks.

Here’s an example to demonstrate the usage of millis():

In this example, the LED connected to pin 13 will blink every second using millis(). The currentMillis variable is assigned the value returned by millis() each time through the loop(). It then compares the difference between currentMillis and previousMillis to the specified interval. If the interval has passed, the LED state is toggled, and the previousMillis is updated with the current time.

By using millis(), you can perform non-blocking timing operations in your Arduino code, allowing you to perform multiple tasks simultaneously without pausing the execution.

What does delay() function in Arduino?

In Arduino programming, the delay() function is used to pause the execution of the program for a specified number of milliseconds. It provides a simple way to introduce delays in your code. However, it should be used with caution because it blocks the execution of other tasks during the delay period.

Here’s an example to demonstrate the usage of delay():

In this example, the LED connected to pin 13 will blink on and off with a delay of 1 second using delay(). The digitalWrite() function is used to set the LED pin to either HIGH (on) or LOW (off), and the delay() function is used to pause the program for the specified number of milliseconds.

During the delay() period, the Arduino does not execute any other instructions. It waits until the specified time has passed before moving on to the next line of code. This means that other tasks, such as reading sensor data or responding to external events, will be paused during the delay.

While delay() is simple to use, it can limit the responsiveness and multitasking capabilities of your Arduino program. If you need to perform multiple tasks simultaneously or maintain more precise timing, it is recommended to use the millis() function along with non-blocking techniques, as shown in the previous example.

Can I use delay with millis?

Yes, you can use delay() together with millis() to create more flexible and precise timing in your Arduino programs. This combination allows you to introduce delays while still maintaining the ability to perform other tasks simultaneously.

Here’s an example that demonstrates the usage of delay() with millis():

In this example, the LED connected to pin 13 will blink on and off with an interval of 1 second using millis(). After each LED state change, a delay() of 100 milliseconds is introduced. This additional delay allows you to control the duration of each LED state while still maintaining precise timing using millis().

By combining millis() with delay(), you can introduce shorter pauses within your timed operations without blocking the execution of other tasks. It enables you to perform other operations or respond to external events during the smaller delay periods, enhancing the responsiveness and multitasking capabilities of your Arduino program.

What is the speed of Millis() in Arduino?

The millis() function in Arduino provides the current value of the system timer, which increments every millisecond. The resolution of millis() is approximately 1 millisecond, meaning it can accurately measure time intervals as small as 1 millisecond.

However, it’s important to note that the actual accuracy of millis() can vary slightly depending on the Arduino board and its clock source. While most Arduino boards provide a reasonably accurate and consistent timing, there may be some variations between different boards.

The Arduino Uno, for example, uses a quartz crystal oscillator as its clock source, which typically provides good accuracy. The ATmega328P microcontroller on the Uno board has a 16 MHz clock, meaning the millis() function is updated every 1 millisecond.

It’s worth mentioning that millis() relies on the internal timer of the microcontroller, and certain factors such as interrupt handling and other tasks running on the Arduino can introduce small variations in timing. However, for most applications, the accuracy and speed of millis() are sufficient for timekeeping and basic timing operations.

If you require higher precision timing, you may consider using external hardware or more advanced techniques like hardware timers or interrupts.

what is the difference between millis() and micros() in Arduino?

In Arduino, both millis() and micros() are functions used to measure time, but they differ in the units of time they provide.

millis() Function:

The millis() function returns the number of milliseconds that have passed since the Arduino board started running. It has a resolution of approximately 1 millisecond, meaning it can accurately measure time intervals as small as 1 millisecond. This function is commonly used for tasks that require longer timing intervals or delays, such as blinking an LED every second.

micros() Function:

The micros() function, on the other hand, returns the number of microseconds that have passed since the Arduino board started running. It has a higher resolution than millis(), with a granularity of approximately 4 microseconds (depending on the Arduino board). This function is used for tasks that require more precise timing, such as measuring short intervals or controlling precise timings of events.

Here’s an example to illustrate the difference between millis() and micros():

In this example, the millis() and micros() functions are called within the loop() function. The values returned by both functions are then printed to the Serial Monitor. You will notice that millis() increments by 1000 every second (as delay(1000) is used), while micros() increments by 1000000 (1000 * 1000) every second.

In summary, millis() provides timing in milliseconds with a resolution of approximately 1 millisecond, suitable for longer timing intervals. micros() provides timing in microseconds with a higher resolution, suitable for precise and shorter timing intervals.

millis() vs delay() in Arduino

millis() and delay() are two functions in Arduino that are commonly used for timing and introducing delays in your code. However, they have different characteristics and usage scenarios:

millis() Function:

The millis() function returns the number of milliseconds that have passed since the Arduino board started running. It allows you to keep track of time without blocking the execution of other tasks. millis() is often used in conjunction with conditional statements to create non-blocking delays and time-based operations. It is useful when you need to perform multiple tasks simultaneously or maintain responsiveness in your program. By comparing the current time returned by millis() with a stored previous time, you can determine if a specific time interval has passed and trigger actions accordingly.

Example:

delay() Function:

The delay() function pauses the execution of your code for a specified number of milliseconds. During the delay period, the Arduino does not execute any other instructions, effectively blocking the program’s execution. It is simpler to use but can limit the responsiveness and multitasking capabilities of your program. delay() is commonly used for simple delays, such as blinking an LED at a fixed rate or introducing pauses in a sequence of actions.

Example:

In summary, millis() is suitable for non-blocking timing operations and multitasking, allowing you to perform other tasks while keeping track of time. On the other hand, delay() is a simple way to introduce fixed delays but can cause the Arduino to be unresponsive during the delay period. The choice between them depends on the requirements of your specific application.

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button