> For the complete documentation index, see [llms.txt](https://monasheng.gitbook.io/zerotohero/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://monasheng.gitbook.io/zerotohero/arduino-zero-to-hero/core-skills/timers.md).

# Timers

{% embed url="<https://youtu.be/cjV-YpAu0_A>" %}

## Motivation

It is often the case that you may wish to execute one or several blocks of code *on a regular interval.* Perhaps you want to blink an LED at a particular frequency, or take input measurements on some interval.

Additionally, while Arduino boards are relatively powerful given their cost, size, and functionality, they do struggle when trying to execute intensive code *every single loop iteration*. When writing to the serial monitor, changing the state of output pins, or taking input pin measurements at this rate, your board might slow down - leading to delayed input readings or loss of synchronisation with other systems.

## `delay()` is a bad function

While Arduino has a built-in function for achieving time-based functionality, `delay()` can be quite dangerous. When `delay()` is called, it halts the entire board for a specified duration, during which it cannot perform any other (background) tasks, e.g. engaging with communication protocols or taking sensor readings.&#x20;

## Introducing Timers

In Arduino, we use so-called *timer functions* to set actions to occur on a regular interval.

Perhaps the simplest way to achieve this is using the `millis()` function, which returns the current time, in milliseconds, since power-on.

```arduino
// Print the current board time to the serial monitor
Serial.println(millis());
```

{% embed url="<https://www.arduino.cc/reference/en/language/functions/time/millis/>" %}

The `millis()`  timer has an incredibly long memory - up to 50 days! Consequently, if you wish to store the current time in a variable, you need to use an `unsigned long` variable type, rather than an `int` or `float`, to provide enough memory for this large value:

```arduino
// Get the current board time and store it in a variable
unsigned long timeNow = millis();
// Print the current board time to the serial monitor
Serial.println(timeNow);
```

## Using `millis()`

To execute code on an interval, we can use `millis()` to check whether enough time has passed since the last execution, and gate its occurrence on this using an `IF` condition.&#x20;

For instance, we could report to the Serial Monitor on a regular interval, rather than flooding the serial interface and slowing the board down by trying to do so every loop iteration:

```arduino
// Define global variables
unsigned long timeLast = 0;
unsigned long timeNow = 0;

// Setup an input pin
pinMode(2,INPUT);

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

void loop() {
    // Get the time since boot for this loop iteration
    timeNow = millis();
    
    // Check to see if at least 2 seconds have passed since we last did something
    if((timeNow-timeLast) > 2000) {
        
        // Update timeLast
        timeLast = timeNow;
    }
    
    // If enough time hasn't passed, do nothing this loop iteration...
}
```

In this regime, the only code that *must* run every loop iteration is a simple `IF` check, rather than an intensive `Serial.println()`. This will speed up the board and leave the serial monitor free of unnecessary traffic.

## Timers and Functional Programming

We can further improve our code using [Clean Code](/zerotohero/arduino-zero-to-hero/core-skills/clean-code.md#functional-programming) to modularise the code that is to be executed on the timer interval. With a simple user function, the main `loop()` of the above code can be simplified:

```arduino
// Define global variables
unsigned long timeLast = 0;
unsigned long timeNow = 0;

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

void loop() {
    // Get the time since boot for this loop iteration
    timeNow = millis();
    // Check to see if at least 2 seconds have passed since we last did something
    if((timeNow-timeLast) > 2000) {
        // If enough time has passed, do something
        measureAndReportToSerial();
        // Update timeLast
        timeLast = timeNow;
    }
    // If enough time hasn't passed, do nothing...
}

/* User Functions --------------------------------- */

void measureAndReportToSerial() {
    // If enough time has passed, do some stuff
    int x = digitalRead(2);
    Serial.print("x ="); Serial.println(x);
}
```

## `EVERY_N_MILLISECONDS()`

A brilliant off-the-shelf timer function is available in the `FastLED.h` library, accessible via the [Arduino IDE](/zerotohero/arduino-zero-to-hero/arduino-ide.md#library-manager).&#x20;

`EVERY_N_MILLISECONDS()` provides a structure, like an `IF` condition, that abstracts away the complexity of `millis()` and the associated `IF` check. It simply takes an input the desired wait period between executions of its inner code (in milliseconds):

```arduino
// Include the library that provides EVERY_N_MILLISECONDS()
#include <FastLED.h>

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

void loop() {
    EVERY_N_MILLISECONDS(2000) {
        measureAndReportToSerial();
    }
}

/* User Functions --------------------------------- */

void measureAndReportToSerial() {
    // If enough time has passed, do some stuff
    int x = digitalRead(2);
    Serial.print("x ="); Serial.println(x);
}
```

Using an off-the-shelf timer function like this further simplifies our main loop(), improving readability and clarifying the purpose of the code.

{% hint style="danger" %}
:zap: Warning: `FastLED.h` is quite a large library, and including the entire thing to use one function is... indulgent to say the least. If your Arduino sketch is already large, consider using a `millis()` structure, rather than `EVERY_N_MILLISECONDS()`.
{% endhint %}
