New library - A timer macro

I've written a lib that simulates a timer via macro: no classes, no functions. It's just a synctactic sugar for IF (millis() - last_tick >= interval) then ..., with the possibility to handle several timers at once and even variable ones (interval not fixed).

I wrote this for C beginners, so it comes with simplicity in mind.
Let me know if you find it useful.

Here's the Github link: Arduino/EVERY at master · SimoneS93/Arduino · GitHub

You use it like this:

#include "EVERY.h"

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

void loop() {
    EVERY(0, 3000) {
        Serial.println("3 seconds have passed since last tick");
    }
}

Can you post the code here - much more accessible.

Why have you && (__EVERY_PAST = __EVERY_NOW) >= 0)
[/color]
This seems to be clever, but I don't like the fact that it hides the workings of a very important piece of code from newcomers.
...R

I like the simplicity of the idea,

think there is a bug in the code ...

  #define EVERY(index, interval) ;__EVERY_NOW = millis(); if (__EVERY_NOW - __EVERY_PAST[i] >= interval && (__EVERY_PAST[i] = __EVERY_NOW) >= 0)


__EVERY_PAST[i]  should be  __EVERY_PAST[index]

furthermore when using macros there is the drawback, when using the increment operator as param

EVERY(++x, 100)
{
...
}

it will give unwanted side effects.... maybe reimplement it as functions?

sofar my 2 cents..

Seems a bit complicated / cumbersome when compared to this...
http://forum.arduino.cc/index.php?topic=124974.0

@Coding Badly's link brought to mind another objection.

What if you don't actually want things to repeat but you do want them to be timed. Learning to use the millis() code directly makes that very simple.

...R

@Robin2: full code

/**
 * A macro definition to exec code on time
 * @author Salerno Simone
 * @date 2015-04-12
 */
 
#ifndef _EVERY_H_
  #define _EVERY_H_ 1
  
  /**
   * Define the maximum number of distinct timers (user-overridable)
   */
  #ifndef EVERY_MAX_COUNT
    #define EVERY_MAX_COUNT 10
  #endif
  
  /**
   * Hold the current time in millis()
   */
  unsigned long __EVERY_NOW;
  
  /**
   * Keep track of last execution for every timer
   */
  unsigned long __EVERY_PAST[EVERY_MAX_COUNT];
  
  /**
   * Init all timers with current time
   */
  #define EVERY_INIT() ;__EVERY_NOW = millis(); for (byte i = 0; i < EVERY_MAX_COUNT; i++) __EVERY_PAST[i] = __EVERY_NOW;
  
  /**
   * Check if interval is elapsed since last execution
   * To distinguish between timers, you have to pass a unique timer index
   * from 0 to EVERY_MAX_COUNT-1
   * NOTE: (__EVERY_PAST[i] = __EVERY_NOW) >= 0 is a fake condition since __EVERY_NOW is always >= 0. It's used as an inline assignement.
   * @param int index : the timer index, from 0 up to EVERY_MAX_COUNT-1
   * @param int interval : timer's interval in millis
   */
  #define EVERY(index, interval) ;__EVERY_NOW = millis(); if (__EVERY_NOW - __EVERY_PAST[index] >= interval && (__EVERY_PAST[index] = __EVERY_NOW) >= 0)
  
#endif

@Robin2: I used

if (__EVERY_NOW - __EVERY_PAST[index] >= interval && (__EVERY_PAST[index] = __EVERY_NOW) >= 0)

in place of

if (__EVERY_NOW - __EVERY_PAST[index] >= interval) {

  • __EVERY_PAST[index] = __EVERY_NOW;*

since I had to an assignment right inside the IF statement, because the macro can't open a new block.

@robtillaart: I fixed the code, thank you. As I wrote in Github README, macros come at a cost: type-safety and pre/post-fix operators weird behaviour among the others.

@Coding Badly: yes, it is. I didn't know about that post, so I wrote EVERY: if I knew, I wouldn't have written.

@Robin2: As I said in the first post, EVERY it's just "synctactic sugar" (kind of): if you know how to use millis(), no need for it.

I was working on a Timer full class, but the macro idea caught me for its immediacy, so I have explored it. Now I think I'll continue working on the class and I'll post as soon as I finish it.