/*
This sketch uses Wire.h library to communicate with DS1307 / DS3231 module without using a dedicated library
See YouTube channel Rudolf - 'Learn everything about the DS3231-SN Real Time Clock | Use without Arduino Library'
DS1307 / DS3231 I2C address is fixed at 0x68
To enable communication, both the SDA and SCL lines should have 4.7K pull-up resistors.
- These are built into the DS1307 / DS3231 RTC module
The simulated DS1307 is automatically initialized to the current system time when starting the simulation.
It then keeps counting the time. You can override the initial time by setting the initTime attribute
to a different value. The value can be either a valid ISO 8601 date string (e.g. "2019-11-19T11:41:56Z"),
or one of the following special values:
"0" - Set the initial time to "2000-01-01T00:00:00Z"
"now" - Set the initial time to the current system time
Note that "Z" at the end of the date string indicates that the time is in UTC, and not in the local time zone. If you omit the "Z", the time will be interpreted as local time.
CM 12/25/24:
Simulation feels a bit buggy. Doesn't alway return the values expected.
** DOES NOT! ** Work in 12 hour mode.
*/
#include <Wire.h>
#define DS1307_ADDR 0x68
// dayofWeek 1,Monday 2,Tuesday 3,Wednesday 4,Thursday 5,Friday 6,Saturday 7,Sunday
/* - - - - - - - - - -
Two ways to enter time and date.
1. Set a value for each item, then compile and upload at the assigned time
2. Use __TIME__ to obtain the values from the system clock at time of compile.
*/
uint8_t day = 6, date = 28, month = 12;
// seconds = 47, minutes = 58, hours = 23,
char time[] = __TIME__;
int UTC = atoi(&time[0]); // does not obtain hours from computer clock
int hours = UTC - 6; // UTC (GMT: 0) -> CST (GMT: -6)
int minutes = atoi(&time[3]);
int seconds = atoi(&time[6]);
int year = 24;
uint8_t hour; // AM or PM hour
uint8_t hoursAMPM;
// in this sketch, AM-PM is not used
bool isPM = false; // 0x02 Hour regester, Bit 5 is set low(0) for AM and set high(1) for PM
bool is12HourMode;
void setup() {
Serial.begin(115200);
Wire.begin();
hoursAMPM = dectoBcd(hours); // 1st: set the hour, in this example 11 or (0001 + 0001) in BCD
Serial.print("24hr mode: "); Serial.println(hoursAMPM, BIN);
// 2nd: Set the DS3231 12-hour format bit settings
// 0x02 Hour address, Bit 6 is set high(1) for 12 hour format or set low(0) for 24 hour format
// In this sketch, 12 hour mode is not selected
hoursAMPM = hoursAMPM | 0b00000000; // OR's 00010001 | 00000000 = (0001 + 0001)
// 3rd: Is PM set to 'true'?
// In this sketch, AM-PM is not used
if (isPM) { // Bit 5 set high in 12 hour mode = PM
hoursAMPM = hoursAMPM | 0b00000000; // OR's 01010001 | 00000000 = (0101 + 0001)
Serial.print(hoursAMPM, BIN);
}
// Set-Time by writing to DS3231
Wire.beginTransmission(DS1307_ADDR); // start communication using DS3231 hex address
Wire.write(0x00); // write to register address 0x00 the seconds register
Wire.write(dectoBcd(seconds)); // write seconds in BCD format, 0100(MSB) and 0111(LSB)
Wire.write(dectoBcd(minutes));
Wire.write(hoursAMPM); // Has already been converted to dectoBcd
Wire.write(dectoBcd(day));
Wire.write(dectoBcd(date));
Wire.write(dectoBcd(month));
Wire.write(dectoBcd(year));
Wire.endTransmission();
}
void loop() {
Wire.beginTransmission(DS1307_ADDR);
Wire.write(0); // Start reading from address 0 (seconds)
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDR, 7); // Request seconds, minutes, hours, day, date, month, year
if (Wire.available()) { // Also works when 'if' statement removed
seconds = bcdToDec(Wire.read() & 0x7F); // Mask the high bit of seconds
minutes = bcdToDec(Wire.read() & 0x7F);
hoursAMPM = Wire.read();
is12HourMode = hoursAMPM & 0x40; // Check if DS3231 is in 12-hour mode
if (is12HourMode) {
Serial.println("12-hour");
isPM = hoursAMPM & 0x20; // Check if it's PM
hour = bcdToDec(hoursAMPM & 0x1F); // Mask the high three bits for 12-hour mode
}
else {
Serial.println("24-hour");
hour = bcdToDec(hoursAMPM & 0x3F); // 24-hour mode, mask the high two bits
}
day = bcdToDec(Wire.read());
date = bcdToDec(Wire.read());
month = bcdToDec(Wire.read());
year = 2000 + bcdToDec(Wire.read());
// Print to Serial Monitor
Serial.print("Date: ");
Serial.print(year);
Serial.print("-");
Serial.print(month);
Serial.print("-");
Serial.print(date);
Serial.print(" ");
Serial.println(dayOfWeekToStr(day));
// Print to Serial Monitor
Serial.print("Time: ");
Serial.print(hour);
Serial.print(":");
if (minutes < 10) Serial.print("0");
Serial.print(minutes);
Serial.print(":");
if (seconds < 10) Serial.print("0"); // Add a '0' to seconds
Serial.print(seconds);
Serial.print(is12HourMode ? (isPM ? " PM" : " AM") : ""); // Empty string if in 24-hour mode
Serial.println();
}
delay(900);
}
// - - - - FUNCTIONS - - - -
byte bcdToDec(byte val) {
return ((val / 16 * 10) + (val % 16));
}
byte dectoBcd(byte val) {
return ((val / 10 * 16) + (val % 10)); // This works the same as below
//return ((val / 10 << 4) + (val % 10)); // This works the same as above
}
String dayOfWeekToStr(byte dayOfWeek) {
switch (dayOfWeek) {
case 1: return "Monday ";
case 2: return "Tuesday ";
case 3: return "Wednesday";
case 4: return "Thursday ";
case 5: return "Friday ";
case 6: return "Saturday ";
case 7: return "Sunday ";
default: return "Err ";
}
}