News:

Let's find out together what makes a PIC Tick!

Main Menu

Day of the week

Started by joesaliba, Dec 15, 2022, 09:01 PM

Previous topic - Next topic

joesaliba

I am using a DS3231 for time keeping and date. It seems that after I set the date, the day of week is not updated accordingly.

Or I didn't read the datasheet properly or else, the DS3231 does not track and update the day of the week. I think that the later is correct, as according to some reading, to calculate the day of the week we also need the century, of which the DS3231 does not have.

For anyone interested, from the reading I did on calculations I did a small procedure, which seems to be working correctly: -

'===================================================================================================
'***********************************************
'* Find the day of week of a date              *
'* Input : YY holds the interested year        *
'* Output: Returns the day of week; 1 = Monday *
'* Notes : Century can be added to get dates   *
'*       : from different centuries            *
'***********************************************

 proc Day_of_Week(YY as byte, MM as byte, Date_of_Month as byte), byte

    dim Year_Code   as byte         ' Variable to hold Year Code
    dim Month_Code  as byte         ' Variable to hold Month Code
    dim Cent_Code   as byte         ' 1700's = 4, 1800's = 2, 1900's = 0, 2000's = 6
                                    ' 2100's = 4, 2200's = 2, 2300s = 0
    dim Leap_Year   as bit          ' Flag to indicate if it's leap year; 0 = Not leap , 1 = leap

    cent_code = 6                   ' Century code is 6 for century 2000

'--------------------------------------------------------------------------------------------------

    year_code = (YY / 4) + YY       ' Do not use the century for year, i.e.: - Year 2022 use only 22
    year_code = year_code // 7      '

    month_code = lookupl mm, [0, 0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5] ' Get Month Code according to current month

    Leap_year = 0                   ' Reset Leap Year

    for bloop = 0 to 96 step 4      ' Create a loop wit a x4 increase to detect leap year
        if bloop = YY then          ' If loop equals year then
            Leap_year = 1           ' it is a leap year, so set Leap bit
        else leap_year = 0          ' else if it not leap year, clear Leap_Year
        endif                       ' End If...Then instruction
    next                            ' next loop

    result = year_code + month_code + cent_code + date_of_month - leap_year
    result = result // 7            '

 endproc
 

Then to get the day of the week: -

Global_DayNum = day_of_week(Global_year, Global_month, Global_day)
NOTE: - Global_year should input the LAST two digit of the year, i.e.: - 2022, input only 22

Century is fixed for the years 2000's, for different centuries please update with appropriate century code: -

cent_code = 6                   ' Century code is 6 for century 2000
or add another input directly to the procedure.

Regards

Joe

keytapper

Thanks for sharing.
I had some experiment with date and time, but I consider the fact that we don't need much expansion to other century, so calculation may be lowered to a couple of decades. For my project I just expect to last no more than a decade, if any.

The DS3231 has the weekday at register $03, just the last 3 bits, didn't get the result of it?
QuoteThe day-of-week register increments at midnight.
low while SCL is high, generating a START condition.
Values that correspond to the day of week are user-defined but must be sequential (i.e., if 1 equals
Sunday, then 2 equals Monday, and so on). Illogical time and date entries result in undefined operation
Sorry I didn't tried, but if I'm not wrong it's necessary to write a value first, corresponding to the day of the week of the written period, then the RTC will increase at midnight. Values bigger than 7 might be crippled down.
So reading the register it should be ANDed with 0b0000111.
Ignorance comes with a cost

joesaliba

Keytapper,

That is why I wrote that procedure because the DS3231 does not set the weekday directly. With the procedure is very easy.

Someone else will input the date so I eliminated the need to add another routine to set the date.

I needed this so I can add day light saving. Here again I read some on the internet and what a load of crap and formulas I saw just to get the daylight saving.

The routine I came up with is very, very, very easy. I will add this when I have some time.

Regards

Joe

Ivano

In DS3231 you have to set all the registers, it doesn't do any calculation of the variables
Once the registers are set, he goes ahead by himself updating all the variables.
I usually run DS3231 in UTC.
After reading it, I transform it into local time taking into account the time zone (only positive at the moment) and summer or winter time.
when I save I transform first into UTC time.
He always goes forward in UTC time and the pic reading the DS 3231 is able to calculate the local time even if powered after a long time, provided that the DS battery works :-)
Sorry google translate

keytapper

There are some C library for date and time. Most of them convert the time in seconds and it's calculated by a starting epoch. Some is set on 1/1/1970, the so called Unix time.
What that makes is to perform the time calculation, which involves the DST too. 
But  for a simple project, the beginning of the year will widely suffice, the just count how many seconds are passed since then.
There are libraries to deal with local time as well, which is including the DST calculating rules.
I think that it is not hard to convert these libraries in basic.
Ignorance comes with a cost