I would like to use a variable in an EVERY_N_* timer so I am

I would like to use a variable in an EVERY_N_* timer so I am utilizing:

EVERY_N_MILLIS_I( timingObj, ALERT_TIME ) {
timingObj.setPeriod(ALERT_TIME);
alert();
}

to dynamically updated the timer to whatever ALERT_TIME is set to.

I am running into an issue when updating ALERT_TIME where the timer will still run out the last of the previous value before updating to the new value.

i.e. -
If I first set ALERT_TIME to 15 seconds (15,000ms) it will call alert() every 15 seconds, no problem.
However, if I then set ALERT_TIME to 30 seconds approximately 10 seconds after alert() was last called, then alert() will not be called again for 35 seconds, after which point the timer will trigger every 30 seconds without issue.
In short, it seems to be adding the remaining value to the new value on the first pass.

The reverse is true when moving from a longer to a shorter timer value.
If I first set ALERT_TIME to 30 seconds it will call alert() every 30 seconds, no problem.
However, if I then set ALERT_TIME to 15 seconds approximately 20 seconds after alert() was last called, then alert() will be called again in 10 seconds, after which point the timer will trigger every 15 seconds without issue.
In this case, it seems to be allowing the previous timer value to run out before using the new value.

Is there a way to clear a running timer before setting a new value in the case above?

@Operator ,
check out Marc Miller’s sketch which explores the EVERY_N methods:

@matt_p
Thanks Matt. That’s a good example but seems to be handling things a bit differently.

This is a post that describes the initial problem I was having with using variable timers and the EVERY_N_MILLIS_I function:
https://plus.google.com/106461657512143768817/posts/AyRzBp77g4h?sfc=false

I also found this example over here which uses this method:

It’s not clear to me whether the example you shared or the one I linked above actually addresses the issue I’m seeing of timers not clearing existing values.

@Operator Both the sketches you linked to will have the same issue you’re experiencing where after you change the timer length it doesn’t take effect until the next go around.
I think using reset() is what you’re looking for.

@marmil
Hello Marc, thanks for the reply.

I did see reset() in lib8tion but unfortunately the documentation is fairly non-existent so it’s a bit unclear what it actually does.

I have tried calling timingObj.reset() both before and after timingObj.serPeriod() but unfortunately the result is the same.

i.e.-
EVERY_N_MILLIS_I( timingObj, ALERT_TIME ) {
timingObj.reset();
timingObj.setPeriod(ALERT_TIME);
alert();
}

or

EVERY_N_MILLIS_I( timingObj, ALERT_TIME ) {
timingObj.setPeriod(ALERT_TIME);
timingObj.reset();
alert();
}

still exhibits the same issue.

Hmmmmm, what if you put the setPeriod and reset somewhere else outside the EVERY_N part?

@marmil

I tried something like:

void loop() {
static CEveryNMillis alertTimer(ALERT_TIME);

if(alertTimer) {
alertTimer.reset();
alertTimer.setPeriod(ALERT_TIME);
alert();
}

sort of like what you did in your example that Matt referenced above but same result.

@Operator

I think I’ve found a functional but inelegant solution which clears the “initial” timer. It uses the trigger() method to force things through. I’m sure there are better ways of going about it.

Note: I’m using CEveryNSeconds instead of CEveryNMillis.

@matt_p

Hi matt, apologies for the slow reply. Your response seems to have been marked as spam initially so I was not notified of it. I’ve restored the comment now though so it’s visible.

This is an interesting approach and I’ll give it a go to see if I can make it work and reply here.
Very much appreciated for the response in any case!

I got this resolved and it now seems terribly obvious after the fact.
I ended up declaring CEveryNMillis alertTimer(ALERT_TIME) globally so that in my loop() I could call:

if(alertTimer) {
alertTimer.reset();
alert();
}

and in my function that receives my alert period over UART I could do something like:

getAlertValueOverUARTorWhatever(){
ALERT_TIME = (uint32_t)msg_deserialized.value[0];
alertTimer.setPeriod(ALERT_TIME);
alertTimer.reset();
alert();
}

I needed to call reset() both when the timer is triggered and when a new ALERT_TIME is set to avoid the issue which I obviously couldn’t do when alertTimer had only local scope.

Great you got it sorted out. And thank you for sharing how you worked it out.