Real Time Clock module to display time and date on LCD

Hi guys,

I have a RTC module similar to the one here: SparkFun Real Time Clock Module - BOB-12708 - SparkFun Electronics

I just need to program the arduino to display the time and date on a LCD display.
Have seen and tried out a few examples on the forum for the RTC module but I don't know why I am not able to get them working properly.

Pls assist. Thanks

Read this before posting a programming question

... I don't know why I am not able to get them working properly.

I don't know either. You haven't posted your code. You haven't said what happens, except that it doesn't "work properly".

Often these modules need to be enabled to start keeping time. There is a bit that needs to be set to do this. If you go to the link in my signature below I have a library with example code that allows you to look at what is happening in the ds1307.

Are you sure your connections are correct?
If you want others to help, though, you really need to be more clear about what errors you are getting.

Well, this is the code below.

And the error is that neither the time nor date gets displayed..

Is there any simple code available to test that my RTC module is actually working?

#include <Wire.h>
#define DS1307_I2C_ADDRESS 0x68
#include <LiquidCrystal.h> // we need this library for the LCD commands
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers
void setDateDs1307(byte second, // 0-59
byte minute, // 0-59
byte hour, // 1-23
byte dayOfWeek, // 1-7
byte dayOfMonth, // 1-28/29/30/31
byte month, // 1-12
byte year) // 0-99
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(second)); // 0 to bit 7 starts the clock
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.write(0x10); // sends 0x10 (hex) 00010000 (binary) to control register - turns on square wave
Wire.endTransmission();
}
// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
// Reset the register pointer
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
// A few of these need masks because certain bits are control bits
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f); // Need to change this if 12 hour am/pm
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}
void setup()
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
Wire.begin();
Serial.begin(9600);
// Change these values to what you want to set your clock to.
// You probably only want to set your clock once and then remove
// the setDateDs1307 call.
second = 0;
minute = 46;
hour = 2;
dayOfWeek = 4;
dayOfMonth = 7;
month = 2;
year = 13;
// setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
lcd.begin(20, 4); // tells Arduino the LCD dimensions
lcd.setCursor(0,0);
lcd.print("test"); // print text and move cursor to start of next line
lcd.setCursor(0,1);
lcd.print(" test ");
delay(5000);
lcd.clear(); // clear LCD screen
}
void loop()
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
lcd.clear(); // clear LCD screen
lcd.setCursor(0,0);
lcd.print(" ");
lcd.print(hour, DEC);
lcd.print(":");
if (minute<10)
{
lcd.print("0");
}
lcd.print(minute, DEC);
lcd.print(":");
if (second<10)
{
lcd.print("0");
}
lcd.print(second, DEC);
lcd.setCursor(0,1);
lcd.print(" ");
switch(dayOfWeek){
case 1:
lcd.print("Sun");
break;
case 2:
lcd.print("Mon");
break;
case 3:
lcd.print("Tue");
break;
case 4:
lcd.print("Wed");
break;
case 5:
lcd.print("Thu");
break;
case 6:
lcd.print("Fri");
break;
case 7:
lcd.print("Sat");
break;
}
lcd.print(" ");
lcd.print(dayOfMonth, DEC);
lcd.print("/");
lcd.print(month, DEC);
lcd.print("/20");
lcd.print(year, DEC);
delay(1000);
}

Have you looked at my library as suggested above for sample code and a working example?

Yup I have tried it out but when I upload it, the whole LCD display shows random running characters

The only change I made to your code is to change the LCD pins and and the no. of rows and columns:

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

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

void setup()
{
  lcd.begin(20,4);
  lcd.clear();
  lcd.noCursor();
}

void p2dig(uint8_t v)
// print 2 digits leading zero
{
  if (v < 10) lcd.print("0");
  lcd.print(v);
}

char *dow2String(uint8_t code)
{
  char *str[] = {" Sun", " Mon", " Tue", " Wed", " Thu", " Fri", " Sat"};
  return(str[code-1]);
}

