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