A real-time clock (RTC) is the center piece of any project that needs to keep an accurate track of time. Your wrist and nightstand watch is certainly equipped with one of these modules. Also, as it runs on a battery, the RTC can keep track of longer time periods even if you have to reflash the microcontroller or disconnect it from the main power supply.
Most microcontrollers have timers embedded into the chip that have the ability to keep track of short time periods. Also, the Arduino has a timer based function called millis() which can keep track of the time since it was last powered or reseted.
However, the problem with this type of timekeeping is that the microcontroller doesn’t know if it’s ‘Monday’ or ‘September 9th’. It only knows how many milliseconds have passed since it was last powered on. Also, millis() will overflow after approximately 50 days.
This sort of basic timekeeping might be enough for projects that don’t need to have a consistent timekeeping. On the other hand, if you’re planning to build a clock or a data-logger a real-time clock is mandatory.
Quoting the datasheet, the DS1307 serial real-time clock is a lowpower, full binary-coded decimal (BCD) clock/calendar plus 56 bytes of NV SRAM. Address and data are transferred serially through an I2C bidirectional bus.
The clock/calendar provides seconds, minutes, hours, day, date, month, and year information. The end of the month date is automatically adjusted for months with fewer than 31 days, including corrections for leap year. The clock operates in either the 24-hour or 12-hour format with AM/PM indicator.
The DS1307 has a built-in power-sense circuit that detects power failures and automatically switches to the backup supply. Timekeeping operation continues while the part operates from the backup supply.
For this tutorial you just need an Arduino Nano 3.0, a DS1307 real-time clock module a breadboard and wires.
Regarding the I2C bus and to avoid communications problems make sure that your RTC module is equipped with pull-up resistors on the SDA and SCL lines. If your module doesn’t have these resistors you can add them externally. Even though knowing that choosing the correct resistance is not that trivial, for a project like this, a value between 2.2kOhm and 10kOhm should be just fine.
Now you have to replicate the circuit below:
Before compiling the code below you need to download, uncompress and install the RTClib library. To install, simply copy it into the “libraries” folder. Alternatively you can read the official tutorial: Installing Additional Arduino Libraries
The code follows below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
/***************************************************************************** * Copyright (C) 2013 by Vasco Ferraz. All Rights Reserved. * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see <http://www.gnu.org/licenses/>. * * * * Author: Vasco Ferraz * * Contact: http://vascoferraz.com/contact/ * * Description: http://vascoferraz.com/tutorials/ds1307-real-time-clock/ * *****************************************************************************/ #include <Wire.h> // I2C and TWI library #include <RTClib.h> // RTClib library #define DS1307_I2C_ADDRESS 0x68 // Each I2C object has a unique bus address, the DS1307 (Real Time Clock) is 0x68 RTC_DS1307 RTC; void setup () { Serial.begin(9600); Wire.begin(); RTC.begin(); // If the clock is not running, execute the following code if (! RTC.isrunning()) { Serial.println("Not Running! Restarting the clock"); delay(5000); // Starts ticking the clock Wire.beginTransmission(DS1307_I2C_ADDRESS); Wire.write(0x00); // Move pointer to 0x00 byte address Wire.write(0x00); // Sends 0x00. The whole byte is set to zero (0x00). This also means seconds will reset!! Unless you use a mask -> homework :) Wire.endTransmission(); // Following line sets the RTC to the date & time this sketch was compiled RTC.adjust(DateTime(__DATE__, __TIME__)); // Following line sets the RTC to the date & time to: 2015 January 01 - 00:00:00 //RTC.adjust(DateTime(2015,1,1, 0,0,0)); // Sequence: year, month, day, hour, minute, second } } void loop () { printTime(); printDate(); } // Print hour, minute and second void printTime (void) { DateTime now = RTC.now(); // Print hour if (now.hour() <= 9) { Serial.print("0"); Serial.print(now.hour(), DEC); Serial.print(":"); } else { Serial.print(now.hour(), DEC); Serial.print(":"); } // Print minute if (now.minute() <= 9) { Serial.print("0"); Serial.print(now.minute(), DEC); Serial.print(":"); } else { Serial.print(now.minute(), DEC); Serial.print(":"); } // Print second if (now.second() <= 9) { Serial.print("0"); Serial.print(now.second(), DEC); } else { Serial.print(now.second(), DEC); } } //Print day, month, year and weekday void printDate (void) { DateTime now = RTC.now(); Serial.print(" | "); // Print day if (now.day() <= 9) { Serial.print("0"); Serial.print(now.day(), DEC); Serial.print("/"); } else { Serial.print(now.day(), DEC); Serial.print("/"); } // Print month switch(now.month()) { case 1: Serial.print("Jan/"); break; case 2: Serial.print("Feb/"); break; case 3: Serial.print("Mar/"); break; case 4: Serial.print("Apr/"); break; case 5: Serial.print("May/"); break; case 6: Serial.print("Jun/"); break; case 7: Serial.print("Jul/"); break; case 8: Serial.print("Aug/"); break; case 9: Serial.print("Sep/"); break; case 10: Serial.print("Oct/"); break; case 11: Serial.print("Nov/"); break; case 12: Serial.print("Dec/"); break; default: Serial.print("Err/"); } // Print year Serial.print(now.year(), DEC); // Print weekday switch(now.dayOfTheWeek()) { case 0: Serial.println(" | Sunday"); break; case 1: Serial.println(" | Monday"); break; case 2: Serial.println(" | Tuesday"); break; case 3: Serial.println(" | Wednesday"); break; case 4: Serial.println(" | Thursday"); break; case 5: Serial.println(" | Friday"); break; case 6: Serial.println(" | Saturday"); break; default: Serial.println(" | Error"); } } |
Open the Serial Monitor and watch the clock ticking.