void printTime()
{
  lcd.setCursor(0,0);
  lcd.print(RTC.yyyy);
  lcd.print("-");
  p2dig(RTC.mm);
  lcd.print("-");
  p2dig(RTC.dd);
  
  lcd.setCursor(0,1);
  p2dig(RTC.h);
  lcd.print(":");
  p2dig(RTC.m);
  lcd.print(":");
  p2dig(RTC.s);
  if (RTC.Status(DS1307_12H) == DS1307_ON)
    lcd.print(RTC.pm ? " pm" : " am");
  lcd.print(dow2String(RTC.dow));
}

void loop()
{
  RTC.ReadTime();
  printTime(); 
  delay(100);
}
char *dow2String(uint8_t code)
{
  char *str[] = {" Sun", " Mon", " Tue", " Wed", " Thu", " Fri", " Sat"};
  return(str[code-1]);
}

What is the pointer pointing to when the array goes out of scope. It points to some place on the heap where some other data now lives. In other words, garbage. So, you get garbage on the LCD. No real surprise there.

The day name string should be global. Then, there is no need for this function.

can some tell me how did we assigned this address:#define DS1307_I2C_ADDRESS 0x68 . how we get this I2c address

kurtselva:
Well, this is the code below.

And the error is that neither the time nor date gets displayed..

Is there any simple code available to test that my RTC module is actually working?

#include <Wire.h>

#define DS1307_I2C_ADDRESS 0x68
#include <LiquidCrystal.h> // we need this library for the LCD commands
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/1016) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return ( (val/16
10) + (val%16) );
}
// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers
void setDateDs1307(byte second, // 0-59
byte minute, // 0-59
byte hour, // 1-23
byte dayOfWeek, // 1-7
byte dayOfMonth, // 1-28/29/30/31
byte month, // 1-12
byte year) // 0-99
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(second)); // 0 to bit 7 starts the clock
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.write(0x10); // sends 0x10 (hex) 00010000 (binary) to control register - turns on square wave
Wire.endTransmission();
}
// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
// Reset the register pointer
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
// A few of these need masks because certain bits are control bits
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f); // Need to change this if 12 hour am/pm
*dayOfWeek = bcdToDec(Wire.read());
*dayOfMonth = bcdToDec(Wire.read());
*month = bcdToDec(Wire.read());
*year = bcdToDec(Wire.read());
}
void setup()
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
Wire.begin();
Serial.begin(9600);
// Change these values to what you want to set your clock to.
// You probably only want to set your clock once and then remove
// the setDateDs1307 call.
second = 0;
minute = 46;
hour = 2;
dayOfWeek = 4;
dayOfMonth = 7;
month = 2;
year = 13;
// setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
lcd.begin(20, 4); // tells Arduino the LCD dimensions
lcd.setCursor(0,0);
lcd.print("test"); // print text and move cursor to start of next line
lcd.setCursor(0,1);
lcd.print(" test ");
delay(5000);
lcd.clear(); // clear LCD screen
}
void loop()
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
lcd.clear(); // clear LCD screen
lcd.setCursor(0,0);
lcd.print(" ");
lcd.print(hour, DEC);
lcd.print(":");
if (minute<10)
{
lcd.print("0");
}
lcd.print(minute, DEC);
lcd.print(":");
if (second<10)
{
lcd.print("0");
}
lcd.print(second, DEC);
lcd.setCursor(0,1);
lcd.print(" ");
switch(dayOfWeek){
case 1:
lcd.print("Sun");
break;
case 2:
lcd.print("Mon");
break;
case 3:
lcd.print("Tue");
break;
case 4:
lcd.print("Wed");
break;
case 5:
lcd.print("Thu");
break;
case 6:
lcd.print("Fri");
break;
case 7:
lcd.print("Sat");
break;
}
lcd.print(" ");
lcd.print(dayOfMonth, DEC);
lcd.print("/");
lcd.print(month, DEC);
lcd.print("/20");
lcd.print(year, DEC);
delay(1000);
}

can some tell me how did we assigned this address:#define DS1307_I2C_ADDRESS 0x68 . how we get this I2c address

This is the address the manufacturer of the 1307 has been given for the chip.

Edit: Examples here Adafruit's I2C Address Reference

I did something similar.

In this post you can read my full sketch.

Hope it helps

marco_c:
Have you looked at my library as suggested above for sample code and a working example?

Hi..

marco_c:
Often these modules need to be enabled to start keeping time. There is a bit that needs to be set to do this. If you go to the link in my signature below I have a library with example code that allows you to look at what is happening in the ds1307.

