New Arduino Library: Periodic Blocks

Periodic is an Arduino library that simplifies the Blink Without Delay pattern. It is used in the following form:

#include <Periodic.h>
...
void loop()
{
  periodic(ms) {
    ...
  }
  ...
}

The Blink Without Delay example sketch can be expressed as:

#include <Periodic.h>

static int LED = 13;
static unsigned long INTERVAL = 1000L;

void setup()
{
  pinMode(LED, OUTPUT);
}

void loop()
{
  periodic(INTERVAL) {
    digitalWrite(LED, !digitalRead(LED));
  }
}

Multiple periodic blocks are allows. Below is an extended blink example sketch with three blink intervals.

#include <Periodic.h>

static int RED_LED = 13;
static int GREEN_LED = 12;
static int BLUE_LED = 11;

void setup()
{
  pinMode(RED_LED, OUTPUT);
  pinMode(GREEN_LED, OUTPUT);
  pinMode(BLUE_LED, OUTPUT);
}

void loop()
{
  periodic(250) {
    digitalWrite(RED_LED, !digitalRead(RED_LED));
  }

  periodic(500) {
    digitalWrite(GREEN_LED, !digitalRead(GREEN_LED));
  }

  periodic(1000) {
    digitalWrite(BLUE_LED, !digitalRead(BLUE_LED));
  }
}

For further details please see the interface and example sketch in the repository.

Cheers!

NB: The library has been ported from the Cosa Periodic class.

Thanks for sharing! some remarks:

for (int __UNIQUE(i) = 1;
==>
for (uint8_t __UNIQUE(i) = 1;

to save a byte of heap runtime?

There is always the choice if

#define periodic(ms)							\
  static uint32_t __UNIQUE(timer) = 0L;					\
  for (int __UNIQUE(i) = 1;						\
       (__UNIQUE(i) != 0) && ((millis() - __UNIQUE(timer)) >= ms);	\
       __UNIQUE(i)--, __UNIQUE(timer) += ms)

#endif

should be

#define periodicWithSkip(ms)							\
  static uint32_t __UNIQUE(timer) = 0L;				\
  for (int __UNIQUE(i) = 1;						\
       (__UNIQUE(i) != 0) && ((millis() - __UNIQUE(timer)) >= ms);	\
       __UNIQUE(i)--, __UNIQUE(timer) = millis())

#endif

The first code will run on average once per ms milliseconds, but might become "blocking" if the load is high.
The second code will skip missed 'timeslots to run'.

What you want depends on the needs of the application, both have their use

@robtillaart

In Cosa the construct is used for syntactic sugar such as asserted, periodic and synchronized. The compiler will detect that it is a one-shot-loop and remove the loop variable all together. No stack (or heap) used.

Cheers!