## Time Comparison: tricks to set On/Off Time

10 posts / 0 new
Author
Message

Dear friends;
I have a Timer project using AVR and DS1307 RTC.
In this project users Set OnTime (OnHour : OnMinute) and Duration DTime(DHour : DMinute).
When time reach to Ontime the PORTTB.7 will set, and after "DTime" it will clear.
It's easy to use "if" statement to check the OnTime and DTime but i need help to use simple and usefull trick to handle the output when OnTime+DTime bigger than 24:00 or OnMinute+DMinute bigger than 60`
Please notice that we have 2 variables for each time duration (Hour, Minute).

Any comment appriciated;
Amir;

You can read the current time from your DS1307. e.g. minute, hour, day, month, year.

Just convert it into an integer. e.g. seconds since 1 Jan 1970 or minutes since 1 Jan 2000.

Likewise you can calculate your alarm time as an integer.

Then do simple 32-bit integer comparisons.

This is how Unix or Windoze determine the timestamp of your disk files. And how Make decides which files need compiling.

David.

Thanks David;
Useful way but this is a periodic timer. The time will act everyday, no date matter for example i want to turn on a device everyday a 23:50 and turn off it after 1 hour and 30 minutes...

There are 86400 seconds in 24 hours so to do something at the same time every day you just do it every time the "unixtime" has incremented by 86400. No need to involve date/time in this. However if the current unixtime is 1370197773 (18:29:33 2nd June 2013) and I want something to happen at 13:22:47 on the 5th then I can work out that is 1370438567 and therefore that is 240794 seconds ahead. That is the joy of using "unixtime", regular events are easy (every hour is just every +3600 seconds relative to where you are now for example) and so are the differences between any two specific date/times.

The principle is exactly the same. Choose a starting point, and calculate offsets from this 'fixed point'.

e.g. choose 00.00AM of your current day.
or 00.00AM of your current year.
or 00.00AM of 1970.

You could even choose 23.50 as your fixed point.

David.

Quote:

What a very 1980's question.

Modern digital TV recorders use an EPG so you just highlight a program and say "that one please". The broadcaster then embeds EIT in the MPEG transport stream and that acts as a trigger "Coronation Street beginning in 2 minutes" etc. In theory if the preceding football goes into extra time and Corrie starts 20 minutes late then ITV delay the EIT and the recorder catches it anyway. Only thing is ITV (but not BBC) hate Sky so they are notorious for deliberate EIT errors so some recordings don't work and people think their Sky+ is faulty. However no one will see the adverts in a "faulty" recording so it's a dangerous game to play.

Freeview is also DVB (DVB-T rather than DVD-S) so can also do EIT.

Sky and other recorders also permit manually timed recordings and for those they do use unixtime.

I wondered when I typed "video recorder". Then I thought to myself: "they may be obsolete, but even youngsters will remember them". After all, they had to program the recordings for their parents!

I am sure that EIT or EPG may actually use transmitted signals. OTOH, I bet that your digital TV software will calculate time_t when it has to check for overlapping recordings.

My Sky+ box can record two programs at once. My old Freeview box could only send one TV program to an external recorder.

Now, if a Sky++ box could eliminate all the adverts, I would be a very happy bunny.

Incidentally, there are many things in life that require time calculations. I just thought that TV might be more familiar than bovine reproductive cycles to the average reader.

David.

Dear friends;
Finally i used the code below:

```     eeprom int OnHour1;
eeprom int OnMinute1;
eeprom int DHour1;
eeprom int DMinute1;

int h,m,s;
.
.
.
.

void CheckTime(void)
{

int th,tho,thd,ton,toff,tnow;

th=h*60;
tnow=th+m;

tho=OnHour1*60;
ton=tho+OnMinute1;

thd=DHour1*60;
toff = ton + thd +DMinute1;
if (toff>1440) toff-=1440;

if (tnow==ton) PORTB.7=1;
if (tnow==toff) PORTB.7=0;
}
```

any better idea welcome.
Regards;
Amir;

If you update h, m, s via interrupts, you need to worry about atomicity.

Even when you have ensured the tnow is valid, I suggest that you test with >= rather than ==

Think about it. What happens at 23:59 31 Dec ?

David.

There is a issue which makes using seconds from the beginning of unix (or any other beginning) complicated -at least it seems-: it is the computation of this number of seconds. before jun,28, 2012, a thread in avrfreaks gave a link to a standard computation, and there was a fuction given, which works on avrs; I just copied it and tested on a PC under GNUlinux, and found it satisfying (therefore, themain function is only to test)):

