An Arduino LCD clock using the ChronoDot RTC

Well, here I go again, another adventure into the land of Arduino. I am in the midst of building an art project which requires the ability to keep accurate time. My first inclination was to create a software solution only using the Arduino. But after a few minutes of research I was aware of the disadvantage of a software solution, mainly, that the time would be incorrect if the Arduino was ever reset. I continued my research and found some cool Arduino clock kits and some great threads on RTC (REAL TIME CLOCK) chips, mainly the more popular DS1337 and DS1307.

Unfortunately both DS1337 and DS1307 chips seem to drift minutes per month, especially in extreme temperature ranges. So, I continued scouring the internet, until I found a thread that mentioned the ChronoDot RTC by MaceTech. The ChronoDot RTC is an extremely accurate real time clock module, based on the DS3231 temperature compensated RTC (TCXO). The ChronoDot claims to drift less than a minute per year, which makes the ChronoDot acceptable for my project. MaceTech provides a basic Arduino example using the Arduino Wire library which reads and prints the hours, minutes, and seconds from the ChronoDot. I basically borrowed the code and expanded upon it. I utilize a basic 16×2 LCD to output the time and date from the ChronoDot and I added the ability to change the hour and minutes via 2 push buttons.

The Arduino communicates with the ChronoDot, using the I2C standard interface. I2C is a serial data bus protocol that allows multiple devices to connect to each other with fairly slow data transfer rates. Thanks to the Arduino Wire library we don’t have to worry about the details. Moving forward you will need the following items to recreate my example:

Arduino Duemilanove,

a character LCD display with 0.1 header 16 pins long and a 10K potentiometer to adjust the contrast on the display,

a 6″ breadboard,

breadboarding wire,

a ChronoDot module,

2 10Kohm 1/2W 5% Carbon Film Resistors
pRS1C-2160239w345

and 2 push buttons.

The first thing you are going to do is connect your LCD to the Arduino. If you are not familiar with the steps, please read my post on connecting a character LCD to an Arduino. I placed my LCD as far left as I could on my 6″ breadboard to allow space for the other components.

The next step is to add the push buttons. The push buttons will enable the ability to set the hour and minutes, if needed.

Grab a push button, and place it on the breadboard. Grab a 10K resistor and connect one end of the resistor to the ground on the breadboard and then connect the other end of the resistor to one leg of the button, remember to leave space between the leg of the button and the resistor. Now, grab breadboarding wire and connect one end of the wire to the power supply on the breadboard, then connect the other end of the wire to the other leg of the button. You have completed a simple button circuit, grab the other push button and repeat the steps, your breadboard should resemble this:


Lets connect a button to the Arduino. Grab a breadboarding wire and connect one end of the wire to digital pin 6 of the Arduino. Connect the other end of the wire to the breadboard between the resistor and the one (grounded) leg of the push button. You have now created a button connection for the hour. Do the same for the minutes button but instead connect one end of a breadboarding wire to digital pin 7 of the Arduino. Connect the other end of the wire to the breadboard between the resistor and the one (grounded) leg of the push button. Your breadboard should look like this:

Now for the final piece, the good ole RTC Module. If you purchased the ChronoDot from Macetech, you should have received the lithium CR2032 battery. The battery allows timekeeping in the absence of external power, you will need to attach the battery to the module. The two solder pads on the PCB are marked + and -. The battery provided with the ChronoDot has a metal tab that runs from the top (positive, +) of the battery and down to the same level as the bottom (negative, -) side of the battery. You will need to solder the tab leading from the top of the battery to the + pad on the ChronoDot. The result should look like this:

Now, place the RTC module on the breadboard. Run breadboarding wire from the ground of the breadboard to the ground of the RTC. Run another strand of wire from the power supply of the breadboard to the VCC line of the RTC:

Grab two more wires to make the final connections to the RTC. Connect one end of a wire to the Arduino Analog pin 5. Now, connect the other end of the wire to the SCL pin of the ChronoDot RTC module on the breadboard. Grab the other wire and connect one end of the wire to the Arduino’s Analog pin 4. Connect the other end of the wire to the SDA pin of the RTC module on the breadboard. You have now connected the wires which communicate between the Arduino and the ChronoDot. Your completed breadboard should resemble this:

All there is left to do, is upload the example sketch below.
/*
 Code under (cc) by Manuel Gonzalez, www.codingcolor.com
 http://creativecommons.org/license/cc-gpl
 Pins 12, 11, 5, 4, 3, 2 to LCD
 Analog pins 4 (SDA),5(SCL) to Chronodot
 Pins 6 (hour), 7(min) buttons
*/


