Alarm using TimeAlarms has no effect

A project I’m working on has scheduled events so I want to use the TimeAlarms library. Nothing is happening at the appointed time so I wrote the following sketch program to test my use of alarmRepeat. It, too, is not acting as expected. It’s supposed to turn on an LED two minutesUntilAlarm minutes after rebooting. Will you please take a look at it and see what’s wrong (@bko)? My first draft had the day, hour, and minute hard coded in but I got tired of editing the minute value every time I wanted to test it again.

#include <TimeAlarms.h>

void setup() {
  // Update clock
  while (Particle.syncTimePending());  // Wait here for sync to finish
  Time.zone(-4);  // Eastern time zone

  // Schedule alarm
  const uint8_t minutesUntilAlarm = 2;
  uint8_t dd = Time.weekday();
  uint8_t mm = Time.minute() + minutesUntilAlarm;
  uint8_t hh = Time.hour() + (mm / 60);
  mm %= 60;    
  Alarm.alarmRepeat(dd, hh, mm, turnOnLED);
    
  // Configure I/O    
  pinMode(D0, OUTPUT);

}

void loop() {
  Alarm.delay(500);  // Have to call this to get TimeAlarms to check status of any alarms
    
}

void turnOnLED() {
  digitalWrite(D0, HIGH);
    
}

@raequin, add a debug print statement to check that the time you are computing is as expected.

I hear ya, @peekay123, but even when I hard coded the time, for example

Alarm.alarmRepeat(3, 11, 28, turnOnLED);

the alarmRepeat did not work. That is, turnOnLED never ran. Thanks.

You seem to using the wrong overloaded method

AlarmID_t alarmRepeat(const timeDayOfWeek_t DOW, const int H,  const int M,  const int S, OnTick_t onTickHandler);

when you set

Alarm.alarmRepeat(3, 11, 28, turnOnLED);

it is using

 AlarmID_t alarmRepeat(const int H,  const int M,  const int S, OnTick_t onTickHandler); // as above, with hms arguments
1 Like

You caught it! I’m good to go, now. Thanks for your time :slight_smile:

One last question: Is the TimeAlarms delay() function blocking (like Arduino’s delay()) or does it behave in some different way?

Alarm.delay() just counts the millis() for each object in the Alarm array which keeps the TimeAlarm objects. and will never block. The delay you are referring to is a system function that pauses everything and is part of the Particle language also.

Alarm.delay() just counts the millis() for each object in the Alarm array which keeps the TimeAlarm objects

It sounds to me like you're saying Alarm.delay() updates the clocks for the TimeAlarms objects it manages. Given this explanation it makes sense that it would not be a blocking function. However, I have two problems with it. First, why is it named, "delay?" That seems a poor description of what it's doing (if I read your explanation right). Second, what is the point of the argument passed to Alarm.delay() if it only updates clocks for objects in its array?

This is correct.

Yes! It just reads the time_t value against Time.now(). If time_t > Time.now() trigger handler and update trigger for next alarm. That is all. No while loop.[quote="raequin, post:8, topic:32835"]
First, why is it named, "delay?" That seems a poor description of what it's doing (if I read your explanation right).
[/quote]

Delay as the parameter uses a millis based timer and you can put 5000 in there and the function will only run every 5 seconds.

If you are using TimeAlarms you are counting in seconds not milliseconds or microseconds so a delay of 1000 loops through the array every one second.

You should open up the h and cpp file to see how it works. I use TimeAlarms for writing demo code or prototyping. Anything with more complexity and i would rather make a custom timer.

Based on my feeble grasp of C++ it seems that Alarms.delay() is blocking, based on this code from TimeAlarms.cpp:

void TimeAlarmsClass::delay(unsigned long ms)
{
  unsigned long start = millis();
  while( millis() - start  <= ms)
    serviceAlarms();
}

Also, the way I read the description you kindly provided for me it seems one would just call Alarms.delay() in setup() but all the comments I’ve seen on other threads say that it must be inside of loop(). This matter is still not clear to me. Thanks again for your attention.

I doubt the delay code can ever block as long as millis() keeps working. Millis = milliseconds since startup. Please put some variables in there and see what the exit condition looks like.

No Alarm.delay() runs in the loop continuously. Placing it in setup will not work. See how millis based timers for work Here.That should help.

Hi @raequin

Glad you found the right overload for your alarm.

The delay function is blocking but you can call it with an argument of 0, so that it spends the minimum time blocked.

Edit: you must call the alarm delay method in order for the alarms to go off, so you should call it in loop().

Thanks, @bko. Could you elucidate why one would pass a non-zero argument to the Alarms.delay function? Would that be for a replacement to the built in delay function (that has the side effect of servicing the alarms)?

Hi @raequin

You need to call the alarm delay method periodically if you want your alarms to go off. The library does not use interrupts or any other way of taking control since it comes from Arduino land where there is largely no thread-based programming. If you don’t call alarm delay, your alarm functions will never get called.

If you do not need an actual delay in your loop function, just call alarm delay with 0 to service the alarm function.

My bad i re-wrote the code in delay to not use the while loop because it blocked and completely forgot about it

unsigned long currentMillis = millis();
		 if (millis() - previousMillis >= ms) {
			 previousMillis = currentMillis;
			 serviceTimers();
		 }
1 Like