Event scheduling triggers every 2 minutes instead of 1

I modified the tracker software a bit to have the One schedule two events: a full report every hour and a small update every minute.

Instead of triggering the update every minute, it triggers every 2 minutes. Looking into the code I can’t figure out exactly why this happens and how the RTC and timer interact.
How I thought it works: RTC is set to trigger an interrupt every 59+1 s. This executes rtcAlarmHandler first, then executes loop(). Loop runs timer.update(), which updates the timer which would have stopped during deepsleep. Because an event is scheduled with timer.every(60), this triggers the update every minute. However, this does not happen: it gets triggered every two minutes instead.

Am I misunderstanding the working of RTC and timer, or is this a race condition? I tried to set the timer.every interval to 59 seconds to prevent the race condition, but this did not help.

Any help would be appreciated. My code:

void initRtc()
{
rtc.begin();

    // Schedule the wakeup interrupt for every minute

    // Alarm is triggered 1 cycle after match
    rtc.setAlarmSeconds(59);
    rtc.enableAlarm(RTCZero::MATCH_SS); // alarm every minute

    // Attach handler
    rtc.attachInterrupt(rtcAlarmHandler);

    // This sets it to 2000-01-01
    rtc.setEpoch(0);
}

/**
 * Runs every minute by the rtc alarm.
*/
void rtcAlarmHandler()
{
    minuteFlag = true;
}

/**
 * Initializes the RTC Timer and schedules the default events.
 */
void initRtcTimer()
{
    timer.setNowCallback(getNow); // set how to get the current time
    timer.allowMultipleEvents();

    resetRtcTimerEvents();
}

/**
 * Clears the RTC Timer events and schedules the default events.
 */
void resetRtcTimerEvents()
{
    timer.clearAllEvents();

    // Schedule the default fix event
    timer.every(60, runDefaultFixEvent);
    timer.every(FULLREPORTTIME * 60, sendFullReport);

    // check if the alternative fix event should be scheduled at all
    if (params.getAlternativeFixInterval() > 0) {
        // Schedule the alternative fix event
        timer.every(params.getAlternativeFixInterval() * 60, runAlternativeFixEvent);
    }

    // if lora is not enabled, schedule an event that takes care of extending the sleep time of the module
    if (!isLoraInitialized) {
        timer.every(24 * 60 * 60, runLoraModuleSleepExtendEvent); // once a day
    }
}

If you are scheduling an event for every 60s and you have an alarm which wakes the device once a minute, it is possible that it will miss the first event. This is may happen if, during the first wake cycle, the event is not due yet, it will then have to wait another minute for next test to be conducted.

Are the gaps 2,2,2,… or 2,1,1,1,… in minutes?

Have you tried scheduling the alarm at a different point e.g. at 30s?

Hi Gabriel,

Thanks for your response. The gaps are 2,2,2,… minutes. I only tried setting the alarm to 59 seconds instead of 60.
If I would change it to below 30s, should it fire only once or multiple times after a minute?

The alarm time is the seconds past the minute when the alarm will be triggered (when using RTCZero::MATCH_SS).

So when the alarm seconds are set to 30, It will trigger once a minute, at 30s past the minute (possibly one second later).

Ah, got it, you were talking about rtc.setAlarmSeconds(30) instead of timer.every(30). I can try that. Is my understanding of the working of RTC and timer correct?

I tried it but it didn’t help. However I noticed the GPS Fix Timeout was set to 60 s. I changed that to 55 s. and now it fires every minute. So I think it was a combination of that and poor GPS reception while testing inside. Thanks for your help!

The functionality of rtctimer does not support catching up. That is if the event in scheduled to run once per minute, and the and you only call the update function after two or more minutes (due to lengthy execution etc), it will only execute once. It will not try and catch up for the missed events.