SONY DSC © 2011 admin. All rights reserved.

Arduino Love electronics RTC – DS3231 wiring example and tutorial.

As you may be aware from my previous post I recently was in the market for a more accurate replacement for the DS1307 RTC clock. I tried with a DS3234 but its SPI interface made it unsuitable in my project (running out of pins). All i was after was a simple breakout board for the DS3231 I found the chronodot but its presoldered pins, lack of stock in/transport costs to Australia (As per normal) and their overly complex setup (for my use anyway). I came across a UK based website called loveelectronics.co.uk . They have a perfect little DS3231 breakout board.

The bonus of this DS3231 board is its improved accuracy over the DS1307 but still using the I2C interface that the DS1307 uses. In short any code that works with DS1307 should work with DS3231 without any changes. One downside of this kit is that it doesn’t come with a coin battery but this is a minor issue. ENSURE YOU HAVE A BATTERY IN THE HOLDER (EVEN IF FLAT), OTHERWISE YOU GET STRANGE RESULTS.

So with that out of the way let me give you a quick tutorial on getting this chip running, first the cabling.

This is the exact same setup as the DS1307, a small problem with the DS3231 board is its hard to see which contact is SDA, but I did this drawing to make it easier for you (and me to look back at). So once you have wired it up(and double checked ground and 5V {trust me do it}). So lets try the basic 1307 reading by the wire library code:

#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);
  Wire.send(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_ADDRESS, 7);

  int second = bcdToDec(Wire.receive());
  int minute = bcdToDec(Wire.receive());
  int hour = bcdToDec(Wire.receive() & 0b111111); //24 hour time
  int weekDay = bcdToDec(Wire.receive()); //0-6 -> sunday - Saturday
  int monthDay = bcdToDec(Wire.receive());
  int month = bcdToDec(Wire.receive());
  int year = bcdToDec(Wire.receive());

  //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);

}

Once uploaded keep the Arduino program open, and go to Tools -> Serial Monitor ensure the baud is at 9600. You should see something similar to:

So before I ran this code I removed power and battery so I reset the RTC to 0:0:0 0/0/00. So there we go its now ticking away. This is a great basic method but I wanted something a bit nicer and easier to work with.

As my previous post I am once again going to use the RTC library changed by manicbubg forked from adafriut. Again this is a little bit further on than the original RTC library sent out in 2010. As you may have seen before this one library allows you to interface with a DS3234 and a DS1307, as i said before DS3231 works exactly the same as the DS1307 so its perfect for us. You can jump onto the github service and download a .zip of the current release or you can use the copy that I’m writing this tutorial with (so it should work) hereExtract the folder inside the zip intoyour arduino\libraries\ and rename the folder to ”ManicbugRTCLib“, If you already have the generic RTClib installed it is best to move it out of the libraries folder(Otherwise it could call the original RTCLIB). Restart the Arduino software. With a new sketch paste in the following code, Alternatively you can go file -> examples -> ManicbugRTCLib -> DS1307 (Read after my code paste to see changes I have done to the standard example).

// Date and time functions using a DS1307 RTC connected via I2C and Wire lib

#include <Wire.h>
#include <SPI.h>
#include <RTClib.h>
#include <RTC_DS1307.h>

RTC_DS1307 RTC;

void setup () {
    Serial.begin(57600);
    Wire.begin();
    RTC.begin();
    DateTime now = RTC.now();
    DateTime compiled = DateTime(__DATE__, __TIME__);
    if (now.unixtime() < compiled.unixtime()) {
    Serial.println("RTC is older than compile time! Updating");
    // 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 midnight 1/1/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);
}
// vim:ci:sw=4 sts=4 ft=cpp

Originally the example has “if(! RTC.isrunning())” . However i never found a time where the RTC wasnt running, even when i took the battery out it started right away as soon as power was restored. The problem here the clock is never set to the current date and time (minus a few seconds). So I replaced that bit of code with;

    DateTime now = RTC.now();
    DateTime compiled = DateTime(__DATE__, __TIME__);
    if (now.unixtime() < compiled.unixtime()) {
    Serial.println("RTC is older than compile time! Updating");
    // following line sets the RTC to the date & time this sketch was compiled
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }

This code gets the time off the DS3231 module and then the time the sketch was created then compares the two dates  If it finds the RTC’s date is earlier than the date the sketch was created it updates the time to the sketch compile date. This is how you can be a few seconds out from actual time due to the time it takes to flash the Arduino.

Once you upload the above code keep the Arduino program open, and go to Tools -> Serial Monitor, ensure the baud down the bottom right is set to 57600. You should see an output like:

So here you can see that the clock has been set as it saw that the previous time was earlier than todays time. I think I will continue to use this chip and breakout board, with the above library.

I hope this blog post helps someone get started with an RTC, chuck me a message telling me what you use it for.

Did you like this? Share it:

4 Comments

  1. Bob D

    Marc
    The reason you have problems without a battery is that BAT pin is supposed to have a battery attached or it must be grounded. See the DS3231 datasheet. I used the Chrondot V2 mainly because it has a larger battery than the Love kit. Not cheap at about AU$30 delivered to Australia. I removed the header pins for my usage

  2. Bob D

    I am curious about this line

    int weekDay = bcdToDec(Wire.receive()); //0-6 -> sunday – Saturday

    When I read the DS3231 datasheet it states the range for this value in the DS3231 register 03H is 1 to 7. Are you actually running it as 0 to 6 successfully?

  3. ALbert

    Hi Marc!
    thanks for this example (DS3231 wiring example and tutorial), which helps me a lot (as a newbe….). I have the following question: line 15 in your second example (“DateTime compiled = DateTime(__DATE__, __TIME__);”) is not recognised by my Arduino 1.02 setup, it seems to have a problem with __DATE__ which gives me an “Error – __DATE__ was not declared in this scope”.
    Please can you help me?
    Thank you!
    Best regards – Albert

    • ALbert

      hm, found the cause of the error…., makes me think….
      I had spelled the keyword in brackets wrong (instead of “DATE” spelled “Date”)
      now it works!
      Thanks again for the code!

One Trackback

  1. By メモたんく » DS3231Sブレイクアウトボードのテスト完了 14 Mar ’12 at 6:48 pm

Leave a Reply

Your email address will not be published.
Required fields are marked:*

*


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>