Timer with long running code

Is there a timer lib for running long, blocking operations? I have this code repeated several times:

bool flag;
void setFlag() {
  flag = true;
}
Timer timer(5000L, setFlag);
timer.start();

void loop() {
  if (flag) {
    flag = false;
    // time consuming operation
  }
}

I don’t need precise timing.

What kind of long, blocking operations are you thinking of?
Can these not be made non-blocking?

1 Like

Publish to MQTT, measure ultrasonic sensors

I tried wrapping the repetitive code in a class but get an error constructing the Particle timer:

# non_blocking_timer.h
# -------------------------------
#ifndef __NON_BLOCKING_TIMER__
#define __NON_BLOCKING_TIMER__

#include "application.h"

class NonBlockingTimer {

  typedef std::function<void(void)> timer_callback_fn;

  public:
    NonBlockingTimer(unsigned int period, timer_callback_fn callback);
    void start();
    void loop();

  private:
    void trigger();
    timer_callback_fn callback;
    Timer timer;
    bool triggered;
};

#endif // __NON_BLOCKING_TIMER__

# non_blocking_timer.cpp
# -------------------------------
#include "non_blocking_timer.h"
#include "application.h"

NonBlockingTimer::NonBlockingTimer(unsigned int period, timer_callback_fn callback)
  : callback(callback), timer(new Timer(period, &NonBlockingTimer::trigger, this))  // no matching function call to Timer::Timer()
{
}

void NonBlockingTimer::start()
{
  timer.start();
}

void NonBlockingTimer::loop()
{
  if (triggered) {
    triggered = false;
    callback();
  }
}

void NonBlockingTimer::trigger()
{
  triggered = true;
}

compiler error:

  no matching function call to Timer::Timer(unsigned int&, void (NonBlockingTimer::*)(), ...`

Usually with that error message also come some note messages that reveal what the compiler actually expects for the closes overload of a call.
In your case this

x.ino: In constructor 'NonBlockingTimer::NonBlockingTimer(unsigned int, NonBlockingTimer::timer_callback_fn)':
x.ino:20:81: error: no matching function for call to 'Timer::Timer(unsigned int&, void (NonBlockingTimer::*)(), NonBlockingTimer*)'
x.ino:20:81: note: candidates are:
In file included from ./inc/application.h:59:0,
                 from src/x.cpp:1:
../wiring/inc/spark_wiring_timer.h:38:5: note: template<class T> Timer::Timer(unsigned int, void (T::*)(), T&, bool)
     Timer(unsigned period, void (T::*handler)(), T& instance, bool one_shot=false) : Timer(period, std::bind(handler, &instance), one_shot)
     ^
../wiring/inc/spark_wiring_timer.h:38:5: note:   template argument deduction/substitution failed:
x.ino:20:81: note:   deduced conflicting types for parameter 'T' ('NonBlockingTimer' and 'NonBlockingTimer*')
In file included from ./inc/application.h:59:0,
                 from src/x.cpp:1:
../wiring/inc/spark_wiring_timer.h:33:5: note: Timer::Timer(unsigned int, Timer::timer_callback_fn, bool)
     Timer(unsigned period, timer_callback_fn callback_, bool one_shot=false) : running(false), handle(nullptr), callback(std::move(callback_)) {
     ^
../wiring/inc/spark_wiring_timer.h:33:5: note:   no known conversion for argument 2 from 'void (NonBlockingTimer::*)()' to 'Timer::timer_callback_fn {aka std::function<void()>}'
../wiring/inc/spark_wiring_timer.h:27:7: note: Timer::Timer(const Timer&)
 class Timer
       ^
../wiring/inc/spark_wiring_timer.h:27:7: note:   candidate expects 1 argument, 3 provided

To interpret these notes you also need to know that this is a pointer to the object, not the object itself.

Also new returns a pointer to the object, but you try to assign it to a object variable. Either make your timer a Timer* timer or dereference the resulting object pointer and assign to a reference Timer &timer.

Awesome, thanks for the detailed reply @ScruffR!

For future readers, my working solution in non_blocking_timer.h and non_blocking_timer.cpp

1 Like