Trigger at a certain time

I need to trigger a function at a certain clock time to keep all of my nodes sync’d. The function sends out a sync packet over my LoRa. My nodes are programmed to leave a few seconds open at the top of every minute to receive that packet. So I need to schedule my IMP to send at second 0 or 1. However I won’t send that sync every minute. Only when it is requested by one of the nodes (at startup and certain other times), but then the transmit will be delayed until we have our open slot at the top of the minute.

It’s probably been done a hundred times, but I’m new to this platform and haven’t figured it out yet. Any suggestions?

Relatively easy in theory but quite tricky to maintain long term. I know years back a company called Dust networks had developed their own resilient method (Time Syncronised Mesh Protocol) which handled the syncing of slots in a stochastic fashion. Maybe things have moved on from there. https://en.wikipedia.org/wiki/TSMP. Otherwise check the radio module as it may have a wakeup feature, as in send some arbitrary bytes causing an interrupt to trigger.

My mesh will not be all that time-critical. I’m looking to maintain about 32 nodes and one central unit within +/- 1 sec. Pretty simple. I send out a sync packet every 30 min for now. That will increase as I become more confident in my node clocks. But when I put a new node on line, it will send a sync request immediately and the master will respond at the next minute tick. So I’m just looking for how to trigger a function (send sync) at a particular time.

In theory you would probably set up wakeup timers which are synced at first tick… but there’s possibly your first constraint as Imp has a max of 20 wakeup timers (I believe this may increase in near future). Issues to consider are when master or a node does an unscheduled reboot for some reason. This throws off your timings or if one node has unreliable comms etc. Then need to factor in your wifi comms (assuming that is at master device) and any imp firmware updates as this could also upset syncing.

The imp has an unlimited number of timers (well, limited by available resources); it’s only the agent where you’re limited to 20 (for now).

For the reasons Gerrikoio mentioned, I don’t think timers are the way to go. If I can sync a timer to start at a particular time, say @ master time of sec = 0 then I should be able to accomplish the task without a timer by simply calling the function at a particular time.

I was assuming this little trick had been done before and hoping someone would have a code snippet. It’s beginning to look like I was wrong. Ideas would be appreciated.

Run a loop function every 0.X seconds which reads date() and, if the second value is 0 or 1, checks an array of nodes that need syncing and sends out the required signal. You’ll need a flag to make sure the check routine isn’t called repeatedly after it has first been triggered. A bit crude, but something like:

`
local syncingFlag = false;

function doSync() {
foreach (device in devicesWaiting) {
sendSync();
}

syncingFlag = false;

}

function loop() {
imp.wakeup(0.1, loop);

local now = date();
if ((now.sec == 0 || now.sec == 1) && !syncingFlag) {
    syncingFlag = true;
    doSync();
}

}

loop()`

Thanks smittytone. Yes that would work.
But I came up with a stupid simple method that seems to do the trick.

Contained in funcction RadioSendSync()
Sends a sync every 5 min at mark second 0

local now = date(time() + LOCAL_CORRECT)
local sync_min  = 5
local next_sync = (59 - now.sec) + (sync_min *60)
imp.wakeup(next_sync,RadioSendSync)

You will occasionally get a second jump there, because;

  • time() comes from the RTC, which if the imp has an 32kHz xtal, is running from a different timebase to imp.wakeup that runs from the high frequency clock
  • a connected imp will get time re-sync from the server with 1s granularity

…but it sounds like you have enough of a window (2s) to contain this if you’re doing it regularly.

Yes, in fact I am getting a double trigger on the sync event occasionally. It doesn’t hurt anything, but I would like to resolve it. Could that be remedied by:

if (send_sync) imp.cancelwakeup(send_sync)
send_sync= imp.wakeup(next_sync,RadioSendSync)    

or would it be better to use a delay somewhere?

Generally it’s a very good idea to cancel any wakeup before setting another.