Go Down

Topic: New library for Scheduling Time Based Tasks (Read 54094 times) previous topic - next topic

Peeter123

#15
Jan 27, 2010, 08:09 pm Last Edit: Jan 27, 2010, 08:12 pm by Peeter123 Reason: 1
Think dayoffset is wrong, lets take Sunday for example. Today is Sunday.

This is your code:

unsigned long dayOffset =  ( 7 + DOW - dayOfWeek(now())) % 7;

dowSunday returns 1, dayOfWeek(now()) returns 0.

(7 + 1 - 0) % 7 = 8 % 7 = 1. So the alarm is always a day off. Correct me if I'm wrong.

I think the right code is:

unsigned long dayOffset =  ( 7 + (DOW - 1) - dayOfWeek(now())) % 7;

ps I also added some functions to your library, usable for easy printing alarms or timers:

TimeAlarms.h
Code: [Select]
 void clear();                                                 // disable and clear all alarms from memory
 time_t readAlarm(AlarmID_t ID);                   // return the value for given alarm
 time_t readTimer(AlarmID_t ID);                   //      return the value for given timer


TimeAlarms.cpp
Code: [Select]
// return the value for alarms only
time_t TimeAlarmsClass::readAlarm(AlarmID_t ID)
{
 if(ID < dtNBR_ALARMS && Alarm[ID].Mode.isAllocated && Alarm[ID].Mode.isAlarm)
   return Alarm[ID].value ;
 else       
   return 0l;  
}

// return the value for timers only
time_t TimeAlarmsClass::readTimer(AlarmID_t ID)
{
 if(ID < dtNBR_ALARMS && Alarm[ID].Mode.isAllocated && Alarm[ID].Mode.isAlarm == false && Alarm[ID].Mode.isOneShot)
   return Alarm[ID].value ;
 else       
   return 0l;  
}

void TimeAlarmsClass::clear()  // clear and disable all alarms and make them avialable for allocation  
{
 for(uint8_t id = 0; id < dtNBR_ALARMS; id++){
    Alarm[id].Mode.isEnabled = false;  
    Alarm[id].Mode.isAllocated = false;
 }
}

mem

its the dayOfWeek macro that needs to be updated, I forgot to include that change in that zip file.
Change the macro to:
#define dayOfWeek(_time_)  ((( _time_ / SECS_PER_DAY + 4)  % DAYS_PER_WEEK)+1) // 1 = Sunday


adambrum

#17
Feb 04, 2010, 10:28 pm Last Edit: Feb 04, 2010, 10:31 pm by adambrum Reason: 1
I have been having a play with this code and im hoping to use ints to set the time for alarms. I have a lcd with buttons ect so i can change the ints but i cant seem to get the code quite right. I have tried several combernations of the following code with no sucess.

Code: [Select]
#include <Time.h>
#include <TimeAlarms.h>

int onhour = 0;
int onmin = 0;
int onsec = 0;

void setup()
{
 Serial.begin(9600);    
 
 setTime(8,29,55,1,1,10); // set time to 8:29:40am Jan 1 2010
}
void MorningAlarm()
{
 Serial.println("Alarm: - turn lights off");    
}
void  loop()
{  
 Alarm.alarmRepeat(onhour,onmin,onsec, MorningAlarm);
 int onhour = 8;
 int onmin = 30;
 int onsec = 0;

 digitalClockDisplay();
 Alarm.delay(1000);
}
void digitalClockDisplay()
{
 Serial.print(hour());
 printDigits(minute());
 printDigits(second());
 Serial.println();
}
void printDigits(int digits)
{
 Serial.print(":");
 if(digits < 10)
   Serial.print('0');
 Serial.print(digits);
}



mem

the call to alarmRepeat in loop is using variables that have not been set the first time through.

It is not clear what you want to achieve, perhaps you can say what you want the sketch to do.

adambrum

What i have basicaly is a lcd which displays  time on and time off so far i can cursor around the screen and change the times, this part of the code works ok, what i need to do now is tie the alarmrepeats into the code. Idea being that the times can be changed without having to plug my laptop in.

The code i used is a cut down sketch, if i can get this to work i can adapt it work in my main code.

mem

I suggest that you simplify the task by adding something like this function to show you the alarm time.
Code: [Select]
void  setAlarmp(int onhour,int onmin,int onsec )
{  
 Serial.println("The alarm will be set to:");
 Serial.println(onhour);
 Serial.println(onmin);
 Serial.println (onsec);
 Alarm.alarmRepeat(onhour,onmin,onsec, MorningAlarm);
}


If you can get the correct values displayed then the alarm should be set accordingly. If the values are not correct then you need to fix your sketch logic.

adambrum

