Pages: [1] 2 3 4   Go Down
Author Topic: New library for Scheduling Time Based Tasks  (Read 16364 times)
0 Members and 2 Guests are viewing this topic.
London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A companion library to the Time library called TimeAlarm has been added to the Time library download: http://www.arduino.cc/playground/Code/Time

The Alarm library makes it easy to perform tasks at specific times or after specific intervals.

Tasks to be scheduled at a particular time of day are called Alarms,
tasks scheduled after an interval of time has elapsed are called Timers.
These tasks can be created to continuously repeat or to occur once only.  

An alarm can be specified to trigger a task repeatedly at a particular time of day:
  Alarm.alarmRepeat(8,30,0, MorningAlarm);  
This would call the function MorningAlarm at 8:30 am every day.

If you want the alarm to trigger only once you can use the alarmOnce  method:
  Alarm.alarmOnce(8,30,0, MorningAlarm);  
This calls a MorningAlarm() function in a sketch once only (when the time is next 8:30am)

Timers trigger tasks that occur after a specified interval of time has passed.
The timer interval can be specified in seconds, or in hour, minutes and seconds.
  Alarm.timerRepeat(15, Repeats);            // timer task every 15 seconds    
This calls the a  Repeats() function in your sketch every 15 seconds.

If you want a timer to trigger once only, you can use the timerOnce method:
  Alarm.timerOnce(10, OnceOnly);             // called once after 10 seconds
This calls the onceOnly() function in a sketch 10 seconds after the timer is created.

Here is an example sketch that illustrates this functionality:
Code:
//This sketch  triggers daily alarms at 8:30 am and 17:45 pm.
//A Timer is triggered every 15 seconds, another timer triggers once only after 10 seconds.

#include <Time.h>
#include <TimeAlarms.h>

void setup()
{
  setTime(8,29,0,1,1,10); // set time to 8:29:00am Jan 1 2010
  // create the alarms
  Alarm.alarmRepeat(8,30,0, MorningAlarm);  // 8:30am every day
  Alarm.alarmRepeat(17,45,0,EveningAlarm);  // 5:45pm every day
 
  Alarm.timerRepeat(15, Repeats);          // timer for every 15 seconds    
  Alarm.timerOnce(10, OnceOnly);          // called once after 10 seconds
}

void  loop(){  
  digitalClockDisplay();
  Alarm.delay(1000); // wait one second between clock display
}

// functions to be called when an alarm triggers:
void MorningAlarm(){
  Serial.println("Alarm: - turn lights off");    
}

void EveningAlarm(){
  Serial.println("Alarm: - turn lights on");          
}

void Repeats(){
  Serial.println("15 second timer");        
}

void OnceOnly(){
  Serial.println("This timer only triggers once");  
}

void digitalClockDisplay()
{
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println();
}

void printDigits(int digits)
{
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}
Note that the loop code calls Alarm.delay(1000) -  Alarm.delay must be used
instead of the usual arduino delay function because the alarms are serviced in the Alarm.delay method.
Failing to regularly call Alarm.delay will result in the alarms not being triggered
so always use Alarm.delay instead of delay in sketches that use the Alarms library.

More details are in the readme.txt file in the download
Logged

London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

FAQ for the Timer Alarm library

Q: What hardware and software is needed to use this library?
A: This library works with the Time library. No internal or external hardware is used by the Alarm library.

Q: Why must I use Alarm.delay() instead of delay()?
A: Task scheduling is handled in the Alarm.delay function.
Tasks are monitored and  triggered from within the Alarm.delay call so Alarm.delay should be called whenever a delay is required in your sketch.
If your sketch waits on an external event (for example,  a sensor change), make sure you repeatedly call Alarm.delay while checking the sensor.
You can call Alarm.delay(0) if you need to service the scheduler without a delay.

Q: Are there any restrictions on the code in a task handler function?
A: No. The scheduler does not use interrupts so your task handling function is no different from other functions you create in your sketch.

