timer t.after() problem?

Hi,

I have a small project to monitor temperatures and operate a pump accordingly. Im having trouble with a library im using to schedule all the events. Test code is attached.

Basically when the pump is turned on I need to prevent any other changes to it for a few seconds while it spins up/down. So every time its state changes I set a 'lock' and start a timer to 'unlock' it. I want to use a timer based system so other events can be built-in later cleanly.

I dont know if im doing something stupid by trying to set a timer outside of the setup(), but it seems to work with a very simple text example. However in the project sketch the lock is released within a few mS of it being set rather than a few seconds, example attached.

The problem must be with the following method? but I dont see why :-[ :

void setPumpSpinLockTimer(){            
    pumpSpinLock=true;
    timerEventId2=t.after(pumpSpinUpTime, stopPumpSpinLockTimer);  //enable event to unlock pumpSpinLock
    t.update();
    if(debug){Serial.println("setPumpSpinLockTimer() pump: "+String(pumpStatus)+" lock: "+String(pumpSpinLock)+" now:"+String(millis())+" unlock in:"+String(pumpSpinUpTime));}
  }

t.update() makes little difference in or out

Any ideas/solutions/alternatives

Thanks

PumpTest.ino (6.5 KB)

TimerTest.ino (1.14 KB)

debug.txt (338 Bytes)

Can anyone recommend an alternative lib? Or another way to set a timed event mid sketch?

Ta

Hi itnoworking

You have two calls to t.after(), one in setupTimers() and the other in setPumpSpinLockTimer().

What happens if you delete the first of these? You only have one in your other test program.

Regards

Ray

Thanks Hackscribble,

Tried it and problem continues :frowning:

I also tried different values and variable types for the pumpSpinUpTime variable, no joy, consistently fails the same way.

The method is being added as an event and triggering but it not being timed correctly, im assuming im making a bad method call or not understanding how to use it correctly.

Can anyone offer any insight on functioning of the timer library im not very confident with the coding

The relevant? parts of the lib might be

Timer.h

int8_t after(unsigned long duration, void (*callback)(void));

Timer.cpp

int8_t Timer::after(unsigned long period, void (*callback)())
{
 return every(period, callback, 1);
}

From this im guessing im not doing anything disastrous. Passing a long might be better than an int but t.every() handles it fine and it has the same definition

Please point out my glaring mistakes

Event.cpp (1.57 KB)

Event.h (1.32 KB)

keywords.txt (726 Bytes)

ReadMe.txt (1.63 KB)

Timer.cpp (3.57 KB)

Timer.h (2.17 KB)

Ive added abit to the test script and seem to be able to replicate the problem.

The first t.after() event that is added is triggered at the correct time however a second un-requested event triggers 1s after this or 1ms after the next requesting event. From this point on the timing of the M4 event is FUBARed.

Code and output are attached, can anyone explain what is going wrong here?

Thanks

TimerTest.ino (1.39 KB)

test_debug.txt (424 Bytes)

Not sure yet why it works, but I think the problem goes away if you declare a second Timer object and use that for the after events.

#include <Timer.h>

int intervalOne = 1000;
int intervalTwo =2000;
int intervalThree =3000;
int intervalFour =2000;

Timer t, t2;

int timerEventId1, timerEventId2, timerEventId3, timerEventId4;

boolean messageTwoLock = false;

void setup() {
Serial.begin(115200);
  // set up the LCD's number of columns and rows: 
  setupTimers();  //add core methods to timer events
}

void loop() {
  t.update();
  t2.update();
}

void setupTimers() {  //set timing events for core methods
  timerEventId1=t.every(intervalOne, messageOne);  
  timerEventId2=t.every(intervalTwo, messageTwo);  
  timerEventId3=t.every(intervalThree, messageThree);  
} 

void messageOne(){
  Serial.println("M1: "+String(millis()));
}

void messageTwo(){
  if (messageTwoLock==true){
    Serial.println("M2 - LOCKED!: "+String(millis()));    
  }else{
    Serial.println("M2: "+String(millis()));
  }
}

void messageThree(){
    Serial.println("M3 - TIMER START: "+String(millis())+" M4 @ +"+String(intervalFour + millis()));
    setMessageFourTimer();
}

void messageFour(){
  if (messageTwoLock==true){    
    messageTwoLock= !messageTwoLock;
    Serial.println("M4 - LOCK FALSE: "+String(millis()));    
  }else{    
    messageTwoLock= !messageTwoLock;
    Serial.println("M4 - LOCK TRUE: "+String(millis()));
  }
}

void setMessageFourTimer(){
  timerEventId4=t2.after(intervalFour, messageFour);  //enable event to unlock pumpSpinLock
}

Fantastic!!

I dont know why it didnt occur to me, a second timer.

Thanks for your help id be banging my head on this for some time yet

Out of interest is there a way to work out how much space a second instance of an object uses? Just compare upload sizes?

TimerTest2.ino (1.48 KB)

TimerTest2_debug.txt (395 Bytes)

The second instance will use more SRAM, not program Flash memory, so won't affect the program upload size, I think.

You could add this function to your program to display the available SRAM, and compare the two versions.

int freeRam () 
{
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
...
Serial.print("SRAM available = ");
Serial.println(freeRam());

I've been looking at the timer and event library code. There is a bug / feature that means, if you create an event on a timer object from the callback function of an event on the same timer object, the library can often (but not always) think that the new event has immediately expired.

In your program, using a second object for the after events avoids the prerequisite condition and the problem goes away.

Another way to work around it would be for your callback function to set a boolean flag, which you then test for in loop() after the calls to the update(). If the flag is true, create the after event and reset the flag to false.