Using Timer in a class

I’m trying to add a Timer that will trigger a function to publish some updates related to the states of members of a class and I’m running into nothing but errors.

In my constructor for the class, I do something like this:

// member function
void MyNamespace::publishPeriodicUpdates(Timer& t) {}

  // In protected area of .h file
Timer* _periodicUpdateTimer;

// Inside constructor...
_periodicUpdateTimer = new Timer(15000, &MyNamespace::publishPeriodicUpdates );

and I get this error:

no matching function for call to 'Timer::Timer(int, void (MyNamespace::*)(Timer&))'

I’ve tried using a lambda to do it too, but I haven’t struck on the right formulation for that (not super experienced with lambdas, though).

Any suggestions?

I’ve got a not so pretty solution that seems to get the job done:

  1. Instantiate a Timer* in your .ino with the appropriate settings, and provide it with a function (let’s call it doStuff) that’s also global (floating in the .ino).
  2. Pass that pointer into the constructor of an instance of the class that’s going to manage the Timer and set up your class as needed. Your class needs a doPeriodicStuff sort of method.
  3. Within doStuff, call your class instance’s doPeriodicStuff method.

That gets the job done, but I don’t like it very much because I’d rather instantiate the Timer within my constructor. If anybody knows how to do that, I’m all ears.

Have you even searched the forum before you posted?
How to use Timer inside a C++ class

Yessir, I did. I found that that didn’t help me - that’s why I asked. I’ve done something similar before, but this Timer class wouldn’t take any sort of lambda I tried. I was expecting to use something along the lines of

[this](void) -> void { this->publishPeriodicUpdates(); }

but no matter what I tried, no luck. Have you done this before? If so, what did you use?

I’ll have to dig into that a bit deeper, or @mdma can just answer it off the top of his head

I have not tested the code, but it at least builds :wink:

class MyClass
{
  public:
    MyClass() { }
    void begin()
    {
      _periodicUpdateTimer = new Timer(15000, (void (*)())&MyClass::publishPeriodicUpdates);
    }

  private:
    Timer* _periodicUpdateTimer;
    volatile int x;
    void publishPeriodicUpdates(void)
    {
      x++;
    }
};

MyClass mc;

void setup()
{
    mc.begin();
}

void loop() { }

One thing to keep in mind might be, that you never know in what order constructors will be called and hence you might into troubles if one constructor would need to rely on another one being already finished.
So the common way around this is to put in a begin() or init() function that only gets called after all constructors should have been called.

1 Like

Iiiiinteresting… I’ll give that a go later today. I had tried casting, but I guess I must not have done it that way.

I’m not sure what you mean by more than one constructor being called at a time. I was under the impression that only one constructor (the one that matches the call signature) was ever called on instantiation. Do you mean w.r.t. stuff instantiated outside of setup() and loop()? In that case we should be good as there’s only one instance of this particular class. Also, would it really be a problem anyway since there should be one Timer per instance?

There are lots of objects that get created on startup - not only the ones you instantiate yourself (e.g. Serial, Wire, Time, …) and since the code above is only a building block without real life in it, I wanted to let you know before you’d see unexpected behaviour rooting in this :wink:


Another thing here might be that the above only works with a static function, so you won’t be able to use any non-static instance fields inside it (I think :sunglasses:)

That did compile for me too, so that’s cool, but I think you’re right about it needing to be static. Unfortunately, I don’t think that’s going to work for our use-case. I need to be able to iterate over a deque stored in the class instance.

Thanks for the help!

Correct syntax seems to be:

Timer(1500,reinterpret_cast<void (*)()>(&MyClass::classMethod));

@steelydev, did you see the documentation for the latest 0.4.9 release:

https://docs.particle.io/reference/firmware/photon/#software-timers

Look under “class member callbacks” :wink:

1 Like

Sorry for the necrobump, but is there any way to use the new “class member callback” syntax to declare/initialize the timer from within the class (possibly its constructor)?

Yes, having a timer as part of a class can be done like this:

#include "Particle.h"

class MyClass {
public:
	MyClass();
	virtual ~MyClass();

	void start();
	void timerCallback();

private:
	Timer timer;
};

MyClass::MyClass() : timer(1000, &MyClass::timerCallback, *this) {
}

MyClass::~MyClass() {
}

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

void MyClass::timerCallback() {
	Serial.println("timerCallback");
}

MyClass myClass;

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

	myClass.start();
}

void loop() {

}

2 Likes

thanks!!