Q: What are the shortest and longest intervals that can be scheduled?
A:  Time intervals can range from 1 second to years.
(If you need timer intervals shorter than 1 second then the TimedAction library
by Alexander Brevig may be more suitable, see: http://www.arduino.cc/playground/Code/TimedAction)

Q: How are scheduled tasks affected if the system time is changed?
A: Tasks are scheduled for specific times designated by the system clock. If the system time is reset to a later time (for example one hour ahead) then all alarms and timers will occur one hour later.
If the system time is set backwards (for example one hour back) then the alarms and timers will occur an hour earlier.
If the time is reset before the time a task was scheduled, then the task will be triggered on the next service (the next call to Alarm.delay).
This is  the expected behaviour for Alarms – tasks scheduled for a specific time of day will trigger at that time, but the affect on timers may not be intuitive. If a timer is scheduled to trigger in 5 minutes time and the clock is set ahead by one hour, that timer will not trigger until one hour and 5 minutes has elapsed.

Q: How many alarms can be created?
A: Up to six alarms can be scheduled.  
The number of alarms can be changed in the TimeAlarms header file (set by the constant dtNBR_ALARMS, note that 12 bytes of RAM are required for each timer)

onceOnly Alarms and Timers are freed when they are triggered so another onceOnly alarm can be set to trigger again.
There is no limit to the number of times a onceOnly alarm can be reset.

The following fragment gives one example of how a timerOnce  task can be rescheduled:
Alarm.timerOnce(random(10), randomTimer);  // trigger after random number of seconds

void randomTimer(){
  int period = random(2,10);             // get a new random period
  Alarm.timerOnce(period, randomTimer);  // trigger for another random period
}
Logged

0
Offline Offline
Full Member
***
Karma: 4
Posts: 218
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Can arduino be put to sleep and then awakened once each day to save battery ?

Q. How to do please mem?
A. ?
« Last Edit: January 12, 2010, 03:53:11 pm by april.steel » Logged

London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

April, unfortunately, it can't be done with this library because it relies on the Arduino software clock (using the millis function), therefore  the processor chip needs to be active to keep track of the time.

You may want to look at using an external  Real Time Clock chip that can generate an interrupt once a day to wake up the Arduino. Have a look in the Playground to see if anyone has written any code to do this.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

once set, can you turn an alarm or timer off?
Logged

London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, timers can be enabled and disabled.

To disable and enable timers and alarms you need to store the timer Id that is returned when by the create method
This Id can be used to disable and enable the alarm.

AlarmId   myTimer = Alarm.timerRepeat(15, Repeats);  

if(some condition)
   Alarm.disable(myTimer);  // prevent my timer from triggering
else
  Alarm.enable(myTimer);  //enable  my timer to trigger

Note that disabled alarms and timers still consume resources so disabled timers count in the limit on the maximum number.

I did not include the disable/enable functionality in the documentation because I am not convinced that introducing the concept of AlarmIds in the documentation would be add value for most users.

For example, when a timer is disabled and then enabled, would people expect the timer acts is if it was just created (any previous time counted before the timer was disabled is ignored).  
Say a timer is set to repeat every hour.   The timer is disabled half an hour before its due to trigger. If it is immediately re-enabled, should it trigger in an hour (they way it works now) or in half an hour?
« Last Edit: January 21, 2010, 03:54:58 am by mem » Logged

Netherlands
Offline Offline
Newbie
*
Karma: 0
Posts: 10
Arduino FTW!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Can you please update your library, to schedule alarms to specific times at specific days of the week. If you can find the time ofcourse.

It would be really cool to schedule diferrent alarms at different days of the week smiley-wink

Thx
Logged

London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Peeter, the logic is in the library but it hasn't been tested and the user interface isn't there. If you would like to try it, add this to the top of the sketch:

Code:
#define AlarmDHMS(D,H,M,S)  (((D-1)* SECS_PER_DAY)  +  (H * SECS_PER_HOUR) + (M* SECS_PER_MIN)  + S)

and in setup create an alarm, in this example its for every Monday morning at 8:30 am:
Code:
 Alarm.alarmRepeat( AlarmDHMS(dowMonday,8,30,0),weeklyAlarm);  

create a function named weeklyAlarm and give it a try.

The defined days are:
 dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday



« Last Edit: January 22, 2010, 04:15:00 pm by mem » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It does not seem to be working for me.
this is the code bits....

  AlarmId loggit = Alarm.timerRepeat(TMR_LOGGER, logTime);             // log scheduler alarm


void fullLog() {                                     // Stop logging when full
  addr = 0;                                           // reset address pointer
  Alarm.disable(loggit);                          // shut off logTime alarm
}

I get;
in function 'void fullLog()'
error: 'loggit' was not declared in this scope

what am I doing wrong?
Logged

London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

the loggit variable is probably not visible to the fillLog function. try it with loggit declared as a global variable :
Code:
#include <Time.h>
#include <TimeAlarms.h>

#define TMR_LOGGER  60
AlarmId loggit;           // create loggit as a global variable

void setup(){
  Serial.begin(9600);
  loggit = Alarm.timerRepeat(TMR_LOGGER, logTime);     // create log scheduler alarm and store the id in loggit
}

void logTime(){
  Serial.println("Alarm");    
}
 
void  loop(){  
  
}

void fullLog() {                                     // Stop logging when full
 addr = 0;                                           // reset address pointer
 Alarm.disable(loggit);                          // shut off logTime alarm
}
« Last Edit: January 24, 2010, 10:09:10 pm by mem » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh yeah, I should have known that..

that fixed it!
thank you very much.
Logged

Netherlands
Offline Offline
Newbie
*
Karma: 0
Posts: 10
Arduino FTW!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Peeter, the logic is in the library but it hasn't been tested and the user interface isn't there. If you would like to try it, add this to the top of the ...

Mem, this doesnt work, if i add an alarm for Sunday the alarm triggers today. If i add an alarm for monday the alarm triggers tomorrow. Can you explain why? smiley-wink

I'm guessing its days from now and not weekdays.
« Last Edit: January 26, 2010, 12:32:27 pm by Peeter123 » Logged

London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Peeter, Yes, the library is doing the calculation assuming the week starts at the previous midnight.
The best way to fix this is for me to add a method that creates an alarm that takes the day as well as H,M,S. That makes it easier for the library to calculate the number of days from today to the requested day of the alarm. I will try to add this into the library this week.
Logged

London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Peeter, I found a few minutes to add a method to specify a day of the week for alarms
example usage:  Alarm.alarmRepeat(dowTuesday,8,40,0, WeeklyAlarm);  // 8:40 on tuesday
 
You can get the download from here
http://www.arduino.cc/playground/uploads/Code/time_proto.zip

I have not had time to test it so would be interested to hear how you get on.
« Last Edit: January 26, 2010, 03:12:36 pm by mem » Logged

Netherlands
Offline Offline
Newbie
*
Karma: 0
Posts: 10
Arduino FTW!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks! Gonna try tommorow. Will report back to you!
Logged

Pages: [1] 2 3 4   Go Up
Jump to: