How to use DS1307 Real time clock module with Arduino

Most of the microcontrollers are time-agnostic, meaning they are unaware of the time around them, but it doesn’t matter as most experiments do not require it. But, there are several experiments that require the actual time. For example, most of the experiments related to data-logging require time.
The following Real time clock (RTC) module can add actual time value to your data-logging experiments.
For this article we will be discussing and using a RTC Module available at buildcircuit.net because it incorporates everything you need to make it work, including a backup battery good for a minimum of 3 years. It comes with the time preset, but you can easily reset it and configure to your own time.
About DS1307
Read about I2C at tronixstuff.com (highly recommended)
The DS1307 is actually a very simple I2C chip. It just gives you back 7 bytes of information that is the time. So, all we need to do is receive it and converts it to decimal. The DS1307 encodes all the data in “Binary Coded Decimal” or BCD. BCD is just a way to encode numbers, and works by encoding each digit in 4 digits of binary… like so:
157 = 0001 0101 0111
1 = 0001
5 = 0101
7 = 0111
Normally you would say that 157 = 10011101. But that is 157, BCD encodes each digit separately. 1, 5, 7 not 157. hence 0001, 0101, 0111 not 10011101.
Ok, now that we know we will be receiving the data as BCD, we just need a way to convert that to decimal. Luckily, John Boxall over at TronixStuff (incredibly awesome site) has a pretty simple function to do that for us.
Connecting the module to Arduino:
Because the DS1307 is an I2C device (I2C is a 2-wire serial connection), you just need to connect the SDA (Data) and SCL (Clock) lines to your Arduino for communication. On your Arduino (all boards but the mega) SDA is on analog pin 4, and SCL is on analog pin 5. On an Arduino mega, SDA is digital 20, and SCL is digital 21.
You can buy the real time clock module at www.buildcircuit.net. The store is owned and operated by BuildCircuit Team.
Sketch:
If you intend to use the clock to set alarms and trigger events based on time, then you should take a look at Lady Ada’s library for this. It’s more advanced, and allows you to make alarms, and check how much time is left and so on.
The following source codes have been copied from bildr.org. The code can be used for testing the module. It simply displays the set time and date.
//Arduino 1.0+ Only | |
//Arduino 1.0+ Only | |
#include "Wire.h" | |
#define DS1307_ADDRESS 0x68 | |
void setup(){ | |
Wire.begin(); | |
Serial.begin(9600); | |
} | |
void loop(){ | |
printDate(); | |
delay(1000); | |
} | |
byte bcdToDec(byte val) { | |
// Convert binary coded decimal to normal decimal numbers | |
return ( (val/16*10) + (val%16) ); | |
} | |
void printDate(){ | |
// Reset the register pointer | |
Wire.beginTransmission(DS1307_ADDRESS); | |
byte zero = 0x00; | |
Wire.write(zero); | |
Wire.endTransmission(); | |
Wire.requestFrom(DS1307_ADDRESS, 7); | |
int second = bcdToDec(Wire.read()); | |
int minute = bcdToDec(Wire.read()); | |
int hour = bcdToDec(Wire.read() & 0b111111); //24 hour time | |
int weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday | |
int monthDay = bcdToDec(Wire.read()); | |
int month = bcdToDec(Wire.read()); | |
int year = bcdToDec(Wire.read()); | |
//print the date EG 3/1/11 23:59:59 | |
Serial.print(month); | |
Serial.print("/"); | |
Serial.print(monthDay); | |
Serial.print("/"); | |
Serial.print(year); | |
Serial.print(" "); | |
Serial.print(hour); | |
Serial.print(":"); | |
Serial.print(minute); | |
Serial.print(":"); | |
Serial.println(second); | |
} |
//Arduino 1.0+ Only | |
//Arduino 1.0+ Only | |
#include "Wire.h" | |
#define DS1307_ADDRESS 0x68 | |
byte zero = 0x00; //workaround for issue #527 | |
void setup(){ | |
Wire.begin(); | |
Serial.begin(9600); | |
setDateTime(); //MUST CONFIGURE IN FUNCTION | |
} | |
void loop(){ | |
printDate(); | |
delay(1000); | |
} | |
void setDateTime(){ | |
byte second = 45; //0-59 | |
byte minute = 40; //0-59 | |
byte hour = 0; //0-23 | |
byte weekDay = 2; //1-7 | |
byte monthDay = 1; //1-31 | |
byte month = 3; //1-12 | |
byte year = 11; //0-99 | |
Wire.beginTransmission(DS1307_ADDRESS); | |
Wire.write(zero); //stop Oscillator | |
Wire.write(decToBcd(second)); | |
Wire.write(decToBcd(minute)); | |
Wire.write(decToBcd(hour)); | |
Wire.write(decToBcd(weekDay)); | |
Wire.write(decToBcd(monthDay)); | |
Wire.write(decToBcd(month)); | |
Wire.write(decToBcd(year)); | |
Wire.write(zero); //start | |
Wire.endTransmission(); | |
} | |
byte decToBcd(byte val){ | |
// Convert normal decimal numbers to binary coded decimal | |
return ( (val/10*16) + (val%10) ); | |
} | |
byte bcdToDec(byte val) { | |
// Convert binary coded decimal to normal decimal numbers | |
return ( (val/16*10) + (val%16) ); | |
} | |
void printDate(){ | |
// Reset the register pointer | |
Wire.beginTransmission(DS1307_ADDRESS); | |
Wire.write(zero); | |
Wire.endTransmission(); | |
Wire.requestFrom(DS1307_ADDRESS, 7); | |
int second = bcdToDec(Wire.read()); | |
int minute = bcdToDec(Wire.read()); | |
int hour = bcdToDec(Wire.read() & 0b111111); //24 hour time | |
int weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday | |
int monthDay = bcdToDec(Wire.read()); | |
int month = bcdToDec(Wire.read()); | |
int year = bcdToDec(Wire.read()); | |
//print the date EG 3/1/11 23:59:59 | |
Serial.print(month); | |
Serial.print("/"); | |
Serial.print(monthDay); | |
Serial.print("/"); | |
Serial.print(year); | |
Serial.print(" "); | |
Serial.print(hour); | |
Serial.print(":"); | |
Serial.print(minute); | |
Serial.print(":"); | |
Serial.println(second); | |
} |
MORE SIMPLE CODE FROM ADAFRUIT.COM
Adafruit.com also sells its own model of real time clock module. They have an excellent library for the module. DOWNLOAD THE LIBRARY.
The library and source codes available are excellent for data-logging experiments.
In this experiment, the sketch reads the time from the RTC once a second. You will see what happens if you remove the battery and replace it since that causes the RTC to halt. Load up the following sketch (which is also found in Examples→RTClib→ds1307) and upload it to your Arduino with the datalogger(data-logging components) shield on!
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib | |
#include <Wire.h> | |
#include "RTClib.h" | |
RTC_DS1307 RTC; | |
void setup () { | |
Serial.begin(57600); | |
Wire.begin(); | |
RTC.begin(); | |
if (! RTC.isrunning()) { | |
Serial.println("RTC is NOT running!"); | |
// following line sets the RTC to the date & time this sketch was compiled | |
//RTC.adjust(DateTime(__DATE__, __TIME__)); | |
} | |
} | |
void loop () { | |
DateTime now = RTC.now(); | |
Serial.print(now.year(), DEC); | |
Serial.print('/'); | |
Serial.print(now.month(), DEC); | |
Serial.print('/'); | |
Serial.print(now.day(), DEC); | |
Serial.print(' '); | |
Serial.print(now.hour(), DEC); | |
Serial.print(':'); | |
Serial.print(now.minute(), DEC); | |
Serial.print(':'); | |
Serial.print(now.second(), DEC); | |
Serial.println(); | |
Serial.print(" since 1970 = "); | |
Serial.print(now.unixtime()); | |
Serial.print("s = "); | |
Serial.print(now.unixtime() / 86400L); | |
Serial.println("d"); | |
// calculate a date which is 7 days and 30 seconds into the future | |
DateTime future (now.unixtime() + 7 * 86400L + 30); | |
Serial.print(" now + 7d + 30s: "); | |
Serial.print(future.year(), DEC); | |
Serial.print('/'); | |
Serial.print(future.month(), DEC); | |
Serial.print('/'); | |
Serial.print(future.day(), DEC); | |
Serial.print(' '); | |
Serial.print(future.hour(), DEC); | |
Serial.print(':'); | |
Serial.print(future.minute(), DEC); | |
Serial.print(':'); | |
Serial.print(future.second(), DEC); | |
Serial.println(); | |
Serial.println(); | |
delay(3000); | |
} |