├── library.properties ├── keywords.txt ├── README.md ├── examples ├── timestamp │ └── timestamp.ino ├── ds1307nvram │ └── ds1307nvram.ino ├── softrtc │ └── softrtc.ino ├── ds1307SqwPin │ └── ds1307SqwPin.ino ├── ds3231alarm │ └── ds3231alarm.ino ├── ds1307 │ └── ds1307.ino ├── datecalc │ └── datecalc.ino ├── ds3231 │ └── ds3231.ino └── ds3231_v2 │ └── ds3231_v2.ino ├── RTClib.h └── RTClib.cpp /library.properties: -------------------------------------------------------------------------------- 1 | name=RTClib 2 | version=1.1.0 3 | author=Adafruit 4 | maintainer=Adafruit 5 | sentence=A fork of Jeelab's fantastic RTC library 6 | paragraph=A fork of Jeelab's fantastic RTC library 7 | category=Timing 8 | url=https://github.com/adafruit/RTClib 9 | architectures=* 10 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For RTC 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | DateTime KEYWORD1 10 | TimeSpan KEYWORD1 11 | RTC_DS1307 KEYWORD1 12 | RTC_DS3231 KEYWORD1 13 | RTC_Millis KEYWORD1 14 | Ds1307SqwPinMode KEYWORD1 15 | 16 | ####################################### 17 | # Methods and Functions (KEYWORD2) 18 | ####################################### 19 | 20 | year KEYWORD2 21 | month KEYWORD2 22 | day KEYWORD2 23 | hour KEYWORD2 24 | minute KEYWORD2 25 | second KEYWORD2 26 | dayOfWeek KEYWORD2 27 | secondstime KEYWORD2 28 | unixtime KEYWORD2 29 | begin KEYWORD2 30 | adjust KEYWORD2 31 | isrunning KEYWORD2 32 | now KEYWORD2 33 | checkRollover KEYWORD2 34 | timestamp KEYWORD2 35 | readSqwPinMode KEYWORD2 36 | writeSqwPinMode KEYWORD2 37 | getTemperature KEYWORD2 38 | getA1Time KEYWORD2 39 | setA1Time KEYWORD2 40 | setAlarm1Simple KEYWORD2 41 | turnOnAlarm KEYWORD2 42 | turnOffAlarm KEYWORD2 43 | checkAlarmEnabled KEYWORD2 44 | checkIfAlarm KEYWORD2 45 | 46 | ####################################### 47 | # Constants (LITERAL1) 48 | ####################################### 49 | TIMESTAMP_FULL LITERAL1 50 | TIMESTAMP_DATE LITERAL1 51 | TIMESTAMP_TIME LITERAL1 52 | 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a fork of JeeLab's fantastic real time clock library for Arduino. 2 | 3 | For details on using this library with an RTC module like the DS1307, see the guide at: https://learn.adafruit.com/ds1307-real-time-clock-breakout-board-kit/overview 4 | 5 | To download. click the DOWNLOADS button to the right, and rename the uncompressed folder RTClib. 6 | 7 | Place the RTClib folder in your arduino_sketch_folder/libraries/ folder. 8 | You may need to create the libraries subfolder if its your first library. 9 | Restart the IDE. 10 | 11 | Basic functions (see libraries/examples of how to use): 12 | - .begin 13 | - .adjust 14 | - .isrunning 15 | - .now 16 | 17 | DS1307 specific functions: 18 | - .readnvram
19 | - .writenvram 20 | - .readSqwPinMode 21 | - .writeSqwPinMode 22 | 23 | PCF8523 specific functions: 24 | - .writeSqwPinMode 25 | 26 | DS3231 specific functions: 27 | - .getTemperature 28 | - .getA1Time 29 | - .setA1Time 30 | - .setAlarm1Simple 31 | - .turnOnAlarm 32 | - .turnOffAlarm 33 | - .checkAlarmEnabled 34 | - .checkIfAlarm 35 | 36 | Millis (software RTC) specific functions: 37 | - .checkRollover 38 | 39 | ##Compatibility 40 | DS3231 functionality tested on Arduino Pro Mini (Jan 8, 2016 - MrAlvin) 41 | 42 | For other compatibility details see https://github.com/adafruit/RTClib 43 | 44 | ToDo: 45 | - debug Alarm2 46 | - make DS3231 SQW functon calls similar to DS1307 function calls 47 | 48 | -------------------------------------------------------------------------------- /examples/timestamp/timestamp.ino: -------------------------------------------------------------------------------- 1 | /* Timestamp functions using a DS1307 RTC connected via I2C and Wire lib 2 | ** 3 | ** Useful for file name 4 | ** ` SD.open(time.timestamp()+".log", FILE_WRITE) ` 5 | ** 6 | ** 7 | ** Created: 2015-06-01 by AxelTB 8 | ** Last Edit: 9 | */ 10 | 11 | #include 12 | #include "RTClib.h" 13 | 14 | RTC_DS1307 rtc; 15 | 16 | void setup() { 17 | Serial.begin(57600); 18 | #ifdef AVR 19 | Wire.begin(); 20 | #else 21 | Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due 22 | #endif 23 | rtc.begin(); 24 | 25 | if (! rtc.isrunning()) { 26 | Serial.println("RTC is NOT running!"); 27 | // following line sets the RTC to the date & time this sketch was compiled 28 | rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 29 | // This line sets the RTC with an explicit date & time, for example to set 30 | // January 21, 2014 at 3am you would call: 31 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); 32 | } 33 | 34 | } 35 | 36 | void loop() { 37 | DateTime time = rtc.now(); 38 | 39 | //Full Timestamp 40 | Serial.println(String("DateTime::TIMESTAMP_FULL:\t")+time.timestamp(DateTime::TIMESTAMP_FULL)); 41 | 42 | //Date Only 43 | Serial.println(String("DateTime::TIMESTAMP_DATE:\t")+time.timestamp(DateTime::TIMESTAMP_DATE)); 44 | 45 | //Full Timestamp 46 | Serial.println(String("DateTime::TIMESTAMP_TIME:\t")+time.timestamp(DateTime::TIMESTAMP_TIME)); 47 | 48 | Serial.println("\n"); 49 | 50 | //Delay 5s 51 | delay(5000); 52 | } 53 | -------------------------------------------------------------------------------- /examples/ds1307nvram/ds1307nvram.ino: -------------------------------------------------------------------------------- 1 | // Example of using the non-volatile RAM storage on the DS1307. 2 | // You can write up to 56 bytes from address 0 to 55. 3 | // Data will be persisted as long as the DS1307 has battery power. 4 | 5 | #include 6 | #include "RTClib.h" 7 | 8 | #if defined(ARDUINO_ARCH_SAMD) 9 | // for Zero, output on USB Serial console, remove line below if using programming port to program the Zero! 10 | #define Serial SerialUSB 11 | #endif 12 | 13 | RTC_DS1307 rtc; 14 | 15 | void printnvram(uint8_t address) { 16 | Serial.print("Address 0x"); 17 | Serial.print(address, HEX); 18 | Serial.print(" = 0x"); 19 | Serial.println(rtc.readnvram(address), HEX); 20 | } 21 | 22 | void setup () { 23 | 24 | #ifndef ESP8266 25 | while (!Serial); // for Leonardo/Micro/Zero 26 | #endif 27 | Serial.begin(57600); 28 | rtc.begin(); 29 | 30 | // Print old RAM contents on startup. 31 | Serial.println("Current NVRAM values:"); 32 | for (int i = 0; i < 6; ++i) { 33 | printnvram(i); 34 | } 35 | 36 | // Write some bytes to non-volatile RAM storage. 37 | // NOTE: You can only read and write from addresses 0 to 55 (i.e. 56 byte values). 38 | Serial.println("Writing NVRAM values."); 39 | // Example writing one byte at a time: 40 | rtc.writenvram(0, 0xFE); 41 | rtc.writenvram(1, 0xED); 42 | // Example writing multiple bytes: 43 | uint8_t writeData[4] = { 0xBE, 0xEF, 0x01, 0x02 }; 44 | rtc.writenvram(2, writeData, 4); 45 | 46 | // Read bytes from non-volatile RAM storage. 47 | Serial.println("Reading NVRAM values:"); 48 | // Example reading one byte at a time. 49 | Serial.println(rtc.readnvram(0), HEX); 50 | Serial.println(rtc.readnvram(1), HEX); 51 | // Example reading multiple bytes: 52 | uint8_t readData[4] = {0}; 53 | rtc.readnvram(readData, 4, 2); 54 | Serial.println(readData[0], HEX); 55 | Serial.println(readData[1], HEX); 56 | Serial.println(readData[2], HEX); 57 | Serial.println(readData[3], HEX); 58 | 59 | } 60 | 61 | void loop () { 62 | // Do nothing in the loop. 63 | } 64 | -------------------------------------------------------------------------------- /examples/softrtc/softrtc.ino: -------------------------------------------------------------------------------- 1 | // Date and time functions using just software, based on millis() & timer 2 | 3 | #include 4 | #include // this #include still required because the RTClib depends on it 5 | #include "RTClib.h" 6 | 7 | #if defined(ARDUINO_ARCH_SAMD) 8 | // for Zero, output on USB Serial console, remove line below if using programming port to program the Zero! 9 | #define Serial SerialUSB 10 | #endif 11 | 12 | RTC_Millis rtc; 13 | 14 | void setup () { 15 | Serial.begin(57600); 16 | // following line sets the RTC to the date & time this sketch was compiled 17 | rtc.begin(); 18 | // This line sets the RTC with an explicit date & time, for example to set 19 | // January 21, 2014 at 3am you would call: 20 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); 21 | } 22 | 23 | void loop () { 24 | DateTime now = rtc.now(); 25 | 26 | Serial.print(now.year(), DEC); 27 | Serial.print('/'); 28 | Serial.print(now.month(), DEC); 29 | Serial.print('/'); 30 | Serial.print(now.day(), DEC); 31 | Serial.print(' '); 32 | Serial.print(now.hour(), DEC); 33 | Serial.print(':'); 34 | Serial.print(now.minute(), DEC); 35 | Serial.print(':'); 36 | Serial.print(now.second(), DEC); 37 | Serial.println(); 38 | 39 | Serial.print(" seconds since 1970: "); 40 | Serial.println(now.unixtime()); 41 | 42 | // calculate a date which is 7 days and 30 seconds into the future 43 | DateTime future (now.unixtime() + 7 * 86400L + 30); 44 | 45 | Serial.print(" now + 7d + 30s: "); 46 | Serial.print(future.year(), DEC); 47 | Serial.print('/'); 48 | Serial.print(future.month(), DEC); 49 | Serial.print('/'); 50 | Serial.print(future.day(), DEC); 51 | Serial.print(' '); 52 | Serial.print(future.hour(), DEC); 53 | Serial.print(':'); 54 | Serial.print(future.minute(), DEC); 55 | Serial.print(':'); 56 | Serial.print(future.second(), DEC); 57 | Serial.println(); 58 | 59 | Serial.println(); 60 | delay(3000); 61 | } 62 | -------------------------------------------------------------------------------- /examples/ds1307SqwPin/ds1307SqwPin.ino: -------------------------------------------------------------------------------- 1 | // SQW/OUT pin mode using a DS1307 RTC connected via I2C. 2 | // 3 | // According to the data sheet (http://datasheets.maxim-ic.com/en/ds/DS1307.pdf), the 4 | // DS1307's SQW/OUT pin can be set to low, high, 1Hz, 4.096kHz, 8.192kHz, or 32.768kHz. 5 | // 6 | // This sketch reads the state of the pin, then iterates through the possible values at 7 | // 5 second intervals. 8 | // 9 | 10 | // NOTE: 11 | // You must connect a pull up resistor (~10kohm) from the SQW pin up to VCC. Without 12 | // this pull up the wave output will not work! 13 | 14 | #include 15 | #include "RTClib.h" 16 | 17 | #if defined(ARDUINO_ARCH_SAMD) 18 | // for Zero, output on USB Serial console, remove line below if using programming port to program the Zero! 19 | #define Serial SerialUSB 20 | #endif 21 | 22 | RTC_DS1307 rtc; 23 | 24 | int mode_index = 0; 25 | 26 | Ds1307SqwPinMode modes[] = {OFF, ON, SquareWave1HZ, SquareWave4kHz, SquareWave8kHz, SquareWave32kHz}; 27 | 28 | 29 | void print_mode() { 30 | Ds1307SqwPinMode mode = rtc.readSqwPinMode(); 31 | 32 | Serial.print("Sqw Pin Mode: "); 33 | switch(mode) { 34 | case OFF: Serial.println("OFF"); break; 35 | case ON: Serial.println("ON"); break; 36 | case SquareWave1HZ: Serial.println("1Hz"); break; 37 | case SquareWave4kHz: Serial.println("4.096kHz"); break; 38 | case SquareWave8kHz: Serial.println("8.192kHz"); break; 39 | case SquareWave32kHz: Serial.println("32.768kHz"); break; 40 | default: Serial.println("UNKNOWN"); break; 41 | } 42 | } 43 | 44 | void setup () { 45 | 46 | #ifndef ESP8266 47 | while (!Serial); // for Leonardo/Micro/Zero 48 | #endif 49 | 50 | Serial.begin(57600); 51 | if (! rtc.begin()) { 52 | Serial.println("Couldn't find RTC"); 53 | while (1); 54 | } 55 | 56 | print_mode(); 57 | } 58 | 59 | void loop () { 60 | rtc.writeSqwPinMode(modes[mode_index++]); 61 | print_mode(); 62 | 63 | if (mode_index > 5) { 64 | mode_index = 0; 65 | } 66 | 67 | delay(5000); 68 | } 69 | -------------------------------------------------------------------------------- /examples/ds3231alarm/ds3231alarm.ino: -------------------------------------------------------------------------------- 1 | // Date, Time and Alarm functions using a DS3231 RTC connected via I2C and Wire lib 2 | // The RTC can wake up the Arduino, if the Arduino has been put to sleep (to save power). 3 | // This can be a handy function for battery operated units. 4 | // 5 | // Hardware: connect RTC SQW/INT pin to Arduino pin2 6 | // during an alarm the RTC SQW/INT pin is pulled low 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | RTC_DS3231 rtc; 14 | int INTERRUPT_PIN = 2; 15 | volatile int state = LOW; 16 | 17 | void setup () { 18 | pinMode(INTERRUPT_PIN, INPUT_PULLUP); //internal pullup on the Arduino ensures that we can detect the LOW from the SQW/INT pin of the RTC 19 | 20 | Serial.begin(57600); 21 | rtc.begin(); 22 | // rtc.adjust(DateTime(__DATE__, __TIME__)); //it is expected that the RTC is already set and running 23 | } 24 | 25 | void loop () { 26 | DateTime tt = rtc.now(); 27 | rtc.setAlarm1Simple(tt.hour(), tt.minute() + 1); 28 | rtc.turnOnAlarm(1); 29 | if (rtc.checkAlarmEnabled(1)) { 30 | Serial.println("Alarm Enabled in 1 minutes"); 31 | } 32 | Serial.print(tt.hour(), DEC); 33 | Serial.print(':'); 34 | Serial.print(tt.minute(), DEC); 35 | Serial.print(':'); 36 | Serial.println(tt.second(), DEC); 37 | if (rtc.checkAlarmEnabled(1) ) Serial.println("A1 Enabled"); else Serial.println("A1 Disbled"); 38 | Serial.println("Going to Sleep"); 39 | Serial.flush(); // empty the send buffer, before continue with; going to sleep 40 | sleepNow(); 41 | Serial.println(); 42 | Serial.println("AWAKE"); 43 | if( rtc.checkIfAlarm(1) ) Serial.println("Alarm1 Triggered"); 44 | } 45 | 46 | void sleepNow() { 47 | set_sleep_mode(SLEEP_MODE_PWR_DOWN); 48 | sleep_enable(); 49 | attachInterrupt(0,logData, LOW); //make sure we can be made to wake up :-) 50 | sleep_mode(); 51 | //CONTINUE HERE AFTER WAKING UP 52 | sleep_disable(); 53 | detachInterrupt(0); //avoid random interrupts 54 | 55 | } 56 | 57 | void logData() { 58 | //do something quick, flip a flag, and handle in loop() - or do nothing at all, here 59 | } 60 | -------------------------------------------------------------------------------- /examples/ds1307/ds1307.ino: -------------------------------------------------------------------------------- 1 | // Date and time functions using a DS1307 RTC connected via I2C and Wire lib 2 | #include 3 | #include "RTClib.h" 4 | 5 | #if defined(ARDUINO_ARCH_SAMD) 6 | // for Zero, output on USB Serial console, remove line below if using programming port to program the Zero! 7 | #define Serial SerialUSB 8 | #endif 9 | 10 | RTC_DS1307 rtc; 11 | 12 | char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; 13 | 14 | void setup () { 15 | 16 | #ifndef ESP8266 17 | while (!Serial); // for Leonardo/Micro/Zero 18 | #endif 19 | 20 | Serial.begin(57600); 21 | if (! rtc.begin()) { 22 | Serial.println("Couldn't find RTC"); 23 | while (1); 24 | } 25 | 26 | if (! rtc.isrunning()) { 27 | Serial.println("RTC is NOT running!"); 28 | // following line sets the RTC to the date & time this sketch was compiled 29 | rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 30 | // This line sets the RTC with an explicit date & time, for example to set 31 | // January 21, 2014 at 3am you would call: 32 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); 33 | } 34 | } 35 | 36 | void loop () { 37 | DateTime now = rtc.now(); 38 | 39 | Serial.print(now.year(), DEC); 40 | Serial.print('/'); 41 | Serial.print(now.month(), DEC); 42 | Serial.print('/'); 43 | Serial.print(now.day(), DEC); 44 | Serial.print(" ("); 45 | Serial.print(daysOfTheWeek[now.dayOfTheWeek()]); 46 | Serial.print(") "); 47 | Serial.print(now.hour(), DEC); 48 | Serial.print(':'); 49 | Serial.print(now.minute(), DEC); 50 | Serial.print(':'); 51 | Serial.print(now.second(), DEC); 52 | Serial.println(); 53 | 54 | Serial.print(" since midnight 1/1/1970 = "); 55 | Serial.print(now.unixtime()); 56 | Serial.print("s = "); 57 | Serial.print(now.unixtime() / 86400L); 58 | Serial.println("d"); 59 | 60 | // calculate a date which is 7 days and 30 seconds into the future 61 | DateTime future (now + TimeSpan(7,12,30,6)); 62 | 63 | Serial.print(" now + 7d + 30s: "); 64 | Serial.print(future.year(), DEC); 65 | Serial.print('/'); 66 | Serial.print(future.month(), DEC); 67 | Serial.print('/'); 68 | Serial.print(future.day(), DEC); 69 | Serial.print(' '); 70 | Serial.print(future.hour(), DEC); 71 | Serial.print(':'); 72 | Serial.print(future.minute(), DEC); 73 | Serial.print(':'); 74 | Serial.print(future.second(), DEC); 75 | Serial.println(); 76 | 77 | Serial.println(); 78 | delay(3000); 79 | } -------------------------------------------------------------------------------- /examples/datecalc/datecalc.ino: -------------------------------------------------------------------------------- 1 | // Simple date conversions and calculations 2 | 3 | #include 4 | #include "RTClib.h" 5 | 6 | #if defined(ARDUINO_ARCH_SAMD) 7 | // for Zero, output on USB Serial console, remove line below if using programming port to program the Zero! 8 | #define Serial SerialUSB 9 | #endif 10 | 11 | void showDate(const char* txt, const DateTime& dt) { 12 | Serial.print(txt); 13 | Serial.print(' '); 14 | Serial.print(dt.year(), DEC); 15 | Serial.print('/'); 16 | Serial.print(dt.month(), DEC); 17 | Serial.print('/'); 18 | Serial.print(dt.day(), DEC); 19 | Serial.print(' '); 20 | Serial.print(dt.hour(), DEC); 21 | Serial.print(':'); 22 | Serial.print(dt.minute(), DEC); 23 | Serial.print(':'); 24 | Serial.print(dt.second(), DEC); 25 | 26 | Serial.print(" = "); 27 | Serial.print(dt.unixtime()); 28 | Serial.print("s / "); 29 | Serial.print(dt.unixtime() / 86400L); 30 | Serial.print("d since 1970"); 31 | 32 | Serial.println(); 33 | } 34 | 35 | void showTimeSpan(const char* txt, const TimeSpan& ts) { 36 | Serial.print(txt); 37 | Serial.print(" "); 38 | Serial.print(ts.days(), DEC); 39 | Serial.print(" days "); 40 | Serial.print(ts.hours(), DEC); 41 | Serial.print(" hours "); 42 | Serial.print(ts.minutes(), DEC); 43 | Serial.print(" minutes "); 44 | Serial.print(ts.seconds(), DEC); 45 | Serial.print(" seconds ("); 46 | Serial.print(ts.totalseconds(), DEC); 47 | Serial.print(" total seconds)"); 48 | Serial.println(); 49 | } 50 | 51 | void setup () { 52 | 53 | #ifndef ESP8266 54 | while (!Serial); // for Leonardo/Micro/Zero 55 | #endif 56 | Serial.begin(57600); 57 | 58 | DateTime dt0 (0, 1, 1, 0, 0, 0); 59 | showDate("dt0", dt0); 60 | 61 | DateTime dt1 (1, 1, 1, 0, 0, 0); 62 | showDate("dt1", dt1); 63 | 64 | DateTime dt2 (2009, 1, 1, 0, 0, 0); 65 | showDate("dt2", dt2); 66 | 67 | DateTime dt3 (2009, 1, 2, 0, 0, 0); 68 | showDate("dt3", dt3); 69 | 70 | DateTime dt4 (2009, 1, 27, 0, 0, 0); 71 | showDate("dt4", dt4); 72 | 73 | DateTime dt5 (2009, 2, 27, 0, 0, 0); 74 | showDate("dt5", dt5); 75 | 76 | DateTime dt6 (2009, 12, 27, 0, 0, 0); 77 | showDate("dt6", dt6); 78 | 79 | DateTime dt7 (dt6.unixtime() + 3600); // One hour later. 80 | showDate("dt7", dt7); 81 | 82 | DateTime dt75 = dt6 + TimeSpan(0, 1, 0, 0); // One hour later with TimeSpan addition. 83 | showDate("dt7.5", dt75); 84 | 85 | DateTime dt8 (dt6.unixtime() + 86400L); // One day later. 86 | showDate("dt8", dt8); 87 | 88 | DateTime dt85 = dt6 + TimeSpan(1, 0, 0, 0); // One day later with TimeSpan addition. 89 | showDate("dt8.5", dt85); 90 | 91 | DateTime dt9 (dt6.unixtime() + 7 * 86400L); // One week later. 92 | showDate("dt9", dt9); 93 | 94 | DateTime dt95 = dt6 + TimeSpan(7, 0, 0, 0); // One week later with TimeSpan addition. 95 | showDate("dt9.5", dt95); 96 | 97 | DateTime dt10 = dt6 + TimeSpan(0, 0, 42, 42); // Fourty two minutes and fourty two seconds later. 98 | showDate("dt10", dt10); 99 | 100 | DateTime dt11 = dt6 - TimeSpan(7, 0, 0, 0); // One week ago. 101 | showDate("dt11", dt11); 102 | 103 | TimeSpan ts1 = dt6 - dt5; 104 | showTimeSpan("dt6-dt5", ts1); 105 | 106 | TimeSpan ts2 = dt10 - dt6; 107 | showTimeSpan("dt10-dt6", ts2); 108 | } 109 | 110 | void loop () { 111 | } 112 | -------------------------------------------------------------------------------- /examples/ds3231/ds3231.ino: -------------------------------------------------------------------------------- 1 | // Date, Time, Alarm and Temperature functions using a DS3231 RTC connected via I2C and Wire lib 2 | 3 | #include 4 | #include 5 | 6 | RTC_DS3231 rtc; 7 | 8 | #if defined(ARDUINO_ARCH_SAMD) 9 | // for Zero, output on USB Serial console, remove line below if using programming port to program the Zero! 10 | #define Serial SerialUSB 11 | #endif 12 | 13 | char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; 14 | 15 | const char* months[] = {"January", "February", "March", "April", "May", "June", "July", "August","September", "October", "November", "December"}; 16 | 17 | 18 | DateTime tt; //variable of type DateTime 19 | 20 | 21 | void setup () { 22 | 23 | #ifndef ESP8266 24 | while (!Serial); // for Leonardo/Micro/Zero 25 | #endif 26 | 27 | Serial.begin(57600); 28 | 29 | 30 | if (! rtc.begin()) { 31 | Serial.println("Couldn't find RTC"); 32 | while (1); // sketch halts in an endless loop 33 | } 34 | 35 | 36 | if (! rtc.isrunning()) { 37 | Serial.println("RTC is NOT running!"); 38 | 39 | //set the RTC date & time - to the time this sketch was compiled 40 | rtc.adjust(DateTime(__DATE__, __TIME__)); 41 | 42 | // set the RTC date & time - to any time you choose example 43 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); // would set to January 21, 2014 at 3:00:00 (3am) 44 | // rtc.adjust(DateTime(2015, 2, 28, 14, 50, 00)); // would set to February 28, 2015 at 14:50:00 (2:50pm) 45 | } 46 | 47 | //get time 48 | tt = rtc.now(); 49 | 50 | //get temperature 51 | float c = rtc.getTemperature(); 52 | 53 | //print temperature 54 | Serial.print("temperature: "); 55 | Serial.print(c); 56 | Serial.println("* C"); 57 | 58 | //set alarm 1 59 | rtc.setAlarm1Simple(tt.hour(), tt.minute() + 1 ); 60 | rtc.turnOnAlarm(1); 61 | if (rtc.checkAlarmEnabled(1)) { 62 | Serial.print("Alarm 1 set to "); 63 | Serial.print(tt.hour()); 64 | Serial.print(":"); 65 | Serial.println(tt.minute() + 1); 66 | } 67 | 68 | }//setup() 69 | 70 | 71 | void loop () { 72 | 73 | 74 | //get time 75 | tt = rtc.now(); // read the time from the DS3231 RTC chip 76 | 77 | Serial.print(tt.year(), DEC); 78 | Serial.print('/'); 79 | Serial.print(tt.month(), DEC); 80 | Serial.print('/'); 81 | Serial.print(tt.day(), DEC); 82 | Serial.print(" ("); 83 | Serial.print(daysOfTheWeek[tt.dayOfTheWeek()]); 84 | Serial.print(") "); 85 | Serial.print(tt.hour(), DEC); 86 | Serial.print(':'); 87 | Serial.print(tt.minute(), DEC); 88 | Serial.print(':'); 89 | Serial.print(tt.second(), DEC); 90 | Serial.println(); 91 | 92 | Serial.print(" since midnight 1/1/1970 = "); 93 | Serial.print(tt.unixtime()); 94 | Serial.print("s = "); 95 | Serial.print(tt.unixtime() / 86400L); 96 | Serial.println("d"); 97 | 98 | // calculate a date which is 7 days and 30 seconds into the future 99 | DateTime future (tt + TimeSpan(7,12,30,6)); 100 | 101 | Serial.print(" now + 7d + 30s: "); 102 | Serial.print(future.year(), DEC); 103 | Serial.print('/'); 104 | Serial.print(future.month(), DEC); 105 | Serial.print('/'); 106 | Serial.print(future.day(), DEC); 107 | Serial.print(' '); 108 | Serial.print(future.hour(), DEC); 109 | Serial.print(':'); 110 | Serial.print(future.minute(), DEC); 111 | Serial.print(':'); 112 | Serial.print(future.second(), DEC); 113 | Serial.println(); 114 | 115 | Serial.println(); 116 | 117 | 118 | // check (in software) to see if Alarm 1 has been triggered 119 | if (rtc.checkIfAlarm(1)) { 120 | Serial.println("Alarm 1 Triggered"); 121 | } 122 | 123 | delay(3000); 124 | }//loop() 125 | -------------------------------------------------------------------------------- /examples/ds3231_v2/ds3231_v2.ino: -------------------------------------------------------------------------------- 1 | // Date, Time, Alarm and Temperature functions using a DS3231 RTC connected via I2C and Wire lib 2 | 3 | #include 4 | #include 5 | 6 | RTC_DS3231 rtc; 7 | 8 | #if defined(ARDUINO_ARCH_SAMD) 9 | // for Zero, output on USB Serial console, remove line below if using programming port to program the Zero! 10 | #define Serial SerialUSB 11 | #endif 12 | 13 | // The following string constants are saved in flash only 14 | // If an array of characters are defined as 'const' and with a set size of the double array, then it is possible to 15 | // use PROGMEM and save much RAM space. Size of array is: [number of strings][longest string + 2] 16 | const char daysOfTheWeek[7][10] PROGMEM = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; 17 | const char months[12][11] PROGMEM = {"January", "February", "March", "April", "May", "June", "July", "August","September", "October", "November", "December"}; 18 | 19 | DateTime tc; //variable of type DateTime 20 | 21 | char buffer[3]; //char buffer used for simple formatting of output, so minutes and seconds are always shown with two digits 22 | 23 | 24 | void setup () { 25 | 26 | #ifndef ESP8266 27 | while (!Serial); // for Leonardo/Micro/Zero 28 | #endif 29 | 30 | Serial.begin(57600); 31 | 32 | if (! rtc.begin()) { 33 | Serial.println( F("Couldn't find RTC") ); // using F() saves RAM - if text is longer than 4 characters 34 | while (1); // sketch halts in an endless loop 35 | } 36 | 37 | 38 | if (! rtc.isrunning()) { 39 | Serial.println( F("RTC is NOT running!") ); 40 | 41 | //set the RTC date & time - to the time this sketch was compiled 42 | rtc.adjust(DateTime(__DATE__, __TIME__)); 43 | 44 | // set the RTC date & time - to any time you choose examples 45 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); // would set to January 21, 2014 at 3:00:00 (3am) 46 | // rtc.adjust(DateTime(2015, 2, 28, 14, 50, 00)); // would set to February 28, 2015 at 14:50:00 (2:50pm) 47 | 48 | if (! rtc.isrunning()) { 49 | Serial.println( F("Halted") ); 50 | while(1); 51 | } 52 | } 53 | 54 | //get time 55 | tc = rtc.now(); 56 | 57 | //get temperature 58 | float c = rtc.getTemperature(); 59 | 60 | //print temperature 61 | Serial.print( F("(chip) temperature is ") ); 62 | Serial.print(c); 63 | Serial.print( F("* Celcius and ")); 64 | Serial.print( ( c * (9/5) ) + 32); 65 | Serial.println( F("* Fahrenheit") ); 66 | 67 | //set alarm 1 68 | rtc.setAlarm1Simple(tc.hour(), tc.minute() + 1 ); 69 | rtc.turnOnAlarm(1); 70 | if (rtc.checkAlarmEnabled(1)) { 71 | Serial.print( F(" Alarm 1 set to ") ); 72 | Serial.print(tc.hour()); 73 | Serial.print(":"); 74 | sprintf(buffer, "%02d", tc.minute() + 1); 75 | Serial.println(buffer); 76 | } 77 | 78 | Serial.println( F("Press [return] at any time, to begin setting RTC Time via serial input") ); 79 | Serial.println(); 80 | 81 | }//setup() 82 | 83 | 84 | void loop () { 85 | 86 | 87 | //get time 88 | tc = rtc.now(); // read the time from the DS3231 RTC chip 89 | 90 | printTime24H(); 91 | printTime_AM_PM(); 92 | 93 | // check (in software) to see if Alarm 1 has been triggered 94 | if (rtc.checkIfAlarm(1)) { 95 | Serial.println( F("Alarm 1 Triggered") ); 96 | } 97 | 98 | Serial.println(); 99 | pause(3000); 100 | }//loop() 101 | 102 | 103 | void pause(int delay_ms) { 104 | while(delay_ms){ //short for: while(delay_ms <> 0) 105 | if( Serial.available() ) { 106 | oldSerialFlush(); // flush serial recieve buffer (so NL and/or CR is removed before looking for entered numbers) 107 | setTimeSerial(); 108 | delay_ms = 1; //ready to go back to running the main loop 109 | } 110 | delay(1); 111 | delay_ms--; //short for: delay_ms = delay_ms - 1 112 | } 113 | }//pause() 114 | 115 | 116 | void printTime24H() { 117 | Serial.print(tc.year(), DEC); 118 | Serial.print('/'); 119 | Serial.print(tc.month(), DEC); 120 | Serial.print('/'); 121 | sprintf(buffer, "%02d", tc.day()); 122 | Serial.print(buffer); 123 | Serial.print(' '); 124 | Serial.print(tc.hour(), DEC); 125 | Serial.print(':'); 126 | sprintf(buffer, "%02d", tc.minute()); 127 | Serial.print(buffer); 128 | Serial.print(':'); 129 | sprintf(buffer, "%02d", tc.second()); 130 | Serial.print(buffer); 131 | Serial.println(); 132 | }//printTime24H() 133 | 134 | 135 | void printTime_AM_PM() { 136 | const char* AMPM = 0; 137 | Serial.print( daysOfTheWeek[tc.dayOfTheWeek()] ); 138 | Serial.print(" "); 139 | Serial.print(months[tc.month()-1]); 140 | Serial.print(" "); 141 | Serial.print(tc.day()); 142 | Serial.print(", "); 143 | Serial.print(tc.year()); 144 | Serial.print(" "); 145 | byte hour = tc.hour(); 146 | if (hour > 12) { 147 | hour -= 12; 148 | AMPM = " PM"; 149 | }else{ 150 | AMPM = " AM"; 151 | } 152 | Serial.print(hour); 153 | Serial.print(":"); 154 | sprintf(buffer, "%02d", tc.minute() ); 155 | Serial.print(buffer); 156 | Serial.println(AMPM); 157 | }//printTime_AM_PM() 158 | 159 | 160 | void setTimeSerial(){ 161 | Serial.print( F("Please enter the current year, 00-99. - ") ); 162 | byte year = readByte(); 163 | Serial.println(year); 164 | Serial.println(); 165 | 166 | Serial.print( F("Please enter the current month, 1-12. - ") ); 167 | byte month = readByte(); 168 | Serial.println(months[month-1]); 169 | Serial.println(); 170 | 171 | Serial.print( F("Please enter the current day of the month, 1-31. - ") ); 172 | byte day = readByte(); 173 | Serial.println(day); 174 | Serial.println(); 175 | 176 | Serial.print( F("Please enter the current hour in 24hr format, 0-23. - ") ); 177 | byte hour = readByte(); 178 | Serial.println(hour); 179 | Serial.println(); 180 | 181 | Serial.print( F("Please enter the current minute, 0-59. - ") ); 182 | byte minute = readByte(); 183 | Serial.println(minute); 184 | 185 | Serial.println(); 186 | Serial.println( F("Please enter your select second, 0-59. - ") ); 187 | Serial.println( F("Press [return/enter] button at the correct second") ); 188 | byte second = readByte(); 189 | Serial.println(second); 190 | 191 | rtc.adjust(DateTime(year, month, day, hour, minute, second)); 192 | Serial.println( F("The RTC has been set.") ); 193 | }//setTimeSerial() 194 | 195 | 196 | byte readByte() { 197 | while (!Serial.available()) delay(10); 198 | byte reading = 0; 199 | byte incomingByte = Serial.read(); 200 | while (incomingByte != '\n') { // '\n' means 'newline' 201 | if (incomingByte >= '0' && incomingByte <= '9') 202 | reading = reading * 10 + (incomingByte - '0'); 203 | else; 204 | incomingByte = Serial.read(); 205 | } 206 | oldSerialFlush(); //empties incomming serial buffer 207 | return reading; 208 | }//readByte() 209 | 210 | 211 | void oldSerialFlush(){ 212 | while ( Serial.available() ) { 213 | byte incomingByte = Serial.read(); 214 | } 215 | }//oldSerialFlush() 216 | 217 | -------------------------------------------------------------------------------- /RTClib.h: -------------------------------------------------------------------------------- 1 | // Code by JeeLabs http://news.jeelabs.org/code/ 2 | // Released to the public domain! Enjoy! 3 | 4 | // Merged DS3231 functions from: github/coobro/RTClib by MrAlvin 2012-02-27 5 | // Alarm code for DS3231 heavily used/modified from Eric Ayars DS3231 library by Coobro 6 | // Eric Ayars code is located at: http://hacks.ayars.org/2011/04/ds3231-real-time-clock.html 7 | 8 | #ifndef _RTCLIB_H_ 9 | #define _RTCLIB_H_ 10 | 11 | #include 12 | class TimeSpan; 13 | 14 | // Simple general-purpose date/time class (no TZ / DST / leap second handling!) 15 | class DateTime { 16 | public: 17 | DateTime (uint32_t t =0); 18 | DateTime (uint16_t year, uint8_t month, uint8_t day, 19 | uint8_t hour =0, uint8_t min =0, uint8_t sec =0); 20 | DateTime (const DateTime& copy); 21 | DateTime (const char* date, const char* time); 22 | DateTime (const __FlashStringHelper* date, const __FlashStringHelper* time); 23 | uint16_t year() const { return 2000 + yOff; } 24 | uint8_t month() const { return m; } 25 | uint8_t day() const { return d; } 26 | uint8_t hour() const { return hh; } 27 | uint8_t minute() const { return mm; } 28 | uint8_t second() const { return ss; } 29 | uint8_t dayOfTheWeek() const; 30 | 31 | // 32-bit times as seconds since 1/1/2000 32 | long secondstime() const; 33 | // 32-bit times as seconds since 1/1/1970 34 | uint32_t unixtime(void) const; 35 | 36 | //ISO 8601 Timestamp function 37 | enum timestampOpt{ 38 | TIMESTAMP_FULL, TIMESTAMP_TIME, TIMESTAMP_DATE 39 | }; 40 | String timestamp(timestampOpt opt = TIMESTAMP_FULL); 41 | 42 | DateTime operator+(const TimeSpan& span); 43 | DateTime operator-(const TimeSpan& span); 44 | TimeSpan operator-(const DateTime& right); 45 | 46 | protected: 47 | uint8_t yOff, m, d, hh, mm, ss; 48 | }; 49 | 50 | // Timespan which can represent changes in time with seconds accuracy. 51 | class TimeSpan { 52 | public: 53 | TimeSpan (int32_t seconds = 0); 54 | TimeSpan (int16_t days, int8_t hours, int8_t minutes, int8_t seconds); 55 | TimeSpan (const TimeSpan& copy); 56 | int16_t days() const { return _seconds / 86400L; } 57 | int8_t hours() const { return _seconds / 3600 % 24; } 58 | int8_t minutes() const { return _seconds / 60 % 60; } 59 | int8_t seconds() const { return _seconds % 60; } 60 | int32_t totalseconds() const { return _seconds; } 61 | 62 | TimeSpan operator+(const TimeSpan& right); 63 | TimeSpan operator-(const TimeSpan& right); 64 | 65 | protected: 66 | int32_t _seconds; 67 | }; 68 | 69 | // RTC based on the DS1307 chip connected via I2C and the Wire library 70 | enum Ds1307SqwPinMode { OFF = 0x00, ON = 0x80, SquareWave1HZ = 0x10, SquareWave4kHz = 0x11, SquareWave8kHz = 0x12, SquareWave32kHz = 0x13 }; 71 | 72 | class RTC_DS1307 { 73 | public: 74 | boolean begin(void); 75 | static void adjust(const DateTime& dt); 76 | uint8_t isrunning(void); 77 | static DateTime now(); 78 | static Ds1307SqwPinMode readSqwPinMode(); 79 | static void writeSqwPinMode(Ds1307SqwPinMode mode); 80 | uint8_t readnvram(uint8_t address); 81 | void readnvram(uint8_t* buf, uint8_t size, uint8_t address); 82 | void writenvram(uint8_t address, uint8_t data); 83 | void writenvram(uint8_t address, uint8_t* buf, uint8_t size); 84 | }; 85 | 86 | // RTC based on the PCF8523 chip connected via I2C and the Wire library 87 | enum Pcf8523SqwPinMode { PCF8523_OFF = 7, PCF8523_SquareWave1HZ = 6, PCF8523_SquareWave32HZ = 5, PCF8523_SquareWave1kHZ = 4, PCF8523_SquareWave4kHz = 3, PCF8523_SquareWave8kHz = 2, PCF8523_SquareWave16kHz = 1, PCF8523_SquareWave32kHz = 0 }; 88 | 89 | class RTC_PCF8523 { 90 | public: 91 | boolean begin(void); 92 | void adjust(const DateTime& dt); 93 | boolean isrunning(void); 94 | static DateTime now(); 95 | 96 | Pcf8523SqwPinMode readSqwPinMode(); 97 | void writeSqwPinMode(Pcf8523SqwPinMode mode); 98 | }; 99 | 100 | // RTC using the internal millis() clock, has to be initialized before use 101 | class RTC_Millis { 102 | public: 103 | void checkRollover(); 104 | 105 | boolean begin(void); 106 | void adjust(const DateTime& dt); 107 | uint8_t isrunning(void) {return 1;}; 108 | DateTime now(); 109 | Ds1307SqwPinMode readSqwPinMode(); 110 | void writeSqwPinMode(Ds1307SqwPinMode mode) {}; 111 | uint8_t readnvram(uint8_t address) {}; 112 | void readnvram(uint8_t* buf, uint8_t size, uint8_t address) {}; 113 | void writenvram(uint8_t address, uint8_t data) {}; 114 | void writenvram(uint8_t address, uint8_t* buf, uint8_t size) {}; 115 | 116 | protected: 117 | long offset; 118 | // Support for millis rollover: 119 | // 1. Periodically compare current millis() with previosly captured millis 120 | // 2. When previus millis is greater than current, a rollover count is increased 121 | // 3. In calculating now(), use additional count of 2^32/1000 to compensate for rollovers 122 | unsigned long prevMillis; 123 | unsigned int countRollovers; 124 | }; 125 | 126 | // RTC based on the DS3231 chip connected via I2C 127 | class RTC_DS3231 128 | { 129 | public: 130 | uint8_t begin(void); 131 | void adjust(const DateTime& dt); 132 | uint8_t isrunning(void); 133 | DateTime now(); 134 | 135 | // Temperature function 136 | 137 | float getTemperature(); 138 | 139 | void getA1Time(byte& A1Day, byte& A1Hour, byte& A1Minute, byte& A1Second, byte& AlarmBits, bool& A1Dy, bool& A1h12, bool& A1PM); 140 | /* Retrieves everything you could want to know about alarm 141 | * one. 142 | * A1Dy true makes the alarm go on A1Day = Day of Week, 143 | * A1Dy false makes the alarm go on A1Day = Date of month. 144 | * 145 | * byte AlarmBits sets the behavior of the alarms: 146 | * Dy A1M4 A1M3 A1M2 A1M1 Rate 147 | * X 1 1 1 1 Once per second 148 | * X 1 1 1 0 Alarm when seconds match 149 | * X 1 1 0 0 Alarm when min, sec match 150 | * X 1 0 0 0 Alarm when hour, min, sec match 151 | * 0 0 0 0 0 Alarm when date, h, m, s match 152 | * 1 0 0 0 0 Alarm when DoW, h, m, s match 153 | * 154 | * Dy A2M4 A2M3 A2M2 Rate 155 | * X 1 1 1 Once per minute (at seconds = 00) 156 | * X 1 1 0 Alarm when minutes match 157 | * X 1 0 0 Alarm when hours and minutes match 158 | * 0 0 0 0 Alarm when date, hour, min match 159 | * 1 0 0 0 Alarm when DoW, hour, min match 160 | */ 161 | void getA2Time(byte& A2Day, byte& A2Hour, byte& A2Minute, byte& AlarmBits, bool& A2Dy, bool& A2h12, bool& A2PM); 162 | // Same as getA1Time();, but A2 only goes on seconds == 00. 163 | void setA1Time(byte A1Day, byte A1Hour, byte A1Minute, byte A1Second, byte AlarmBits, bool A1Dy, bool A1h12, bool A1PM); 164 | // Set the details for Alarm 1 165 | void setAlarm1Simple(byte hour, byte minute); 166 | // A simple hour/minute alarm. 167 | void setA2Time(byte A2Day, byte A2Hour, byte A2Minute, byte AlarmBits, bool A2Dy, bool A2h12, bool A2PM); 168 | // Set the details for Alarm 2 169 | void setAlarm2Simple(byte hour, byte minute); 170 | // A simple hour/minute alarm. 171 | void turnOnAlarm(byte Alarm); 172 | // Enables alarm 1 or 2 and the external interrupt pin. 173 | // If Alarm != 1, it assumes Alarm == 2. 174 | void turnOffAlarm(byte Alarm); 175 | // Disables alarm 1 or 2 (default is 2 if Alarm != 1); 176 | // and leaves the interrupt pin alone. 177 | bool checkAlarmEnabled(byte Alarm); 178 | // Returns T/F to indicate whether the requested alarm is 179 | // enabled. Defaults to 2 if Alarm != 1. 180 | bool checkIfAlarm(byte Alarm); 181 | // Checks whether the indicated alarm (1 or 2, 2 default); 182 | // has been activated. 183 | 184 | // Oscillator functions 185 | 186 | void enableOscillator(bool TF, bool battery, byte frequency); 187 | // turns oscillator on or off. True is on, false is off. 188 | // if battery is true, turns on even for battery-only operation, 189 | // otherwise turns off if Vcc is off. 190 | // frequency must be 0, 1, 2, or 3. 191 | // 0 = 1 Hz 192 | // 1 = 1.024 kHz 193 | // 2 = 4.096 kHz 194 | // 3 = 8.192 kHz (Default if frequency byte is out of range); 195 | void enable32kHz(bool TF); 196 | // Turns the 32kHz output pin on (true); or off (false). 197 | bool oscillatorCheck();; 198 | // Checks the status of the OSF (Oscillator Stop Flag);. 199 | // If this returns false, then the clock is probably not 200 | // giving you the correct time. 201 | // The OSF is cleared by function setSecond();. 202 | 203 | private: 204 | byte readControlByte(bool which); 205 | // Read selected control byte: (0); reads 0x0e, (1) reads 0x0f 206 | void writeControlByte(byte control, bool which); 207 | // Write the selected control byte. 208 | // which == false -> 0x0e, true->0x0f. 209 | }; 210 | 211 | 212 | #endif // _RTCLIB_H_ 213 | -------------------------------------------------------------------------------- /RTClib.cpp: -------------------------------------------------------------------------------- 1 | // Code by JeeLabs http://news.jeelabs.org/code/ 2 | // Released to the public domain! Enjoy! 3 | 4 | #include 5 | #include "RTClib.h" 6 | 7 | #ifdef __AVR__ 8 | #include 9 | #elif defined(ESP8266) 10 | #include 11 | #elif defined(ARDUINO_ARCH_SAMD) 12 | // nothing special needed 13 | #elif defined(ARDUINO_SAM_DUE) 14 | #define PROGMEM 15 | #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) 16 | #define Wire Wire1 17 | #endif 18 | 19 | #define PCF8523_ADDRESS 0x68 20 | #define PCF8523_CLKOUTCONTROL 0x0F 21 | 22 | #define DS1307_ADDRESS 0x68 23 | #define DS1307_CONTROL 0x07 24 | #define DS1307_NVRAM 0x08 25 | 26 | #define DS3231_ADDRESS 0x68 27 | 28 | #define SECONDS_PER_DAY 86400L 29 | 30 | #define SECONDS_FROM_1970_TO_2000 946684800 31 | 32 | #if (ARDUINO >= 100) 33 | #include // capital A so it is error prone on case-sensitive filesystems 34 | // Macro to deal with the difference in I2C write functions from old and new Arduino versions. 35 | #define _I2C_WRITE write 36 | #define _I2C_READ read 37 | #else 38 | #include 39 | #define _I2C_WRITE send 40 | #define _I2C_READ receive 41 | #endif 42 | 43 | //////////////////////////////////////////////////////////////////////////////// 44 | // utility code, some of this could be exposed in the DateTime API if needed 45 | 46 | const uint8_t daysInMonth [] PROGMEM = { 31,28,31,30,31,30,31,31,30,31,30,31 }; 47 | 48 | // number of days since 2000/01/01, valid for 2001..2099 49 | static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d) { 50 | if (y >= 2000) 51 | y -= 2000; 52 | uint16_t days = d; 53 | for (uint8_t i = 1; i < m; ++i) 54 | days += pgm_read_byte(daysInMonth + i - 1); 55 | if (m > 2 && y % 4 == 0) 56 | ++days; 57 | return days + 365 * y + (y + 3) / 4 - 1; 58 | } 59 | 60 | static long time2long(uint16_t days, uint8_t h, uint8_t m, uint8_t s) { 61 | return ((days * 24L + h) * 60 + m) * 60 + s; 62 | } 63 | 64 | //////////////////////////////////////////////////////////////////////////////// 65 | // DateTime implementation - ignores time zones and DST changes 66 | // NOTE: also ignores leap seconds, see http://en.wikipedia.org/wiki/Leap_second 67 | 68 | DateTime::DateTime (uint32_t t) { 69 | t -= SECONDS_FROM_1970_TO_2000; // bring to 2000 timestamp from 1970 70 | 71 | ss = t % 60; 72 | t /= 60; 73 | mm = t % 60; 74 | t /= 60; 75 | hh = t % 24; 76 | uint16_t days = t / 24; 77 | uint8_t leap; 78 | for (yOff = 0; ; ++yOff) { 79 | leap = yOff % 4 == 0; 80 | if (days < 365 + leap) 81 | break; 82 | days -= 365 + leap; 83 | } 84 | for (m = 1; ; ++m) { 85 | uint8_t daysPerMonth = pgm_read_byte(daysInMonth + m - 1); 86 | if (leap && m == 2) 87 | ++daysPerMonth; 88 | if (days < daysPerMonth) 89 | break; 90 | days -= daysPerMonth; 91 | } 92 | d = days + 1; 93 | } 94 | 95 | DateTime::DateTime (uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec) { 96 | if (year >= 2000) 97 | year -= 2000; 98 | yOff = year; 99 | m = month; 100 | d = day; 101 | hh = hour; 102 | mm = min; 103 | ss = sec; 104 | } 105 | 106 | DateTime::DateTime (const DateTime& copy): 107 | yOff(copy.yOff), 108 | m(copy.m), 109 | d(copy.d), 110 | hh(copy.hh), 111 | mm(copy.mm), 112 | ss(copy.ss) 113 | {} 114 | 115 | static uint8_t conv2d(const char* p) { 116 | uint8_t v = 0; 117 | if ('0' <= *p && *p <= '9') 118 | v = *p - '0'; 119 | return 10 * v + *++p - '0'; 120 | } 121 | 122 | // A convenient constructor for using "the compiler's time": 123 | // DateTime now (__DATE__, __TIME__); 124 | // NOTE: using F() would further reduce the RAM footprint, see below. 125 | DateTime::DateTime (const char* date, const char* time) { 126 | // sample input: date = "Dec 26 2009", time = "12:34:56" 127 | yOff = conv2d(date + 9); 128 | // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec 129 | switch (date[0]) { 130 | case 'J': m = date[1] == 'a' ? 1 : m = date[2] == 'n' ? 6 : 7; break; 131 | case 'F': m = 2; break; 132 | case 'A': m = date[2] == 'r' ? 4 : 8; break; 133 | case 'M': m = date[2] == 'r' ? 3 : 5; break; 134 | case 'S': m = 9; break; 135 | case 'O': m = 10; break; 136 | case 'N': m = 11; break; 137 | case 'D': m = 12; break; 138 | } 139 | d = conv2d(date + 4); 140 | hh = conv2d(time); 141 | mm = conv2d(time + 3); 142 | ss = conv2d(time + 6); 143 | } 144 | 145 | // A convenient constructor for using "the compiler's time": 146 | // This version will save RAM by using PROGMEM to store it by using the F macro. 147 | // DateTime now (F(__DATE__), F(__TIME__)); 148 | DateTime::DateTime (const __FlashStringHelper* date, const __FlashStringHelper* time) { 149 | // sample input: date = "Dec 26 2009", time = "12:34:56" 150 | char buff[11]; 151 | memcpy_P(buff, date, 11); 152 | yOff = conv2d(buff + 9); 153 | // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec 154 | switch (buff[0]) { 155 | case 'J': m = buff[1] == 'a' ? 1 : m = buff[2] == 'n' ? 6 : 7; break; 156 | case 'F': m = 2; break; 157 | case 'A': m = buff[2] == 'r' ? 4 : 8; break; 158 | case 'M': m = buff[2] == 'r' ? 3 : 5; break; 159 | case 'S': m = 9; break; 160 | case 'O': m = 10; break; 161 | case 'N': m = 11; break; 162 | case 'D': m = 12; break; 163 | } 164 | d = conv2d(buff + 4); 165 | memcpy_P(buff, time, 8); 166 | hh = conv2d(buff); 167 | mm = conv2d(buff + 3); 168 | ss = conv2d(buff + 6); 169 | } 170 | 171 | uint8_t DateTime::dayOfTheWeek() const { 172 | uint16_t day = date2days(yOff, m, d); 173 | return (day + 6) % 7; // Jan 1, 2000 is a Saturday, i.e. returns 6 174 | } 175 | 176 | uint32_t DateTime::unixtime(void) const { 177 | uint32_t t; 178 | uint16_t days = date2days(yOff, m, d); 179 | t = time2long(days, hh, mm, ss); 180 | t += SECONDS_FROM_1970_TO_2000; // seconds from 1970 to 2000 181 | 182 | return t; 183 | } 184 | 185 | long DateTime::secondstime(void) const { 186 | long t; 187 | uint16_t days = date2days(yOff, m, d); 188 | t = time2long(days, hh, mm, ss); 189 | return t; 190 | } 191 | 192 | DateTime DateTime::operator+(const TimeSpan& span) { 193 | return DateTime(unixtime()+span.totalseconds()); 194 | } 195 | 196 | DateTime DateTime::operator-(const TimeSpan& span) { 197 | return DateTime(unixtime()-span.totalseconds()); 198 | } 199 | 200 | TimeSpan DateTime::operator-(const DateTime& right) { 201 | return TimeSpan(unixtime()-right.unixtime()); 202 | } 203 | 204 | //ISO 8601 Timestamp 205 | String DateTime::timestamp(timestampOpt opt){ 206 | char buffer[20]; 207 | 208 | //Generate timestamp according to opt 209 | switch(opt){ 210 | case TIMESTAMP_TIME: 211 | //Only time 212 | sprintf(buffer, "%02d:%02d:%02d", hh, mm, ss); 213 | break; 214 | case TIMESTAMP_DATE: 215 | //Only date 216 | sprintf(buffer, "%d-%02d-%02d", 2000+yOff, m, d); 217 | break; 218 | default: 219 | //Full 220 | sprintf(buffer, "%d-%02d-%02dT%02d:%02d:%02d", 2000+yOff, m, d, hh, mm, ss); 221 | } 222 | return String(buffer); 223 | } 224 | 225 | 226 | //////////////////////////////////////////////////////////////////////////////// 227 | // TimeSpan implementation 228 | 229 | TimeSpan::TimeSpan (int32_t seconds): 230 | _seconds(seconds) 231 | {} 232 | 233 | TimeSpan::TimeSpan (int16_t days, int8_t hours, int8_t minutes, int8_t seconds): 234 | _seconds((int32_t)days*86400L + (int32_t)hours*3600 + (int32_t)minutes*60 + seconds) 235 | {} 236 | 237 | TimeSpan::TimeSpan (const TimeSpan& copy): 238 | _seconds(copy._seconds) 239 | {} 240 | 241 | TimeSpan TimeSpan::operator+(const TimeSpan& right) { 242 | return TimeSpan(_seconds+right._seconds); 243 | } 244 | 245 | TimeSpan TimeSpan::operator-(const TimeSpan& right) { 246 | return TimeSpan(_seconds-right._seconds); 247 | } 248 | 249 | //////////////////////////////////////////////////////////////////////////////// 250 | // RTC_DS1307 implementation 251 | 252 | static uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); } 253 | static uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); } 254 | 255 | boolean RTC_DS1307::begin(void) { 256 | Wire.begin(); 257 | return true; 258 | } 259 | 260 | uint8_t RTC_DS1307::isrunning(void) { 261 | Wire.beginTransmission(DS1307_ADDRESS); 262 | Wire._I2C_WRITE((byte)0); 263 | Wire.endTransmission(); 264 | 265 | Wire.requestFrom(DS1307_ADDRESS, 1); 266 | uint8_t ss = Wire._I2C_READ(); 267 | return !(ss>>7); 268 | } 269 | 270 | void RTC_DS1307::adjust(const DateTime& dt) { 271 | Wire.beginTransmission(DS1307_ADDRESS); 272 | Wire._I2C_WRITE((byte)0); // start at location 0 273 | Wire._I2C_WRITE(bin2bcd(dt.second())); 274 | Wire._I2C_WRITE(bin2bcd(dt.minute())); 275 | Wire._I2C_WRITE(bin2bcd(dt.hour())); 276 | Wire._I2C_WRITE(bin2bcd(0)); 277 | Wire._I2C_WRITE(bin2bcd(dt.day())); 278 | Wire._I2C_WRITE(bin2bcd(dt.month())); 279 | Wire._I2C_WRITE(bin2bcd(dt.year() - 2000)); 280 | Wire.endTransmission(); 281 | } 282 | 283 | DateTime RTC_DS1307::now() { 284 | Wire.beginTransmission(DS1307_ADDRESS); 285 | Wire._I2C_WRITE((byte)0); 286 | Wire.endTransmission(); 287 | 288 | Wire.requestFrom(DS1307_ADDRESS, 7); 289 | uint8_t ss = bcd2bin(Wire._I2C_READ() & 0x7F); 290 | uint8_t mm = bcd2bin(Wire._I2C_READ()); 291 | uint8_t hh = bcd2bin(Wire._I2C_READ()); 292 | Wire._I2C_READ(); 293 | uint8_t d = bcd2bin(Wire._I2C_READ()); 294 | uint8_t m = bcd2bin(Wire._I2C_READ()); 295 | uint16_t y = bcd2bin(Wire._I2C_READ()) + 2000; 296 | 297 | return DateTime (y, m, d, hh, mm, ss); 298 | } 299 | 300 | Ds1307SqwPinMode RTC_DS1307::readSqwPinMode() { 301 | int mode; 302 | 303 | Wire.beginTransmission(DS1307_ADDRESS); 304 | Wire._I2C_WRITE(DS1307_CONTROL); 305 | Wire.endTransmission(); 306 | 307 | Wire.requestFrom((uint8_t)DS1307_ADDRESS, (uint8_t)1); 308 | mode = Wire._I2C_READ(); 309 | 310 | mode &= 0x93; 311 | return static_cast(mode); 312 | } 313 | 314 | void RTC_DS1307::writeSqwPinMode(Ds1307SqwPinMode mode) { 315 | Wire.beginTransmission(DS1307_ADDRESS); 316 | Wire._I2C_WRITE(DS1307_CONTROL); 317 | Wire._I2C_WRITE(mode); 318 | Wire.endTransmission(); 319 | } 320 | 321 | void RTC_DS1307::readnvram(uint8_t* buf, uint8_t size, uint8_t address) { 322 | int addrByte = DS1307_NVRAM + address; 323 | Wire.beginTransmission(DS1307_ADDRESS); 324 | Wire._I2C_WRITE(addrByte); 325 | Wire.endTransmission(); 326 | 327 | Wire.requestFrom((uint8_t) DS1307_ADDRESS, size); 328 | for (uint8_t pos = 0; pos < size; ++pos) { 329 | buf[pos] = Wire._I2C_READ(); 330 | } 331 | } 332 | 333 | void RTC_DS1307::writenvram(uint8_t address, uint8_t* buf, uint8_t size) { 334 | int addrByte = DS1307_NVRAM + address; 335 | Wire.beginTransmission(DS1307_ADDRESS); 336 | Wire._I2C_WRITE(addrByte); 337 | for (uint8_t pos = 0; pos < size; ++pos) { 338 | Wire._I2C_WRITE(buf[pos]); 339 | } 340 | Wire.endTransmission(); 341 | } 342 | 343 | uint8_t RTC_DS1307::readnvram(uint8_t address) { 344 | uint8_t data; 345 | readnvram(&data, 1, address); 346 | return data; 347 | } 348 | 349 | void RTC_DS1307::writenvram(uint8_t address, uint8_t data) { 350 | writenvram(address, &data, 1); 351 | } 352 | 353 | //////////////////////////////////////////////////////////////////////////////// 354 | // RTC_Millis implementation 355 | 356 | boolean RTC_Millis::begin(void) { 357 | offset = 0; 358 | adjust(DateTime(__DATE__,__TIME__)); 359 | return true; 360 | } 361 | 362 | void RTC_Millis::adjust(const DateTime& dt) { 363 | offset = dt.unixtime() - millis() / 1000; 364 | prevMillis = millis(); 365 | countRollovers = 0; 366 | } 367 | 368 | DateTime RTC_Millis::now() { 369 | checkRollover(); 370 | return (uint32_t)(offset + millis() / 1000 + (countRollovers * 4294967L) + (countRollovers*296/1000) ); 371 | } 372 | 373 | // checkRollover should be run periodically to ensure a rollover is captured. 374 | // Since rollovers happen once in ~43 days, "periodically" could be once a day, once a week, or even once a month! 375 | void RTC_Millis::checkRollover() { 376 | if (prevMillis > millis()) countRollovers++; 377 | prevMillis = millis(); 378 | } 379 | 380 | 381 | Ds1307SqwPinMode RTC_Millis::readSqwPinMode() { 382 | int mode; 383 | 384 | mode = 0x80 | 0x12; 385 | 386 | mode &= 0x93; 387 | return static_cast(mode); 388 | } 389 | //////////////////////////////////////////////////////////////////////////////// 390 | 391 | //////////////////////////////////////////////////////////////////////////////// 392 | // RTC_PCF8563 implementation 393 | 394 | boolean RTC_PCF8523::begin(void) { 395 | Wire.begin(); 396 | return true; 397 | } 398 | 399 | boolean RTC_PCF8523::isrunning(void) { 400 | Wire.beginTransmission(PCF8523_ADDRESS); 401 | Wire._I2C_WRITE((byte)0); 402 | Wire.endTransmission(); 403 | 404 | Wire.requestFrom(PCF8523_ADDRESS, 1); 405 | uint8_t ss = Wire._I2C_READ(); 406 | return !(ss & (1<<5)); 407 | } 408 | 409 | void RTC_PCF8523::adjust(const DateTime& dt) { 410 | Wire.beginTransmission(PCF8523_ADDRESS); 411 | Wire._I2C_WRITE((byte)3); // start at location 3 412 | Wire._I2C_WRITE(bin2bcd(dt.second())); 413 | Wire._I2C_WRITE(bin2bcd(dt.minute())); 414 | Wire._I2C_WRITE(bin2bcd(dt.hour())); 415 | Wire._I2C_WRITE(bin2bcd(0)); 416 | Wire._I2C_WRITE(bin2bcd(dt.day())); 417 | Wire._I2C_WRITE(bin2bcd(dt.month())); 418 | Wire._I2C_WRITE(bin2bcd(dt.year() - 2000)); 419 | Wire.endTransmission(); 420 | } 421 | 422 | DateTime RTC_PCF8523::now() { 423 | Wire.beginTransmission(PCF8523_ADDRESS); 424 | Wire._I2C_WRITE((byte)3); 425 | Wire.endTransmission(); 426 | 427 | Wire.requestFrom(PCF8523_ADDRESS, 7); 428 | uint8_t ss = bcd2bin(Wire._I2C_READ() & 0x7F); 429 | uint8_t mm = bcd2bin(Wire._I2C_READ()); 430 | uint8_t hh = bcd2bin(Wire._I2C_READ()); 431 | Wire._I2C_READ(); 432 | uint8_t d = bcd2bin(Wire._I2C_READ()); 433 | uint8_t m = bcd2bin(Wire._I2C_READ()); 434 | uint16_t y = bcd2bin(Wire._I2C_READ()) + 2000; 435 | 436 | return DateTime (y, m, d, hh, mm, ss); 437 | } 438 | 439 | Pcf8523SqwPinMode RTC_PCF8523::readSqwPinMode() { 440 | int mode; 441 | 442 | Wire.beginTransmission(PCF8523_ADDRESS); 443 | Wire._I2C_WRITE(PCF8523_CLKOUTCONTROL); 444 | Wire.endTransmission(); 445 | 446 | Wire.requestFrom((uint8_t)PCF8523_ADDRESS, (uint8_t)1); 447 | mode = Wire._I2C_READ(); 448 | 449 | mode >>= 3; 450 | mode &= 0x7; 451 | return static_cast(mode); 452 | } 453 | 454 | void RTC_PCF8523::writeSqwPinMode(Pcf8523SqwPinMode mode) { 455 | Wire.beginTransmission(PCF8523_ADDRESS); 456 | Wire._I2C_WRITE(PCF8523_CLKOUTCONTROL); 457 | Wire._I2C_WRITE(mode << 3); 458 | Wire.endTransmission(); 459 | } 460 | 461 | 462 | /////////////////////////////////////////////////////////////////////////////// 463 | // RTC_DS3231 implementation 464 | 465 | uint8_t RTC_DS3231::begin(void) { 466 | Wire.begin(); 467 | return true; 468 | } 469 | 470 | uint8_t RTC_DS3231::isrunning(void) 471 | { 472 | Wire.beginTransmission(DS3231_ADDRESS); 473 | Wire._I2C_WRITE(0); 474 | Wire.endTransmission(); 475 | 476 | Wire.requestFrom(DS3231_ADDRESS, 1); 477 | uint8_t ss = Wire._I2C_READ(); 478 | return !(ss>>7); 479 | } 480 | 481 | void RTC_DS3231::adjust(const DateTime& dt) 482 | { 483 | Wire.beginTransmission(DS3231_ADDRESS); 484 | Wire._I2C_WRITE(0); 485 | Wire._I2C_WRITE(bin2bcd(dt.second())); 486 | Wire._I2C_WRITE(bin2bcd(dt.minute())); 487 | Wire._I2C_WRITE(bin2bcd(dt.hour())); 488 | Wire._I2C_WRITE(bin2bcd(0)); 489 | Wire._I2C_WRITE(bin2bcd(dt.day())); 490 | Wire._I2C_WRITE(bin2bcd(dt.month())); 491 | Wire._I2C_WRITE(bin2bcd(dt.year() - 2000)); 492 | Wire._I2C_WRITE(0); 493 | Wire.endTransmission(); 494 | } 495 | 496 | DateTime RTC_DS3231::now() 497 | { 498 | Wire.beginTransmission(DS3231_ADDRESS); 499 | Wire._I2C_WRITE(0); 500 | Wire.endTransmission(); 501 | 502 | Wire.requestFrom(DS3231_ADDRESS, 19); 503 | 504 | uint8_t ss = bcd2bin(Wire._I2C_READ() & 0x7F); 505 | uint8_t mm = bcd2bin(Wire._I2C_READ()); 506 | uint8_t hh = bcd2bin(Wire._I2C_READ()); 507 | Wire._I2C_READ(); 508 | uint8_t d = bcd2bin(Wire._I2C_READ()); 509 | uint8_t m = bcd2bin(Wire._I2C_READ()); 510 | uint16_t y = bcd2bin(Wire._I2C_READ()) + 2000; 511 | 512 | return DateTime (y, m, d, hh, mm, ss); 513 | } 514 | 515 | float RTC_DS3231::getTemperature() { 516 | // Checks the internal thermometer on the DS3231 and returns the 517 | // temperature as a floating-point value. 518 | byte temp; 519 | Wire.beginTransmission(DS3231_ADDRESS); 520 | Wire._I2C_WRITE(0x11); 521 | Wire.endTransmission(); 522 | 523 | Wire.requestFrom(DS3231_ADDRESS, 2); 524 | temp = Wire._I2C_READ(); // Here's the MSB 525 | return float(temp) + 0.25*(Wire._I2C_READ()>>6); 526 | } 527 | 528 | void RTC_DS3231::getA1Time(byte& A1Day, byte& A1Hour, byte& A1Minute, byte& A1Second, byte& AlarmBits, bool& A1Dy, bool& A1h12, bool& A1PM) { 529 | byte temp_buffer; 530 | Wire.beginTransmission(DS3231_ADDRESS); 531 | Wire._I2C_WRITE(0x07); 532 | Wire.endTransmission(); 533 | 534 | Wire.requestFrom(DS3231_ADDRESS, 4); 535 | 536 | temp_buffer = Wire._I2C_READ(); // Get A1M1 and A1 Seconds 537 | A1Second = bcd2bin(temp_buffer & 0b01111111); 538 | // put A1M1 bit in position 0 of DS3231_AlarmBits. 539 | AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>7; 540 | 541 | temp_buffer = Wire._I2C_READ(); // Get A1M2 and A1 minutes 542 | A1Minute = bcd2bin(temp_buffer & 0b01111111); 543 | // put A1M2 bit in position 1 of DS3231_AlarmBits. 544 | AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>6; 545 | 546 | temp_buffer = Wire._I2C_READ(); // Get A1M3 and A1 Hour 547 | // put A1M3 bit in position 2 of DS3231_AlarmBits. 548 | AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>5; 549 | // determine A1 12/24 mode 550 | A1h12 = temp_buffer & 0b01000000; 551 | if (A1h12) { 552 | A1PM = temp_buffer & 0b00100000; // determine am/pm 553 | A1Hour = bcd2bin(temp_buffer & 0b00011111); // 12-hour 554 | } else { 555 | A1Hour = bcd2bin(temp_buffer & 0b00111111); // 24-hour 556 | } 557 | 558 | temp_buffer = Wire._I2C_READ(); // Get A1M4 and A1 Day/Date 559 | // put A1M3 bit in position 3 of DS3231_AlarmBits. 560 | AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>4; 561 | // determine A1 day or date flag 562 | A1Dy = (temp_buffer & 0b01000000)>>6; 563 | if (A1Dy) { 564 | // alarm is by day of week, not date. 565 | A1Day = bcd2bin(temp_buffer & 0b00001111); 566 | } else { 567 | // alarm is by date, not day of week. 568 | A1Day = bcd2bin(temp_buffer & 0b00111111); 569 | } 570 | } 571 | 572 | void RTC_DS3231::getA2Time(byte& A2Day, byte& A2Hour, byte& A2Minute, byte& AlarmBits, bool& A2Dy, bool& A2h12, bool& A2PM) { 573 | byte temp_buffer; 574 | Wire.beginTransmission(DS3231_ADDRESS); 575 | Wire._I2C_WRITE(0x0b); 576 | Wire.endTransmission(); 577 | 578 | Wire.requestFrom(DS3231_ADDRESS, 3); 579 | temp_buffer = Wire._I2C_READ(); // Get A2M2 and A2 Minutes 580 | A2Minute = bcd2bin(temp_buffer & 0b01111111); 581 | // put A2M2 bit in position 4 of DS3231_AlarmBits. 582 | AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>3; 583 | 584 | temp_buffer = Wire._I2C_READ(); // Get A2M3 and A2 Hour 585 | // put A2M3 bit in position 5 of DS3231_AlarmBits. 586 | AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>2; 587 | // determine A2 12/24 mode 588 | A2h12 = temp_buffer & 0b01000000; 589 | if (A2h12) { 590 | A2PM = temp_buffer & 0b00100000; // determine am/pm 591 | A2Hour = bcd2bin(temp_buffer & 0b00011111); // 12-hour 592 | } else { 593 | A2Hour = bcd2bin(temp_buffer & 0b00111111); // 24-hour 594 | } 595 | 596 | temp_buffer = Wire._I2C_READ(); // Get A2M4 and A1 Day/Date 597 | // put A2M4 bit in position 6 of DS3231_AlarmBits. 598 | AlarmBits = AlarmBits | (temp_buffer & 0b10000000)>>1; 599 | // determine A2 day or date flag 600 | A2Dy = (temp_buffer & 0b01000000)>>6; 601 | if (A2Dy) { 602 | // alarm is by day of week, not date. 603 | A2Day = bcd2bin(temp_buffer & 0b00001111); 604 | } else { 605 | // alarm is by date, not day of week. 606 | A2Day = bcd2bin(temp_buffer & 0b00111111); 607 | } 608 | } 609 | 610 | void RTC_DS3231::setAlarm1Simple(byte hour, byte minute) { 611 | setA1Time(0, hour, minute, 00, 0b00001000, false, false, false); 612 | } 613 | 614 | void RTC_DS3231::setAlarm2Simple(byte hour, byte minute) { 615 | setA2Time(0, hour, minute, 0b00001000, false, false, false); 616 | } 617 | 618 | void RTC_DS3231::setA1Time(byte A1Day, byte A1Hour, byte A1Minute, byte A1Second, byte AlarmBits, bool A1Dy, bool A1h12, bool A1PM) { 619 | // Sets the alarm-1 date and time on the DS3231, using A1* information 620 | byte temp_buffer; 621 | Wire.beginTransmission(DS3231_ADDRESS); 622 | Wire._I2C_WRITE(0x07); // A1 starts at 07h 623 | // Send A1 second and A1M1 624 | Wire._I2C_WRITE(bin2bcd(A1Second) | ((AlarmBits & 0b00000001) << 7)); 625 | // Send A1 Minute and A1M2 626 | Wire._I2C_WRITE(bin2bcd(A1Minute) | ((AlarmBits & 0b00000010) << 6)); 627 | // Figure out A1 hour 628 | if (A1h12) { 629 | // Start by converting existing time to h12 if it was given in 24h. 630 | if (A1Hour > 12) { 631 | // well, then, this obviously isn't a h12 time, is it? 632 | A1Hour = A1Hour - 12; 633 | A1PM = true; 634 | } 635 | if (A1PM) { 636 | // Afternoon 637 | // Convert the hour to BCD and add appropriate flags. 638 | temp_buffer = bin2bcd(A1Hour) | 0b01100000; 639 | } else { 640 | // Morning 641 | // Convert the hour to BCD and add appropriate flags. 642 | temp_buffer = bin2bcd(A1Hour) | 0b01000000; 643 | } 644 | } else { 645 | // Now for 24h 646 | temp_buffer = bin2bcd(A1Hour); 647 | } 648 | temp_buffer = temp_buffer | ((AlarmBits & 0b00000100)<<5); 649 | // A1 hour is figured out, send it 650 | Wire._I2C_WRITE(temp_buffer); 651 | // Figure out A1 day/date and A1M4 652 | temp_buffer = ((AlarmBits & 0b00001000)<<4) | bin2bcd(A1Day); 653 | if (A1Dy) { 654 | // Set A1 Day/Date flag (Otherwise it's zero) 655 | temp_buffer = temp_buffer | 0b01000000; 656 | } 657 | Wire._I2C_WRITE(temp_buffer); 658 | // All done! 659 | Wire.endTransmission(); 660 | } 661 | 662 | void RTC_DS3231::setA2Time(byte A2Day, byte A2Hour, byte A2Minute, byte AlarmBits, bool A2Dy, bool A2h12, bool A2PM) { 663 | // Sets the alarm-2 date and time on the DS3231, using A2* information 664 | byte temp_buffer; 665 | Wire.beginTransmission(DS3231_ADDRESS); 666 | Wire._I2C_WRITE(0x0b); // A1 starts at 0bh 667 | // Send A2 Minute and A2M2 668 | Wire._I2C_WRITE(bin2bcd(A2Minute) | ((AlarmBits & 0b00010000) << 3)); 669 | // Figure out A2 hour 670 | if (A2h12) { 671 | // Start by converting existing time to h12 if it was given in 24h. 672 | if (A2Hour > 12) { 673 | // well, then, this obviously isn't a h12 time, is it? 674 | A2Hour = A2Hour - 12; 675 | A2PM = true; 676 | } 677 | if (A2PM) { 678 | // Afternoon 679 | // Convert the hour to BCD and add appropriate flags. 680 | temp_buffer = bin2bcd(A2Hour) | 0b01100000; 681 | } else { 682 | // Morning 683 | // Convert the hour to BCD and add appropriate flags. 684 | temp_buffer = bin2bcd(A2Hour) | 0b01000000; 685 | } 686 | } else { 687 | // Now for 24h 688 | temp_buffer = bin2bcd(A2Hour); 689 | } 690 | // add in A2M3 bit 691 | temp_buffer = temp_buffer | ((AlarmBits & 0b00100000)<<2); 692 | // A2 hour is figured out, send it 693 | Wire._I2C_WRITE(temp_buffer); 694 | // Figure out A2 day/date and A2M4 695 | temp_buffer = ((AlarmBits & 0b01000000)<<1) | bin2bcd(A2Day); 696 | if (A2Dy) { 697 | // Set A2 Day/Date flag (Otherwise it's zero) 698 | temp_buffer = temp_buffer | 0b01000000; 699 | } 700 | Wire._I2C_WRITE(temp_buffer); 701 | // All done! 702 | Wire.endTransmission(); 703 | } 704 | 705 | void RTC_DS3231::turnOnAlarm(byte Alarm) { 706 | // turns on alarm number "Alarm". Defaults to 2 if Alarm is not 1. 707 | byte temp_buffer = readControlByte(0); 708 | // modify control byte 709 | if (Alarm == 1) { 710 | temp_buffer = temp_buffer | 0b00000101; 711 | } else { 712 | temp_buffer = temp_buffer | 0b00000110; 713 | } 714 | writeControlByte(temp_buffer, 0); 715 | } 716 | 717 | void RTC_DS3231::turnOffAlarm(byte Alarm) { 718 | // turns off alarm number "Alarm". Defaults to 2 if Alarm is not 1. 719 | // Leaves interrupt pin alone. 720 | byte temp_buffer = readControlByte(0); 721 | // modify control byte 722 | if (Alarm == 1) { 723 | temp_buffer = temp_buffer & 0b11111110; 724 | } else { 725 | temp_buffer = temp_buffer & 0b11111101; 726 | } 727 | writeControlByte(temp_buffer, 0); 728 | } 729 | 730 | bool RTC_DS3231::checkAlarmEnabled(byte Alarm) { 731 | // Checks whether the given alarm is enabled. 732 | byte result = 0x0; 733 | byte temp_buffer = readControlByte(0); 734 | if (Alarm == 1) { 735 | result = temp_buffer & 0b00000001; 736 | } else { 737 | result = temp_buffer & 0b00000010; 738 | } 739 | return result; 740 | } 741 | 742 | bool RTC_DS3231::checkIfAlarm(byte Alarm) { 743 | // Checks whether alarm 1 or alarm 2 flag is on, returns T/F accordingly. 744 | // Turns flag off, also. 745 | // defaults to checking alarm 2, unless Alarm == 1. 746 | byte result; 747 | byte temp_buffer = readControlByte(1); 748 | if (Alarm == 1) { 749 | // Did alarm 1 go off? 750 | result = temp_buffer & 0b00000001; 751 | // clear flag 752 | temp_buffer = temp_buffer & 0b11111110; 753 | } else { 754 | // Did alarm 2 go off? 755 | result = temp_buffer & 0b00000010; 756 | // clear flag 757 | temp_buffer = temp_buffer & 0b11111101; 758 | } 759 | writeControlByte(temp_buffer, 1); 760 | return result; 761 | } 762 | 763 | void RTC_DS3231::enableOscillator(bool TF, bool battery, byte frequency) { 764 | // turns oscillator on or off. True is on, false is off. 765 | // if battery is true, turns on even for battery-only operation, 766 | // otherwise turns off if Vcc is off. 767 | // frequency must be 0, 1, 2, or 3. 768 | // 0 = 1 Hz 769 | // 1 = 1.024 kHz 770 | // 2 = 4.096 kHz 771 | // 3 = 8.192 kHz (Default if frequency byte is out of range) 772 | if (frequency > 3) frequency = 3; 773 | // read control byte in, but zero out current state of RS2 and RS1. 774 | byte temp_buffer = readControlByte(0) & 0b11100111; 775 | if (battery) { 776 | // turn on BBSQW flag 777 | temp_buffer = temp_buffer | 0b01000000; 778 | } else { 779 | // turn off BBSQW flag 780 | temp_buffer = temp_buffer & 0b10111111; 781 | } 782 | if (TF) { 783 | // set ~EOSC to 0 and INTCN to zero. 784 | temp_buffer = temp_buffer & 0b01111011; 785 | } else { 786 | // set ~EOSC to 1, leave INTCN as is. 787 | temp_buffer = temp_buffer | 0b10000000; 788 | } 789 | // shift frequency into bits 3 and 4 and set. 790 | frequency = frequency << 3; 791 | temp_buffer = temp_buffer | frequency; 792 | // And write the control bits 793 | writeControlByte(temp_buffer, 0); 794 | } 795 | 796 | void RTC_DS3231::enable32kHz(bool TF) { 797 | // turn 32kHz pin on or off 798 | byte temp_buffer = readControlByte(1); 799 | if (TF) { 800 | // turn on 32kHz pin 801 | temp_buffer = temp_buffer | 0b00001000; 802 | } else { 803 | // turn off 32kHz pin 804 | temp_buffer = temp_buffer & 0b11110111; 805 | } 806 | writeControlByte(temp_buffer, 1); 807 | } 808 | 809 | bool RTC_DS3231::oscillatorCheck() { 810 | // Returns false if the oscillator has been off for some reason. 811 | // If this is the case, the time is probably not correct. 812 | byte temp_buffer = readControlByte(1); 813 | bool result = true; 814 | if (temp_buffer & 0b10000000) { 815 | // Oscillator Stop Flag (OSF) is set, so return false. 816 | result = false; 817 | } 818 | return result; 819 | } 820 | 821 | byte RTC_DS3231::readControlByte(bool which) { 822 | // Read selected control byte 823 | // first byte (0) is 0x0e, second (1) is 0x0f 824 | Wire.beginTransmission(DS3231_ADDRESS); 825 | if (which) { 826 | // second control byte 827 | Wire._I2C_WRITE(0x0f); 828 | } else { 829 | // first control byte 830 | Wire._I2C_WRITE(0x0e); 831 | } 832 | Wire.endTransmission(); 833 | Wire.requestFrom(DS3231_ADDRESS, 1); 834 | return Wire._I2C_READ(); 835 | } 836 | 837 | void RTC_DS3231::writeControlByte(byte control, bool which) { 838 | // Write the selected control byte. 839 | // which=false -> 0x0e, true->0x0f. 840 | Wire.beginTransmission(DS3231_ADDRESS); 841 | if (which) { 842 | Wire._I2C_WRITE(0x0f); 843 | } else { 844 | Wire._I2C_WRITE(0x0e); 845 | } 846 | Wire._I2C_WRITE(control); 847 | Wire.endTransmission(); 848 | } 849 | --------------------------------------------------------------------------------