Go Down

Topic: Can the DS3231 RTC calculate the Day of Week based on the Date set? (Read 1 time) previous topic - next topic

ryemac3

I created a digital clock using the DS3231 and a 16x2 LCD. I set the time and date through a gui that I wrote. There is a set button on the clock. Pressing it steps the user through each settable field which they can then increment up or down with 2 other buttons.



The day and date are manually set with the buttons. Here's the code for each field as the user steps through them:

Code: [Select]
//hours
 if (buttonCount == 1) {
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("HOURS:");
   lcd.setCursor(0,1);
   
   if (display12HrMode == false) {  //display 24 hour format
     if (hours < 10) {
       lcd.print("0");
     }
     lcd.print(hours);
   }

   else { //in 12 hr mode
      switch(hours){
   case 0:
     lcd.print("12 AM");
     break;
   case 1:
     lcd.print("1 AM");
     break;
   case 2:
     lcd.print("2 AM");
     break;
   case 3:
     lcd.print("3 AM");
     break;
   case 4:
     lcd.print("4 AM");
     break;
   case 5:
     lcd.print("5 AM");
     break;
   case 6:
     lcd.print("6 AM");
     break;
   case 7:
     lcd.print("7 AM");
     break;
   case 8:
     lcd.print("8 AM");
     break;
   case 9:
     lcd.print("9 AM");
     break;
   case 10:
     lcd.print("10 AM");
     break;
   case 11:
     lcd.print("11 AM");
     break;
   case 12:
     lcd.print("12 PM");
     break;
   case 13:
     lcd.print("1 PM");
     break;
   case 14:
     lcd.print("2 PM");
     break;
   case 15:
     lcd.print("3 PM");
     break;
   case 16:
     lcd.print("4 PM");
     break;
   case 17:
     lcd.print("5 PM");
     break;
   case 18:
     lcd.print("6 PM");
     break;
   case 19:
     lcd.print("7 PM");
     break;
   case 20:
     lcd.print("8 PM");
     break;
   case 21:
     lcd.print("9 PM");
     break;
   case 22:
     lcd.print("10 PM");
     break;
   case 23:
     lcd.print("11 PM");
     break;
   }
     
   }
 
   delay(200);
 }
 //mins
 if (buttonCount == 2) {
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("MINUTES:");
   lcd.setCursor(0,1);
   if(minutes < 10) {
     lcd.print("0");
   }
   lcd.print(minutes);
   delay(200);
 }
 //day of week
 if (buttonCount == 3) {
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("DAY OF WEEK:");
   lcd.setCursor(0,1);
   switch(dayOfWeek){
   case 1:
     lcd.print("Sun");
     break;
   case 2:
     lcd.print("Mon");
     break;
   case 3:
     lcd.print("Tue");
     break;
   case 4:
     lcd.print("Wed");
     break;
   case 5:
     lcd.print("Thu");
     break;
   case 6:
     lcd.print("Fri");
     break;
   case 7:
     lcd.print("Sat");
     break;
   }
   delay(200);
 }
 //month
 if (buttonCount == 4) {
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("MONTH:");
   lcd.setCursor(0,1);
   if(month < 10) {
     lcd.print("0");
   }
   lcd.print(month);
   delay(200);
 }
 //day of month
 if (buttonCount == 5) {
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("DAY OF MONTH:");
   lcd.setCursor(0,1);
   if(dayOfMonth < 10) {
     lcd.print("0");
   }
   lcd.print(dayOfMonth);
   delay(200);
 }
 //year
 if (buttonCount == 6) {
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("YEAR:");
   lcd.setCursor(0,1);
   lcd.print("20");
   lcd.print(year);
   delay(200);
 }


As you step through and set each field, the changes are pushed to the RTC like this:

Code: [Select]
void set_date()
{
 Wire.beginTransmission(104);
 Wire.write(3);
 Wire.write(decToBcd(dayOfWeek));
 Wire.write(decToBcd(dayOfMonth));
 Wire.write(decToBcd(month));
 Wire.write(decToBcd(year));
 Wire.endTransmission();
}

void set_time()
{
 Wire.beginTransmission(104);
 Wire.write(0);
 Wire.write(decToBcd(seconds));
 Wire.write(decToBcd(minutes));
 Wire.write(decToBcd(hours));
 Wire.endTransmission();
}


So you see, the Date and the Day of Week are sort of independent of each other. It's possible to set the Day of Week incorrectly based on the date.

My question is, do I have to manually set the Day of Week like I'm doing? Is there a way to calculate the Day of Week based on the date? Does the DS3231 provide that feature? I've searched high and low and can't seem to find the answer. I'd like to be able to configure the Day of Week automatically based on the date that is set by the user instead of the user having to do it.

elac

From DS3231 library keyword.txt try this: getDoW.  It worked great for my DS1307 RTC, as its library has the same function. For the DS1307 it was:
Code: [Select]
switch (RTC.dow)
It's all about the skills

Riva

The DS3231 cannot calculate the DoW but maybe some of the libraries for the DS1307/DS3231 will have functions to do that. The DoW value just increments every day then rolls back to 1 when it exceeds 7. It's your choice what the value means. You could decide 1=Sunday or any other day of the week.

Jack Christensen

Just to expand a bit on what Riva said, the DS3231 has a register (0x03) that tracks DoW as a number between 1 and 7. It increments at midnight and rolls back to 1 after 7. It's up to the user to decide which day corresponds to which value and set it correctly.

Personally, I usually use the Time library which does the calculation. Set the time and date, and it calculates the correct DoW. When using the Time library with an RTC, the RTC's DoW register is irrelevant (but not, of course, the date and time registers).
MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

ryemac3

Cool. Thanks. Maybe I'll look at the Time library. I just think it's silly to have to set the DOW as well as the date. I figured if I have the date, there's no need to set the DOW. It should be automatic.

Go Up