```
//   RTC and TimeStamp Handling
//   ==========================
//
#define   RTC_SEC_PER_HOUR   (60l * 60l)
#define   RTC_SEC_PER_DAY      (RTC_SEC_PER_HOUR * 24l)
#define   RTC_SEC_PER_YEAR   (RTC_SEC_PER_DAY * 365l)

// Seconds from Jan.1, 1970 through Dec. 31, 2008.
//   -- 39 years
//   -- Leap years: 72, 76, 80, 84, 88, 92, 96, 00, 04, 08
//
//   According to Excel, there are 14245 days between those two dates.
//      365 * 39 = 14235 so that would be 10 leap years.
//
#define   RTC_SEC_TILL_2009   (RTC_SEC_PER_DAY * 14245L)

#define   RTC_YEAR_MIN   9   // 2009, as an 8-bit binary year
#define   RTC_YEAR_MAX   25   // 2025, as an 8-bit binary year

// Elapsed days at the end of each month shown (ignoring leap years)
// flash unsigned int      rtc_days[13] =
unsigned int      rtc_days[13] =
{
0,
31,      // J
59,      // F
90,      // M
120,   // A
151,   // M
181,   // J
212,   // J
243,   // A
273,   // S
304,   // O
334,   // N
365      // D
};
//   RTC and TimeStamp Handling
//   ==========================
//
#define   RTC_SEC_PER_HOUR   (60l * 60l)
#define   RTC_SEC_PER_DAY      (RTC_SEC_PER_HOUR * 24l)
#define   RTC_SEC_PER_YEAR   (RTC_SEC_PER_DAY * 365l)

// Seconds from Jan.1, 1970 through Dec. 31, 2008.
//   -- 39 years
//   -- Leap years: 72, 76, 80, 84, 88, 92, 96, 00, 04, 08
//
//   According to Excel, there are 14245 days between those two dates.
//      365 * 39 = 14235 so that would be 10 leap years.
//
#define   RTC_SEC_TILL_2009   (RTC_SEC_PER_DAY * 14245L)

#define   RTC_YEAR_MIN   9   // 2009, as an 8-bit binary year
#define   RTC_YEAR_MAX   25   // 2025, as an 8-bit binary year

typedef  long utime_t ;

struct bintime    {
int year;
int month;
int date;
int hours ;
int minutes;
int seconds ;
} temps;

//
// **************************************************************************
// *
// *   B I N T I M E 2 U N I X T I M E
// *
// **************************************************************************
//
utime_t             bintime2unixtime   (struct bintime * btimeptr)
{
// Convert the BCD time From DS1305/6 to an unsigned long UNIX timestamp
//   of seconds since the epoch-- Jan. 1, 1970.
//
// As this app never needs to go back in time or specify arbitrary dates,
//   simplifications can be done by simply calculating the whole-year
//   seconds through an arbitrary year such as 2000, 2007, or 2008.
//
// Do a quick window check on the year.  It must be > 2008, and must be less than
//   an arbitrary year--2020?
utime_t         work;   // accumulator of seconds
signed int      mult;   // working

// Base seconds, 1970 through 2008
work = RTC_SEC_TILL_2009;

// How many years since?
mult = btimeptr->year - RTC_YEAR_MIN;
if ((mult < 0) || (mult > (RTC_YEAR_MAX - RTC_YEAR_MIN + 1)))
{
mult = 0;
}
// Add the whole years since start of 2009
work += (unsigned long)mult * RTC_SEC_PER_YEAR;

// Add a day for each leap year in the prior years
work += ((unsigned long)mult/4) * RTC_SEC_PER_DAY;

// Add a day for this year, if leap year and past Feb.
if ((mult+1) % 4 == 0)
{
// Leap year
if (btimeptr->month > 2)
{
// Past February
work += RTC_SEC_PER_DAY;
}
}

// Add the days up to this month.  Use a table
mult = btimeptr->month;
if ((mult < 1) || (mult > 12))
{
mult = 1;
}

work += ((unsigned long)rtc_days[mult-1]) * RTC_SEC_PER_DAY;

// Add the days this month, up to today
mult = btimeptr->date;
if ((mult < 1) || (mult > 31))
{
mult = 1;
}

work += ((unsigned long)(mult-1)) * RTC_SEC_PER_DAY;

// Add the seconds up to this hour
mult = btimeptr->hours;
if ((mult < 0) || (mult > 23))
{
mult = 1;
}

work += ((unsigned long)(mult)) * RTC_SEC_PER_HOUR;

// Add the seconds this hour
mult = (unsigned int)60 * (unsigned int)btimeptr->minutes + (unsigned int)btimeptr->seconds;

work += mult;

return work;
}
int main() {
utime_t posi ;
temps.year=12;
temps.month=6;
temps.date=27;
temps.hours=18 ;
temps.minutes= 59;
temps.seconds= 26 ;
posi  =  bintime2unixtime(&temps);
printf("  % d\n", bintime2unixtime(&temps));
}
```