|
|
View previous topic :: View next topic |
Author |
Message |
aaronik19
Joined: 25 Apr 2011 Posts: 297
|
Add time to RTC |
Posted: Wed Feb 12, 2020 5:18 pm |
|
|
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: 9225 Location: Greensville,Ontario
|
|
Posted: Wed Feb 12, 2020 5:44 pm |
|
|
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
|
|
Posted: Wed Feb 12, 2020 5:49 pm |
|
|
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: 9225 Location: Greensville,Ontario
|
|
Posted: Wed Feb 12, 2020 7:49 pm |
|
|
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
|
Re: Add time to RTC |
Posted: Wed Feb 12, 2020 11:08 pm |
|
|
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: 19504
|
|
Posted: Thu Feb 13, 2020 12:35 am |
|
|
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
|
|
Posted: Fri Feb 14, 2020 4:30 am |
|
|
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: 9225 Location: Greensville,Ontario
|
|
Posted: Fri Feb 14, 2020 6:05 am |
|
|
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. |
|
|
|
|
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
|