Project

General

Profile

Scheduler not in time with interrupt

Added by zoic21 over 6 years ago

Hi,

I have I little probleme with Scheduler which not fire poll event in time I use this part of code :

Declaration

enum { 
  MEASURE, TASK_END };
static word schedbuf[TASK_END];
Scheduler scheduler (schedbuf, TASK_END);
static int reportCount;
// has to be defined because we're using the watchdog for low-power waiting
ISR(WDT_vect) { 
  Sleepy::watchdogEvent(); 
}

Setup

scheduler.timer(MEASURE, 0);

Poll

  if (timer.poll(60000)){
    if(++measureCount >= MEASURE_PERIOD){
      measureCount = 0;
      reportCount++;
      for(int i=1;i<5;i++){ //Recuperation valeur des ports
        sensors[i].doMeasure();
      }
    }

    if(reportCount >= REPORT_EVERY){
      reportCount = 0;
      doReport();
    }
  }

With REPORT_EVERY = 5,then report data send to another jeenode wich send send data to server. I have multiple jeenode, everyone who uses interrupt (for PIR like roomnode sketch) do not send their reports on a regular basis. In general it is more than 10 minutes to 5 minutes. Anyone know about this issue ?


Replies (1)

RE: Scheduler not in time with interrup - Added by damonb over 6 years ago

I had a similar problem and it took me a long time to figure out the answer.

It is a limitation in the Scheduler class in JeeLib (in ports.cpp).

To minimise power consumption the PollWaiting() method waits using Sleepy::LoseSomeTime() in blocks of 600 tenths i.e one minute at a time.

The problem is that if your interrupt wakes the node up from these sleeps, it only knows it didn’t finish its last one-minute sleep so it starts the same sleep again without counting down. This means that any interrupts will delay the next scheduler event. If interrupts come more frequently than one minute, the scheduler event can be delayed indefinitely.

For my application I receive interrupts from a water meter that can occur up to twice per second. My work-around is to use a modified version of ports.cpp (from JeeLib) as follows:

In Scheduler::pollWaiting() find the following line:

word step = remaining > 600 ? 600 : remaining;

Change both the 600 values to an interval that is shorter than the minimum period between interrupts.
I am using 4 (= 400ms) and it works for me, i.e.

word step = remaining > 4 ? 4 : remaining;

The disadvantage is the node will consume more current, because it wakes up to measure its sleep time much more often. For me it now uses about 20µA instead of about 8µA, which is ok. It still lasts >12 months on AA batteries.

To formalise this solution I have been thinking the best way would be to add another method to the Scheduler class to allow the sleep increment to be set by the calling sketch, with 600 being retained as the default for backward compatibility. I have an intention to submit this as a code improvement, as soon as I allocate some time to learn how to use github properly for branching etc. :(

    (1-1/1)