/* Source - http://osoyoo.com/2017/09/12/arduino-lesson-real-time-clock-rtc-module-ds3231/
Modified 12 hours format removing Temp with simple if-else. Also 3 char month name print on lcd.
Printing 4 digit year on 16x2 lcd with leading '20' is merely showing century and looks good until end of this century ;)
Thanks OSOYOO.COM
*/
#include <Wire.h> // For the i2c devices
#include <LiquidCrystal_I2C.h> // For the LCD
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
#define DS3231_I2C_ADDRESS 104 // RTC is connected, address is Hex68 (Decimal 104)
// SCL - pin A5
// SDA - pin A4
// To set the clock, run the sketch and use the serial monitor.
// Enter T0000123010119; the code will read this and set the clock. See the code for full details.
//
byte seconds, minutes, hours, day, date, month, year;
char monthName[4];
char weekDay[4];
void setup()
{
Wire.begin();
Serial.begin(9600);
lcd.init(); // initialize the lcd
}
void loop()
{
watchConsole();
get3231Date();
// Print a message to the LCD.
lcd.backlight();
lcd.setCursor(0,0);
lcd.print("Time ");
if (hours<=12)
{
lcd.print(hours, DEC);
lcd.print(":");
lcd.print(minutes, DEC);
lcd.print(":");
lcd.print(seconds, DEC);
lcd.print(" ");
lcd.setCursor(14,0);
lcd.print("AM");
} else {
lcd.print((hours-12), DEC);
lcd.print(":");
lcd.print(minutes, DEC);
lcd.print(":");
lcd.print(seconds, DEC);
lcd.print(" ");
lcd.setCursor(14,0);
lcd.print("PM");
}
lcd.setCursor(0,1);
lcd.print(weekDay);
lcd.print(", ");
lcd.print(date, DEC);
lcd.print("-");
//lcd.print(month, DEC);
lcd.print(monthName);
lcd.print("-20");
lcd.print(year, DEC);
delay(1000);
}
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
void watchConsole()
{
if (Serial.available()) { // Look for char in serial queue and process if found
if (Serial.read() == 84) { //If command = "T" Set Date
set3231Date();
get3231Date();
}
}
}
void set3231Date()
{
//T(sec)(min)(hour)(dayOfWeek)(dayOfMonth)(month)(year)
//T(00-59)(00-59)(00-23)(1-7)(01-31)(01-12)(00-99)
//Example: 01-Jan-19 @ 12:00:00 for the 3rd day of the week -> T0000123010119
// T0000123010119
seconds = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48)); // Use of (byte) type casting and ascii math to achieve result.
minutes = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
hours = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
day = (byte) (Serial.read() - 48);
date = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
month = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
year = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0x00);
Wire.write(decToBcd(seconds));
Wire.write(decToBcd(minutes));
Wire.write(decToBcd(hours));
Wire.write(decToBcd(day));
Wire.write(decToBcd(date));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}
void get3231Date()
{
// send request to receive data starting at register 0
Wire.beginTransmission(DS3231_I2C_ADDRESS); // 104 is DS3231 device address
Wire.write(0x00); // start at register 0
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 7); // request seven bytes
if(Wire.available()) {
seconds = Wire.read(); // get seconds
minutes = Wire.read(); // get minutes
hours = Wire.read(); // get hours
day = Wire.read();
date = Wire.read();
month = Wire.read(); //temp month
year = Wire.read();
seconds = (((seconds & B11110000)>>4)*10 + (seconds & B00001111)); // convert BCD to decimal
minutes = (((minutes & B11110000)>>4)*10 + (minutes & B00001111)); // convert BCD to decimal
hours = (((hours & B00110000)>>4)*10 + (hours & B00001111)); // convert BCD to decimal (assume 24 hour mode)
day = (day & B00000111); // 1-7
date = (((date & B00110000)>>4)*10 + (date & B00001111)); // 1-31
month = (((month & B00010000)>>4)*10 + (month & B00001111)); //msb7 is century overflow
year = (((year & B11110000)>>4)*10 + (year & B00001111));
}
else {
//NULL
}
switch (day) {
case 1:
strcpy(weekDay, "Sun");
break;
case 2:
strcpy(weekDay, "Mon");
break;
case 3:
strcpy(weekDay, "Tue");
break;
case 4:
strcpy(weekDay, "Wed");
break;
case 5:
strcpy(weekDay, "Thu");
break;
case 6:
strcpy(weekDay, "Fri");
break;
case 7:
strcpy(weekDay, "Sat");
break;
}
switch (month) {
case 1:
strcpy(monthName, "Jan");
break;
case 2:
strcpy(monthName, "Feb");
break;
case 3:
strcpy(monthName, "Mar");
break;
case 4:
strcpy(monthName, "Apr");
break;
case 5:
strcpy(monthName, "May");
break;
case 6:
strcpy(monthName, "Jun");
break;
case 7:
strcpy(monthName, "Jul");
break;
case 8:
strcpy(monthName, "Aug");
break;
case 9:
strcpy(monthName, "Sep");
break;
case 10:
strcpy(monthName, "Oct");
break;
case 11:
strcpy(monthName, "Nov");
break;
case 12:
strcpy(monthName, "Dec");
break;
}
}