Doc request: wakeup dos & don'ts

It seems from my experience with one particularly thorny bug today (happily, solved) that there are many ways to trip oneself up when using “wakeup” calls. And since wakeup calls are encouraged in the imp style of coding, so that the imp can get updated by the server, it seems like this would be worth clarifying.


Here’s what I’ve seen so far:

There’s a technique we learn early on (in the Blink-o-Matic example) where a function sets a wakeup call for itself, so it can be run periodically.

e.g.
function blink() {
  // blink the LED
  imp.wakeup(0.2, blink);
}

If we extend this technique to two functions, only one will work.

e.g.
function checkFirstInput() {
  // check the input
  imp.wakeup(0.2, checkFirstInput);
}

function checkSecondInput() {
  // check the input
  imp.wakeup(0.2, checkSecondInput);
}

    ^- this will fail. One of the two will not re-run itself after the initial call to start it going.

It took me a while to sort out that this was what was going wrong. My first thought, once I figured out that this was why an entire side of my program was failing, was to set up a single dispatcher function to be the only one that re-woke itself, like so:

function checkAllInputs() {
  checkFirstInput();
  checkSecondInput();
  imp.wakeup(0.2 checkAllInputs);
}
function checkFirstInput() { /check/ }
function checkSecondInput() { /check/ }

I’d reasoned that maybe a single thread could only have a single wakeup call scheduled, and whichever one came second was just replacing the first. Yet this master-dispatcher-function technique would have gotten around that issue. And it didn’t. The same as before, only one of the functions would run.

The solution that did work for me was to have the two routines chain off each other. Like so:
function checkFirstInput() {
  // check the input
  imp.wakeup(0.1, checkSecondInput);
}

function checkSecondInput() {
  // check the input
  imp.wakeup(0.1, checkFirstInput);
}

First wakes up second, which wakes up first in turn, etc…

Why this worked and not the master-dispatched approach is a mystery to me. A quick skim of the threading & wakeup section of the Squirrel docs doesn’t clarify the behavior.

Can anyone explain what’s going on with the wakeup fragility I’m running into here? What ARE the actual limitations you have to observer with wakeup calls?

Hmm. I can’t explain why your master dispatcher didn’t work (apart from the lack of a comma after the 0.2, but I guess that’s a transcription typo). Did you try putting server.log()s in there to see what actually got called?


Multiple outstanding imp.wakeup’s are on the todo list, as I’ve run into this in my own applications a few times. It’s very near the top of the list too :slight_smile:

Well, I certainly could have screwed something up in the master dispatcher version. Good to know that’s supposed to work, though. It seems like a better way of handling things than the chain solution. I’ll try the dispatcher again in future cases.

You’re correct that you can only, currently, have one wakeup call scheduled at a time. This doesn’t affect other registered event handlers such as input pin transitions, although only one handler can run at a time (they’ll queue).


Rob
Fen Consultants, UK

To stop spam bots like the above, maybe add a captcha to the posting form.

Hi Hugo,

if you’re running somthing like this at root:

imp.wakeup(30, function(){server.sleepfor(6000.0)});

Can you extend the wakeup call. Basically I want the device to wakeup from deep sleep when triggered with pin 1 using DIGITAL_IN_WAKEUP and stay awake for 30 seconds which I’ve got working. But then I want it to keep staying awake if there are any further interactions on pin 1. I tried adding another wakeup call in my pin function but it doesn’t seem to keep it awake any longer than the original root level wakeup call.

`server.log(“Hello world”);

function pin1changed() {
// declare a local variable
local buttonState = hardware.pin1.read();

if (buttonState == 1) {
    server.show("Button Pressed!");
    server.log("Button Pressed");
    imp.sleep(0.05);
    imp.wakeup(30, pin1changed);
} else {
    server.show("Button Released!");
    server.log("Button Released");
    imp.sleep(0.05);
}

}

// Configure Pin1 to be wake up pin
hardware.pin1.configure(DIGITAL_IN_WAKEUP, pin1changed);

imp.configure(“Pin1 Waker”, [], []);

// Enter deep sleep
//server.log(“Test sleep started”);
//imp.onidle(function() { server.sleepfor(6000.0); } );
imp.wakeup(30, function(){server.sleepfor(6000.0)});

`

Sorry if I’m missing something obvious, but I’m totally new to squirrel
So any help much appreciated

Benjamin:-)