CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Add time to RTC

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
aaronik19



Joined: 25 Apr 2011
Posts: 297

View user's profile Send private message

Add time to RTC
PostPosted: Wed Feb 12, 2020 5:18 pm     Reply with quote

Dear All,

I am using the DS3231 with the PIC18F4520 on 20MHz external crystal. I would like to add the feature when someone press an external button a delay alarm of example 50s will be generated. For test I made 50s because the delay might be hours.

I do not know if it is complicated the way I figured it out....First I convert the current time in seconds (e.g: 23:13:05 in seconds will come 83605) than I add the delay seconds I need my alarm (in my case 50s so the total seconds are 83655s), after I convert everything to H:M:s (again in my case is 23:13:55) and send it to the RTC Module. For some reason on the display is showing 04:00:15. The code of my calculation is below:

Code:
  void set_alarm()
  {
   //will add 50 seconds to make alarm as test
   //first convert current time to seconds
   mytime = RTC_Get();
   calc_mytimehours = (mytime->hours * 3600);
   calc_mytimeminutes = (mytime->minutes * 60);
   calc_mytimetotal = (calc_mytimehours + calc_mytimeminutes + mytime->seconds);
   
   all_time_including_alarm = calc_mytimetotal + 50;
   
   alarm1->hours = floor(all_time_including_alarm/3600);
   calc_alarm1minutes = (all_time_including_alarm - (3600 * alarm1->hours));
   calc_alarm1minutes = (calc_alarm1minutes/60);
   calc_alarm1seconds = calc_alarm1minutes - floor(calc_alarm1minutes);
   alarm1->seconds = (calc_alarm1seconds * 60);
   
   Alarm1_Set(alarm1, HOURS_MINUTES_SECONDS_MATCH);
     Alarm1_IF_Reset();  // reset alarm1 interrupt flag
      Alarm1_Enable();
      alarms_edit(1);     // edit alarm1 ON & OFF
  }
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Feb 12, 2020 5:44 pm     Reply with quote

I use that RTC all the time now, no pun intended. It generates an interrupt every second.
You could have a variable named dly_amount, which is the # of seconds the delay is to be.50 in your test.
Another variable, dly_counts,is the count of 1Hz interrupts(seconds).
You also need an 'enable flag', dly_flag.This is set when the external button is pressed.
So within the ISR, if dly_flag is set, you compare the dly_counts to the dly_amount. When they are equal, you set the alarm_flag.
Main() looks at the staus of 'alarm_flag' and when set, sounds the buzzer.
You'll also have to reset variables as needed.

If you look in the 'code library' here, there is a Software RTC. Wthin the ISR you'll see code to increment/compare hours,minutes, etc. It should better explain what I mean.
aaronik19



Joined: 25 Apr 2011
Posts: 297

View user's profile Send private message

PostPosted: Wed Feb 12, 2020 5:49 pm     Reply with quote

Thanks for your reply. You are referring to some particular code on another page? Suppose you have delay of 4 hours, you have to compare through the 4 hours?
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Feb 12, 2020 7:49 pm     Reply with quote

Here's the link.... http://www.ccsinfo.com/forum/viewtopic.php?t=26177, located in the 'code library' forum.

There are two ways to do it.
One, take the delay value, add it to current time, store, then compare current time to store time, When = turn on buzzer

Two, take the delay value,convert into seconds, increment a 'seconds' counter in the ISR. When counter = delay value in seconds, turn on buzzer.

The second method will produce smaller code.

The actual comparison can get 'tricky' depending on the range of the alarm.
If you want 'to the second', then you need to convert hrs,min,sec to seconds and do the compare. If you need hrs and min, then you can compare once per minute. If you can live with hrs and 1/4 hrs ( 15 minute intervals), you can reduce the 'alarm time' to 96 time period(7 bits) so the comparisons are just single bytes therefore very fast compares ! I've done this for 3 decades in my energy control systems. I use the 'extra' bit of the time byte as a 'control flag'. If set, turn on the heater, if clear, turn off the heater. This method is great on low memory PICs and fast as single byte compares.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

Re: Add time to RTC
PostPosted: Wed Feb 12, 2020 11:08 pm     Reply with quote

aaronik19 wrote:

After I convert everything to H:M:s (again in my case is 23:13:55) and send it to the RTC Module, for some reason on the display is showing 04:00:15

void set_alarm()
{
//will add 50 seconds to make alarm as test
//first convert current time to seconds
mytime = RTC_Get();
calc_mytimehours = (mytime->hours * 3600);
calc_mytimeminutes = (mytime->minutes * 60);
calc_mytimetotal = (calc_mytimehours + calc_mytimeminutes + mytime->seconds);

all_time_including_alarm = calc_mytimetotal + 50;

alarm1->hours = floor(all_time_including_alarm/3600);
calc_alarm1minutes = (all_time_including_alarm - (3600 * alarm1->hours));
calc_alarm1minutes = (calc_alarm1minutes/60);
calc_alarm1seconds = calc_alarm1minutes - floor(calc_alarm1minutes);
alarm1->seconds = (calc_alarm1seconds * 60);

Alarm1_Set(alarm1, HOURS_MINUTES_SECONDS_MATCH);
Alarm1_IF_Reset(); // reset alarm1 interrupt flag
Alarm1_Enable();
alarms_edit(1); // edit alarm1 ON & OFF


You never set the value for alarm1->minutes. You do it for hours and
seconds, but not the minutes.
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Thu Feb 13, 2020 12:35 am     Reply with quote

I also worry about 'sizes'. You are using the 'mytime' structure to
hold the temporary results of the multiplications when working out the
total seconds. I doubt if these variables are large enough. Think about
it you have 59 minutes into the hour, then calculate the number of
seconds by multiplying this by 60. The 59 fits nicely in the int8 variable,
but won't hold the 3540 result of this sum. Also though you are doing the
multiplication using int8, so will actually 'get' 212.... Not what is required.

You need to be using int32 temporary variables and maths. So:
Code:

unsigned int32 temp;
mytime = RTC_Get();
temp = (mytime->hours * 3600LL); //Note the 'LL' here
temp+= (mytime->minutes * 60L); //note the 'L' here
temp+= mytime->seconds);

This then gives the int32 second count required.
The 'LL' is needed, since the maths here needs to be int32, since 3600
* 23 > 65535. The 'L' is needed since both 'minutes', and '60' are int8
values, and here we need to use int16 multiplication if it isn't to
overflow....
aaronik19



Joined: 25 Apr 2011
Posts: 297

View user's profile Send private message

PostPosted: Fri Feb 14, 2020 4:30 am     Reply with quote

Thanks to All. In fact I took the advice of temtronic to use the 1Hz output from the DS3231 and the delay become perfect. I also tested for a delay of 1 hour, it was very accurate, apart from that the code was reduced by 15%. Sometimes when you are in the middle of a problem, one forgets that he has more tools to play with. Once again thanks for the help and time that all of you offered to help me....much appreciated.
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Feb 14, 2020 6:05 am     Reply with quote

Nice that it's 'up and running' ! I use the RTC 1Hz interrupt all the time, as a basic 'tick' for projects. I use it to update the display of an LCD module as well as a 'trigger' to control/read the DS18B20 temperature sensors. Those need 750ms for 12 bit mode.
If you never use the alarm registers of the DS3231 RTC, you can use them as battery backed RAM. While only 7 bytes are available, they are useful to store some data say when powerfails.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group