The every construct lets you run a piace of code at regular intervals in a fluent way. If you don't need to start, stop, pause your timer, this construct is a valid alternative to more complex timer libraries already available: it only takes a time interval as argument and will execute the code block periodically.

Definition

#define every(interval) \
    static uint32_t __every__##interval = millis(); \
    if (millis() - __every__##interval >= interval && (__every__##interval = millis()))

How to use

// these are for greater code readability
#define Millis 
#define Second  *1000
#define Seconds *1000
int interval = 1 Second;

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

void loop() {
    every(1000 Millis) {
        Serial.println("This line is printed every 1 second");
    }

    every(2000 Millis) {
        Serial.println("This line is printed every 2 seconds");
    }

    every(interval) {
        interval += 1 Second;
        Serial.print("You can have variable intervals too! ");
        Serial.print("This line will be printed again in ");
        Serial.print(interval / 1000);
        Serial.println(" seconds");
    }
}

Caveats

every is just a macro definition and is not a proper timer, so it has some limitations:

  1. you can't stop, pause or resume it: once set, it will run forever
  2. its argument must be the suffix of a valid identifier
  3. you can't use several every with the exact same argument: you have to put all the code that needs to happen at the same interval in the same block

Caveat #2

The macro works by generating a variable named like __every__##argument

every(1) ==> uint32_t __every__1;
every(2) ==> uint32_t __every__2;
every(a_given_interval) ==> uint32_t __every__a_given_interval;
every(an invalid interval) ==> uint32_t __every__an invalid interval; // Syntax error
every(1 Second) ==> uint32_t __every__1 *1000; // Syntax error

So every integer literal and any variable are all valid arguments. Any expression is forbidden.

Caveat #3

If you use two every with the exact same argument, two variables with the exact same name will be created and it will rise a compile-time error.

If you can live with this limitations, every only needs the space of an uint32_t to work.

Help the blow grow