#include <Wire.h>
#include <LiquidCrystal.h>


const int hourButtonPin = 6;
const int minButtonPin = 7;

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

int hourButtonState;
int minButtonState;

int seconds; //00-59;
int minutes; //00-59;
int hours;//1-12 - 00-23;
int day;//1-7
int date;//01-31
int month;//01-12
int year;//0-99;




void setup()
{

  pinMode(hourButtonPin,INPUT);
  pinMode(minButtonPin,INPUT);

  Wire.begin();
  lcd.begin(16, 2);
 
  hourButtonState = 0;
  minButtonState = 0;
  ////////////////////////////////
  seconds = 00;
  minutes = 26;
  hours = 17;
  day = 7;
  date = 31;
  month = 5;
  year = 10;
  //initChrono();//just set the time once on your RTC
  ///////////////////////////////
}

void loop()
{
  check_buttons();
  get_time();
  get_date();
  display_time();
  display_date();
  delay(1000);
 
}
void display_time()
{
  char buf[12];
 
  lcd.setCursor(0, 0);
 
  if(hours == 0)
  {
    lcd.clear();
  }
 
  lcd.print("Time ");  
  lcd.print(itoa(hours, buf, 10));
  lcd.print(":");
 
  if(minutes < 10)
  {
    lcd.print("0");
  }
  lcd.print(itoa(minutes, buf, 10));
 
  lcd.print(":");
 
  if(seconds < 10){
    lcd.print("0");
  }
  lcd.print(itoa(seconds, buf, 10));

}
void display_date()
{
  char buf[12];
 
  lcd.setCursor(0, 1);
  lcd.print("Date ");
 
 if(month < 10){
    lcd.print("0");
  }  
 
  lcd.print(itoa(month, buf, 10));
  lcd.print("/");
  lcd.print(itoa(date, buf, 10));
  lcd.print("/");
 
  if(year < 10){
    lcd.print("0");
  }
 
  lcd.print(itoa(year, buf, 10));
}
void initChrono()
{
  set_time();
  set_date();
}


void set_date()
{
  Wire.beginTransmission(104);
  Wire.send(3);
  Wire.send(decToBcd(day));
  Wire.send(decToBcd(date));
  Wire.send(decToBcd(month));
  Wire.send(decToBcd(year));
  Wire.endTransmission();
}
void get_date()
{
  Wire.beginTransmission(104);
  Wire.send(3);//set register to 3 (day)
  Wire.endTransmission();
  Wire.requestFrom(104, 4); //get 5 bytes(day,date,month,year,control);
  day   = bcdToDec(Wire.receive());
  date  = bcdToDec(Wire.receive());
  month = bcdToDec(Wire.receive());
  year  = bcdToDec(Wire.receive());
}

void set_time()
{
   Wire.beginTransmission(104);
   Wire.send(0);
   Wire.send(decToBcd(seconds));
   Wire.send(decToBcd(minutes));
   Wire.send(decToBcd(hours));
   Wire.endTransmission();
}
void get_time()
{
  Wire.beginTransmission(104);
  Wire.send(0);//set register to 0
  Wire.endTransmission();
  Wire.requestFrom(104, 3);//get 3 bytes (seconds,minutes,hours);
  seconds = bcdToDec(Wire.receive() & 0x7f);
  minutes = bcdToDec(Wire.receive());
  hours = bcdToDec(Wire.receive() & 0x3f);
 
 


 
}
void setHour()
{
  hours++;
  if(hours > 23)
  {
   hours = 0;
   seconds = 0;
   minutes = 0;
  }
  set_time();
 
}
void setMinutes()
{
  minutes++;  
  if(minutes > 59)
  {
   minutes = 0;
   
  }
  seconds=0;
 
  set_time();
 
}
void check_buttons()
{
  hourButtonState = digitalRead(hourButtonPin);
  minButtonState = digitalRead(minButtonPin);
 
  if(hourButtonState == HIGH){
    setHour();
  }
 
  if(minButtonState == HIGH){
    setMinutes();
  }
}
///////////////////////////////////////////////////////////////////////

byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}
//////////////////////////////////////////////////////////////////////

Take a look at the setup method in particular
////////////////////////////////
  seconds = 00;
  minutes = 26;
  hours = 17;
  day = 7;
  date = 31;
  month = 5;
  year = 10;
  //initChrono();//just set the time once on your RTC
  ///////////////////////////////

When you upload your sketch for the first time you will want to update the variables to the correct time then, un-comment out the initChrono() to set the clock, upload your sketch and now should have a running clock.
Enjoy!

Be Sociable, Share!
Coding Color | 2009 All Rights Reserved.