Are you sure your connections are correct?
If you want others to help, though, you really need to be more clear about what errors you are getting.

Hi....Macro_c How to enable nd ds1307
n Pls tell me what connection to be made ..to d Ardino pins no n d Modules Pls
Have already uploaded ur code.... in my board...n its scrolling some msg Like "36%RH Wednesday 29 Feb 2016 "

The_Undertaker:
Hi..
Hi....Macro_c How to enable nd ds1307
n Pls tell me what connection to be made ..to d Ardino pins no n d Modules Pls
Have already uploaded ur code.... in my board...n its scrolling some msg Like "36%RH Wednesday 29 Feb 2016 "

i cnt evn ndr stand tht.

kurtselva:
I have a RTC module similar to the one here: SparkFun Real Time Clock Module - BOB-12708 - SparkFun Electronics
I just need to program the arduino to display the time and date on a LCD display.

Write a sketch to initialize and read your RTC, and print the results to Serial.
Write a sketch to print numbers on your LCD.

You will find that you have difficulty with one of these two tasks. Or both. Work on making each of these two things happen. You will then know enough to make the combined thing go.

Here is my "standard" sketch for reading the time from an RTC and showing it on the Serial monitor:

#include <Wire.h>

byte ss=0, mi=0, hh=0, wd=6, dd=1, mo=1, yy=0;
 
void setup()
{
  Wire.begin();
  Serial.begin(9600);
 
  // clear /EOSC bit
  // Sometimes necessary to ensure that the clock
  // keeps running on just battery power. Once set,
  // it shouldn't need to be reset but it's a good
  // idea to make sure.
//  Wire.beginTransmission(0x68); // address DS3231
//  Wire.write(0x0E); // select register
//  Wire.write(0b00011100); // write register bitmap, bit 7 is /EOSC
//  Wire.endTransmission();
}
 
void loop()
{
  // ask RTC for the time
  // send request to receive data starting at register 0
  Wire.beginTransmission(0x68); // 0x68 is DS3231 device address
  Wire.write((byte)0); // start at register 0
  Wire.endTransmission();
  Wire.requestFrom(0x68, 7); // request seven bytes (ss, mi, hh, wd, dd, mo, yy)
  // check for a reply from the RTC, and use it if we can
  if (Wire.available() >= 7) { 
    // if we're here, we got a reply and it is long enough
    // so now we read the time
    ss = bcd2bin(Wire.read()); // get seconds
    mi = bcd2bin(Wire.read()); // get minutes
    hh = bcd2bin(Wire.read()); // get hours
    wd = bcd2bin(Wire.read());
    dd = bcd2bin(Wire.read());
    mo = bcd2bin(Wire.read());
    yy = bcd2bin(Wire.read());
    // show that we successfully got the time
    Serial.print("Got the time: ");
    printTime();
  }
  else {
    // if we're here, that means we were unable to read the time
    Serial.println("Unable to read time from RTC"); 
  }
  delay(500);
}

byte bcd2bin(byte x) {
  // converts from binary-coded decimal to a "regular" binary number
  return ((((x >> 4) & 0xF) * 10) + (x & 0xF)) ;
}

void printTime() {
  // just like it says on the tin
  Serial.print ("\'");
  if (yy<10) Serial.print("0"); Serial.print(yy,DEC); Serial.print("-");
  if (mo<10) Serial.print("0"); Serial.print(mo,DEC); Serial.print("-");
  if (dd<10) Serial.print("0"); Serial.print(dd,DEC); Serial.print("(");
  switch (wd) {
    case 1: Serial.print("Mon"); break;
    case 2: Serial.print("Tue"); break; 
    case 3: Serial.print("Wed"); break; 
    case 4: Serial.print("Thu"); break; 
    case 5: Serial.print("Fri"); break; 
    case 6: Serial.print("Sat"); break; 
    case 7: Serial.print("Sun"); break;
    default: Serial.print("Bad");  
  }
  Serial.print(") ");
  if (hh<10) Serial.print("0"); Serial.print(hh,DEC); Serial.print(":");
  if (mi<10) Serial.print("0"); Serial.print(mi,DEC); Serial.print(":");
  if (ss<10) Serial.print("0"); Serial.print(ss,DEC); Serial.println("");
}