trouble using Clock.attachAlarmInterrupt


#1

I’m trying to figure out how I can use this command to restart the loop just like a timeout in case the unit gets stuck (etablish connection too long). I tried to make a simple model just to understand. The function “alrm” is activated but the led does not pulse and the code seems to stop after 2seconds. I tried several variants but my knowledge is limited, I thought it would be easy! Any help would be appreciated

void setup() {
  Serial.begin (9600);
  Clock.setAlarmSecondsFromNow(5);
  Clock.attachAlarmInterrupt(alrm);
}

void loop() {
  Serial.println("loop begin");
  Dash.pulseLED(100, 100);
  Dash.snooze(2000);
}

void alrm() {
   Serial.println("alarm expired 5s");
   Dash.pulseLED(200, 200);  //the led stays on(no pulse) for 2 seconds.
   Dash.snooze(2000);
   Clock.setAlarmSecondsFromNow(5);
   Clock.attachAlarmInterrupt(alrm);
   loop (); //restart the loop but doesn't.
   }

#2

Your setup looks good. It sets the alarm timer and attaches the callback function that is called on timer expiration. So far so good.

Your loop is fine, we’ll come back to that.

When your program runs on the dash, setup() is run, then loop() is run repeatedly. Each time it completes, it starts again. When the alarm expires, it triggers an interrupt. That stops the processor where ever it is in your code, and alrm() is run. When alrm() is finished, the program goes back to where it was stopped and resumes.

The alarm will expire somewhere in the loop function, and then jump to alrm(). While in alrm, other interrupts are blocked from running (with some exceptions, but that’s not important for now). Once such interrupt that is blocked is the timer that pulses the LED that is set by pulseLED. So while snoozing in alrm, the LED is not going to pulse. You restart the alarm, which is good. But you shouldn’t ever call loop because loop will continue to run on its own. The general rule for interrupt handlers like alrm is to have it do its work quickly and return so nothing else is blocked for an extended period. You don’t need to re-attach the alarm function as that is already set. It doesn’t expired like the alarm itself.

Try this instead:

void setup() {
  Serial.begin (9600);
  Clock.setAlarmSecondsFromNow(5);
  Clock.attachAlarmInterrupt(alrm);
  Dash.pulseLED(100, 100);
}

void loop() {
  Serial.println("loop begin");
  Dash.snooze(2000);
}

void alrm() {
   Serial.println("alarm expired 5s");
   Clock.setAlarmSecondsFromNow(5);
}

While this code will work most of the time, you could have a situation where the alarm expires while “loop begin” is being printed. So every once in a while you might see something like:

loop begin
loop bealarm expired 5s
in
loop begin

The workaround for this is to have your alrm set a flag, and then print from your main loop. That way the loop and alrm aren’t both trying to use Serial at the same time

bool expired;

void setup() {
  Serial.begin (9600);
  expired = false;
  Clock.attachAlarmInterrupt(alrm);
  Clock.setAlarmSecondsFromNow(5);
  Dash.pulseLED(100, 100);
}

void loop() {
  Serial.print(".");
  if(expired) {
    expired = false;
    Serial.println();
    Serial.println("alarm expired 5s");
  }
}

void alrm() {
   expired = true;
   Clock.setAlarmSecondsFromNow(5);
}

This will print a . every time through loop. But when the alarm expires, the flag is set, and the message is printed the next time through loop. Experiment and see what you can do.


#3

thanks for your fast reply. It works pretty well but would it be possible to restart the loop from the beginning? I had in mind to apply a deepsleep 60mins into the alrm() then restart the loop from the beginning. *just trying to do a simple but reliable field data collector that will not stuck trying to connect for an extended period(I’m figuring 2 mins to connect + send message else skip the process and sleep for 1 hour).


#4

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.