Static Callback function with parameters?

C++ gurus,

Am using the TaskScheduler library to setup a timer for my object to "turn off" once the timer duration has expired after the object has been "turned on"

The task Scheduler library requires a Task object to be constructed as:

Task(unsigned long aInterval, long aIterations, void (aCallback)(), Scheduler aScheduler, bool aEnable, bool (*aOnEnable)(), void (*aOnDisable)());

I'm being told that the callback needs to be a static method.. and the following compiles and works fine in a class

Task * timer = new Task(duration, iterations, &turnOff, scheduler, false);

with void turnOff(){//blah}
defined in the main sketch (as a static method)

However since the turnOff method is static, I need to pass a parameter to the callback.
I can't get it to compile using

Task * timer = new Task(duration, iterations, &turnOff(pin), scheduler, false); //pin is an int value

with void turnOff(int pin){//blah} in the main sketch

My question is how to pass in an int parameter to the callback without modifying the library, or how to make the callback non static.. or ...


You can't write it to take a parameter in that callback unless you want to go rewrite the scheduler library.

The easiest thing to do would be to throw away the Scheduler crutch and just handle your timing with millis so you're not forced into this issue.

But if you're just married to the idea of bloating your code with that library then you'll have to write a function that takes no arguments and calls the function with the argument that you want. So you'll have two functions, one as the callback and then the one that the callback calls.

I could rewrite with millis, but am worried about the rollover.

The maximum timerDuration allowed is 23 hours 59 minutes so I'd only run into this issue if the switch was turned on within that duration of the rollover, but it could happen..

Am also reading that there are ways to workaround that issue but not sure how...

The two functions technique will not work - I need to have a way to reference back to the calling object (in which the turn off scheduler event fired), and for that I need to pass the GPIO pin # as the parameter...

I could rewrite with millis, but am worried about the rollover.

Nonsense. Written properly, a millis()-based timer can time for a duration of over 49 days regardless of when it starts relative to the roll over point.

There is no worry about rollover as long as none of your intervals are more than 49 days long. As long as you're just dealing with times of day then there is no issue with rollover from millis. At least as long as you code it right. There are plenty of tutorials that will show you how to be safe with it.

I don't think you understand what I mean by using two functions. It will work if you do it right.

Sorry, very much a C++ newbie as apparent.

My understanding of the two Functions method:
Step 1: Use static callback method with no parameters in Task definition (done)

_ Task * timer = new Task(dur, it, &turnTimedOff, device->scheduler, false);_

Step 2: In static turnTimedOff callback method, call the actual target function in the correct switch object

void turnTimedOff(){
//iterate vector containing up to 8 dynamically created "switch" objects and find the one with the GPIO Pin corresponding to the switch object that just fired the turnTimedOff scheduler event

//call the real turn off function on that object


Where Im stuck is I need the GPIO pin to get the object from the switches vector.....

Am I going about it wrong?

Will read up on millis and rollover to get a better understanding.


Okay, got it working

In the turnOn method
isTimerOn = true;
timerStartTime = millis();

Heres the loop function now

if(millis() - timerStartTime > timerDuration * 1000){ //timerduration is in seconds

  • turnTimedOff();*

Hope I got it right.. :confused:

Make sure timerStartTime and timerDuration are of type 'unsigned long' (or uint32_t)

Where Im stuck is I need the GPIO pin to get the object from the switches vector.....

This is the part you're not explaining well. How were you going to get that pin number in the interrupt routine that you can't get it from your other function. Either you can OR what you wanted to do didn't make any sense in the first place.