Managed to sort it out, just needed a break from it.

Heres the code

Code: [Select]

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

void setup()
{
 Serial.begin(9600);    
 setTime(8,29,55,1,1,10); // set time to 8:29:40am Jan 1 2010
}
void  loop()
{  
 int onhour =8;
 int onmin = 30;
 int onsec = 0;

 void  setAlarm(int onhour,int onmin,int onsec );
{
 Serial.println("The alarm will be set to:");
 Serial.println(onhour);
 Serial.println(onmin);
 Serial.println (onsec);
 Alarm.alarmRepeat(onhour,onmin,onsec, MorningAlarm);
}
digitalClockDisplay();
 Alarm.delay (1000);
}
void MorningAlarm()
 {
    Serial.println("Alarm: - turn lights off");  
 }
void digitalClockDisplay()
{
 Serial.print(hour());
 printDigits(minute());
 printDigits(second());
 Serial.println();
}
void printDigits(int digits)
{
 Serial.print(":");
 if(digits < 10)
   Serial.print('0');
 Serial.print(digits);
}



Thanks for the help

newhobby

Hi,
How can I pass a variable together with the function pointer?
Like this:
Alarm.alarmRepeat(onhour,onmin,onsec, MorningAlarm(1));

Thanks,
RI

mem

hi newhobby, the previous library, DateTimeAlarms, passed a variable (an alarm identifier) when the alarm function was called and you can look at the source code to see how that was done:  http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1217881285/15

But the new library was simplified to make it easier to use - if you need to do something specific for each alarm type, you can have each using a separate function.

Perhaps if you explain the task you want to perform I can suggest a way to achieve this without the need for passing variables in the alarm function.

newhobby

Hi mem,
I saw the previous library, but it was using an internal variable to be passed to the external function. I need an external variable to be passed to an external function.
What I'm trying to accomplish is scheduling of relays.
So, I have the parameters of the tasks being read from EEPROM and then created on setup().
Something like this:
Code: [Select]

 NumTasks=8;
 for (int a=0;a<NumTasks;a++)
 {
   EEPROM_readAnything(100,Task);
   Alarm.alarmRepeat(Task.OnTime, MorningAlarm(Task.RelayID));
 }

Would there be way to pass the function MorningAlarm the Task.RelayID that's being triggered?

mem

You could add a field in the alarm class, something like:
class AlarmClass
{  
private:
public:
 AlarmClass();
 OnTick_t onTickHandler;  
 void updateNextTrigger();
 time_t value;
 time_t nextTrigger;
 AlarmMode_t Mode;
 int tag; // new field
};

And set the value of tag in the alarm creation function. You would then use a similar callback to the one in the old library, but pass the tag instead of the alarm id.

But the disadvantage of this is that it adds one or two bytes of ram to every alarm, even if the tag is not used.

Bear in mind that your code fragment has 8 tasks but the default number of alarms is 6.
If you need 8 alarms and have not increased the value of  dtNBR_ALARMS , you can do this in TimeAlarms.h

LEDjunkie

Could this be used to leave one state, and then return to it at current time?
I'm trying to get my LED's to dim throughout the day. But I have a couple of other states that I'd like to cycle through. If I can use your code to keep track of my Day program, dim in, clouds, etc, if I leave that section to cycle through the other sections, will it return to current time of the day program? If that makes sense at all.
Say if I my day program is going. I want to turn the white on, then 3 hours later return to the day program, 3 hours down the sketch, not where I left it.
The reason I ask, is it seems I could use this to schedule the different sections of day based on time without using a RTC. Thanks for your help.

stolken

#27
Apr 28, 2010, 05:51 pm Last Edit: Apr 28, 2010, 05:52 pm by stolken Reason: 1
hey again,

Code: [Select]
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
 }

void  loop(){  
 control()



 Alarm.delay(0); // check if there is alarm
}




If my control() function contain some Alarm.delay() intruction, it will call the MorningAlarm() during control()
It may disturb control() ?

Can I use delay() only in the control() to avoid call the alarm function ?

mem

@stolken, yes, alarms will not trigger if you do not call Alarm.delay (or another TimeAlarms library function that handles alarm servicing)

If an alarm is ready to trigger it will wait until the next call to Alarm.delay before calling the handler function

mem

@LEDjunky I must have missed your previous post, if you still need help then post your question again.

If you are asking if you can schedule a function to be called at a particular time of day or after a specified interval, then yes you can do that with the TimeAlarms library. You can inspect and manipulative your application state variables in the alarm handler functions, indeed there are no special restrictions on what you can do in an alarm handler. Its just like any normal function you create in a sketch, but the function is only called when an alarm you create is triggered.

Go Up