AdSense

Tuesday 24 September 2013

Real Time Clock DS1307

(Deutsche Version) Sometimes you need the date or time for your Arduino projects, for example for data logging. In this case, a so called real time clock module like "Tiny RTC" comes in very handy. It is based on a DS1307 and has a backup battery. It keeps on counting the time, even if your Arduino is not longer connected to a power supply.

The DS1307 is connected via I2C. You just have to connect the power supply and SDA and SCL with the according pins on your Arduino. It is important to use pins on the right side of the module (the side with 7 pins). With the pins on the other side you can connect the EEPROM-IC which is also soldered to the board.

You can read date and time (year, month, day, weekday, hour, minute, second) from your RTC module. These values are stored in a SRAM register and can be interfaced via I2C. 
Register 0: bits 0 to 6 store the seconds - bit 7 indicates if the clock is running or not. When the bit is set to 1 - the clock will stop. 
Register 1: bits 0 to 6 store the minutes.
Register 2: if bit 6 is set, the hours are stored in 12h-format. Bit 5 indicates wheter it's AM or PM. The hours are stored in bit 0 to 4. If bit 6 is cleared, the hours are stored in 24h-format in bits 0 to 5.
Register 3: weekdays can be read from bits 0 to 3. If the register is set to 1, it's Sunday, 2 means Monday and so on.
Register 4 to 6: date, month and year
Register 7: some configuration-stuff we won't need.
The following register can be used as battery-powered RAM and can be read and written as desired.

All numbers are stored in BCD-format (Binary Coded Decimal). For example, the number 18 would be 0001'1000, 34 would be 0011'0100 and so on.

The address of the DS1307 in I2C-bus is 0x68.

Before first use, you have to set the correct time:

#include "Wire.h"

#define DS1307_ADDRESS 0x68

void setup(){
  Wire.begin();
    
  Serial.begin(9600);
  
  byte second =      0; //0-59
  byte minute =      44; //0-59
  byte hour =        22; //0-23
  byte weekDay =     1; //1-7
  byte monthDay =    22; //1-31
  byte month =       9; //1-12
  byte year  =       13; //0-99

  Wire.beginTransmission(DS1307_ADDRESS);
    
  Wire.write(0x00); //set pointer to register 0
  
  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.endTransmission();
  
}

void loop(){
}

byte decToBcd(byte val){
//convert decimal to BCD
  return ( (val/10*16) + (val%10) );
}

In the variables you have to set the correct date and time. With beginTransmission() you start communicating with the module. After setting the pointer to register 0 (where the seconds are stored), you can transmit date and time: the values stored in the variables are converted to BCD and then written to the register. After each write()-command, the Arduino automatically jumps to the next register.


Once the DS1307 is set correct, it keeps on counting the time until the end of time (or its battery). Date and time can be accessed with the following code:


#include "Wire.h"
#define DS1307_ADDRESS 0x68

void setup(){
  Wire.begin();
  Serial.begin(9600);
}

void loop(){
  
  //set pointer to register 0
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(0x00);
  Wire.endTransmission();

  //get time
  Wire.requestFrom(DS1307_ADDRESS, 7);

  int second = bcdToDec(Wire.read());
  int minute = bcdToDec(Wire.read());
  int hour = bcdToDec(Wire.read());
  int weekDay = bcdToDec(Wire.read());
  int monthDay = bcdToDec(Wire.read());
  int month = bcdToDec(Wire.read());
  int year = bcdToDec(Wire.read());

  //print date and time in format dd.mm.yy - hh:mm:ss
  Serial.print(monthDay);
  Serial.print(".");
  Serial.print(month);
  Serial.print(".");
  Serial.print(year);
  Serial.print(" - ");
  Serial.print(hour);
  Serial.print(":");
  Serial.print(minute);
  Serial.print(":");
  Serial.println(second);
  delay(1000);
}

byte bcdToDec(byte val)  {
//convert BCD to de cimal
  return ( (val/16*10) + (val%16) );
}

At first the pointer is set so register 0 (since we want to start reading the seconds). After that, 7 bytes of data are requested with requestFrom(). The data is read(), converted to decimal and stored in variables. At the end, date and time are printed via serial.

No comments:

Post a Comment