Add I2C LCD Display to my Digital Clock Using a DS1302 Project

Hello everyone,
I need help on adding a LCD I2C Display to my project and display only the Time. So here is the coding without adding a LCD I2C code yet.

Components that i'm using:-

  • DS1302 Real Time Clock Module RTC.

  • 2x16 LCD I2C

  • Arduino UNO

    Connections:

    • CLK/SCLK --> 5
    • DAT/IO --> 4
    • RST/CE --> 2
    • VCC --> 2.0v - 5.5v
    • GND --> GND
#include <ThreeWire.h>
#include <RtcDS1302.h>

const int IO = 4;    // DAT
const int SCLK = 5;  // CLK
const int CE = 2;    // RST

ThreeWire myWire(4, 5, 2);  // IO, SCLK, CE
RtcDS1302<ThreeWire> Rtc(myWire);

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

  Serial.print("compiled: ");
  Serial.print(__DATE__);
  Serial.println(__TIME__);

  Rtc.Begin();

  RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
  printDateTime(compiled);
  Serial.println();

  if (!Rtc.IsDateTimeValid()) {
    // Common Causes:
    //    1) first time you ran and the device wasn't running yet
    //    2) the battery on the device is low or even missing

    Serial.println("RTC lost confidence in the DateTime!");
    Rtc.SetDateTime(compiled);
  }

  if (Rtc.GetIsWriteProtected()) {
    Serial.println("RTC was write protected, enabling writing now");
    Rtc.SetIsWriteProtected(false);
  }

  if (!Rtc.GetIsRunning()) {
    Serial.println("RTC was not actively running, starting now");
    Rtc.SetIsRunning(true);
  }

  RtcDateTime now = Rtc.GetDateTime();
  if (now < compiled) {
    Serial.println("RTC is older than compile time!  (Updating DateTime)");
    Rtc.SetDateTime(compiled);
  } else if (now > compiled) {
    Serial.println("RTC is newer than compile time. (this is expected)");
  } else if (now == compiled) {
    Serial.println("RTC is the same as compile time! (not expected but all is fine)");
  }
}

void loop() {
  RtcDateTime now = Rtc.GetDateTime();

  printDateTime(now);
  Serial.println();

  if (!now.IsValid()) {
    // Common Causes:
    //    1) the battery on the device is low or even missing and the power line was disconnected
    Serial.println("RTC lost confidence in the DateTime!");
  }

  delay(5000);  // five seconds
}

#define countof(a) (sizeof(a) / sizeof(a[0]))

void printDateTime(const RtcDateTime& dt) {
  char datestring[20];

  snprintf_P(datestring,
             countof(datestring),
             PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
             dt.Month(),
             dt.Day(),
             dt.Year(),
             dt.Hour(),
             dt.Minute(),
             dt.Second());
  Serial.print(datestring);
}

Here's the pic of the setup:-

follow the forum rules: edit your post and put entire code between CODE tags.
after that, place pictures of your setup, diagram, schematic. more info is better then less.
say when done, i will take a look

2 Likes
  1. Provide Clear Documentation: Since we can’t see your project, share an annotated schematic (best) or a clear drawing of your setup. Pictures are welcome, but avoid using Fritzing diagrams as they are wiring diagrams, not schematics, and are not ideal for troubleshooting.
  2. Include Technical Details: If there is specific hardware involved, include links to technical information. There are often many versions of similar components, so precise details are essential.
  3. Reference Resources: For additional help, check out useful links and tutorials: Useful Links on Arduino Forum.
  4. Read and follow the forum guidelines When posting your code and schematic, please review the forum guidelines and use code tags to ensure clarity.
1 Like

Better to use DS3231........

1 Like

TQ for your time sir. I already edit my post.

I edited my answer, note the bold print. Your photo is not clear but it appears things are not connected correctly, you are using to many pins on the Arduino.

Put it on a proper schematic No idea of which end is which.
What did not work, the display is lit up. Post the links to the technical information on the hardware I do not have anything that looks like what I assume is the clock module.

Your screen shot is useless, best post it as requested by @kolaha

#include <ThreeWire.h>
#include <RtcDS1302.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // address may be 0x3F

// determine the size of an array dynamically
#define countof(a) (sizeof(a) / sizeof(a[0]))

// RtcDateTime uses Y2K as OriginYear, while time_t uses Epoch 1970 as OriginYear.
// This is the difference between years 2000 and 1970 in seconds.
#define   UNIX_OFFSET   946684800

const int RST_PIN   = 2;  // Chip Enable
const int IO_PIN   = 4;   // Input/Output
const int SCLK_PIN = 5;   // Serial Clock

ThreeWire myWire(IO_PIN, SCLK_PIN, RST_PIN);
RtcDS1302<ThreeWire> Rtc(myWire);

// 30 chars is max, RAM is 31 Bytes, last char is null.
// Will be used to store the next alarm date+time.
const char data[] = "";

//Is Eastern Daylight Savings Time?
bool isEDT = false;

// Set the current date and time for RTC based on compile time.
// Calculate the next alarm date.
void setup ()
{
  Serial.begin(9600);
  lcd.init();                      // initialize the lcd
  lcd.init();
  // Print a message to the LCD.
  lcd.backlight();

  //__DATE__ is a preprocessor macro that expands to current date (at compile time)
  // in the form mmm dd yyyy (e.g. "Jan 14 2012"), as a string.
  const char* nowDate = __DATE__;
  const char* nowTime = __TIME__;

  Rtc.Begin();
  runRtcChecks();

  // Set the date and time.  This only needs to be done once if there is a battery backup
  //RtcDateTime compiled = RtcDateTime(nowDate, nowTime);
  //Rtc.SetDateTime(compiled);

  RtcDateTime now = Rtc.GetDateTime();

  // Eastern Time Zone (Toronto, New York, Detroit)
  // Daylight Saving Time is from Second Sunday in March after 2AM
  // until First Sunday in November until 2AM
  isEDT = isDaylightSavingTime(now);

  storeAlarmInMemory(now);
}

// Print current time every 5 seconds.
// If current time passed the alarm time, execute Alarm and set the next alarm's date+time.
void loop ()
{
  RtcDateTime now = Rtc.GetDateTime();
  RtcDateTime nextAlarm = readAlarmFromMemory();

  if (!now.IsValid())
  {
    // Common Causes:
    //    1) the battery on the device is low or even missing and the power line was disconnected
    Serial.println(F("RTC lost confidence in the DateTime!"));
  }
  else
  {
    // Adjust for DaylightSavingTime/Standard Time, Eastern Time Zone
    if (now.Month() == 3 && !isEDT && isDaylightSavingTime(now))
    {
      // from EST to EDT (+ 1 hour)
      now += 3600;
      Rtc.SetDateTime(now);

      nextAlarm += 3600;
      storeAlarmInMemory(nextAlarm);

      isEDT = true;
    }
    else if (now.Month() == 11 && isEDT && !isDaylightSavingTime(now))
    {
      // from EDT to EST (- 1 hour)
      now -= 3600;
      Rtc.SetDateTime(now);

      nextAlarm -= 3600;
      storeAlarmInMemory(nextAlarm);

      isEDT = false;
    }

    // debug

    lcd.setCursor(0, 1);
    // execute alarm
    if (now >= nextAlarm) {
      Serial.println("!!!!  ALARM  !!!");
      storeAlarmInMemory(nextAlarm);
      lcd.print("!!!!  ALARM  !!!");
    } else {
      Serial.print(F("Next Alarm: "));
      printDateTime(nextAlarm);
    }

    // debug
    Serial.print(F("Time now: "));
    lcd.setCursor(0, 0);
    printDateTime(now);
  }

  delay(5000);
}

// Print date+time in a 12-hour AM/PM format.
void printDateTime(const RtcDateTime& dt)
{
  char datestring[30];

  bool isPM = (dt.Hour() > 12);
  // read the format string from the Flash memory
  snprintf_P(datestring,
             countof(datestring),
             // PSTR macro = pointer to a string
             // creating a PROGMEM array and returning its address
             PSTR("%02u %s %04u %02u:%02u:%02u %s %s %s"),
             dt.Day(),
             monthShortString(dt.Month()),
             dt.Year(),
             //Sutract 12, Exception: 12 AM = 00 in 24 hrs
             isPM ? dt.Hour() - 12 : (dt.Hour() == 0 ? 12 : dt.Hour()),
             dt.Minute(),
             dt.Second(),
             isPM ? "PM" : "AM",
             "+",
             isEDT ? "EDT" : "EST"); // Eastern Daylight Time/Eastern Standard Time
  Serial.println(datestring);

  snprintf_P(datestring,
             countof(datestring),
             // PSTR macro = pointer to a string
             // creating a PROGMEM array and returning its address
             PSTR("%02u%s%02u%s%02u:%02u:%02u"),
             dt.Day(),
             monthShortString(dt.Month()),
             dt.Year() % 100,
             isPM ? "P" : "A",
             //Sutract 12, Exception: 12 AM = 00 in 24 hrs
             isPM ? dt.Hour() - 12 : (dt.Hour() == 0 ? 12 : dt.Hour()),
             dt.Minute(),
             dt.Second()
            ); // Eastern Daylight Time/Eastern Standard Time
  lcd.print(datestring);
}

// Initialize chip by turning off write protection and clearing the clock halt flag.
void runRtcChecks()
{
  if (Rtc.GetIsWriteProtected())
  {
    Serial.println("RTC was write protected, enabling writing now");
    Rtc.SetIsWriteProtected(false);
  }

  if (!Rtc.GetIsRunning())
  {
    Serial.println("RTC was not actively running, starting now");
    Rtc.SetIsRunning(true);
  }
}

// Calculate the next alarm's date and store in memory.
void storeAlarmInMemory(RtcDateTime lastAlarm)
{
  // Calculate next alarm date
  // by rounding off to the last minute
  RtcDateTime nextAlarm = RtcDateTime(lastAlarm.Year(), lastAlarm.Month(), lastAlarm.Day(), lastAlarm.Hour(), lastAlarm.Minute(), 0);
  // then adding +1 min
  nextAlarm = RtcDateTime(nextAlarm.Epoch64Time() - UNIX_OFFSET + 60);
  char datestring[28];

  // read the format string from the Flash memory
  snprintf_P(datestring,
             countof(datestring),
             // PSTR macro = pointer to a string
             // creating a PROGMEM array and returning its address
             PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
             nextAlarm.Day(),
             nextAlarm.Month(),
             nextAlarm.Year(),
             nextAlarm.Hour(),
             nextAlarm.Minute(),
             nextAlarm.Second());

  // Store next alarm in memory on the RTC
  uint8_t _count = sizeof(datestring);
  uint8_t written = Rtc.SetMemory((const uint8_t*)datestring, _count); // this includes a null terminator for the string
  if (written != _count)
  {
    Serial.print("something didn't match, count = ");
    Serial.print(_count, DEC);
    Serial.print(", written = ");
    Serial.print(written, DEC);
    Serial.println();
  }
}

RtcDateTime readAlarmFromMemory() {
  // read data
  uint8_t buff[31];
  char buffy[31];

  const uint8_t count = sizeof(buff);
  // get our data
  uint8_t gotten = Rtc.GetMemory(buff, count);

  if (gotten != count)
  {
    Serial.print("something didn't match, count = ");
    Serial.print(count, DEC);
    Serial.print(", gotten = ");
    Serial.print(gotten, DEC);
    Serial.println();
  }

  // print the string, but terminate if we get a null
  for (uint8_t ch = 0; ch < gotten && buff[ch]; ch++)
  {
    buffy[ch] = buff[ch];
  }

  uint16_t day, month, year, hour, minute, second;
  sscanf(buffy, "%02u/%02u/%04u %02u:%02u:%02u",
         &day,
         &month,
         &year,
         &hour,
         &minute,
         &second);

  RtcDateTime nextAlarm = RtcDateTime(year, month, day, hour, minute, second);
  return nextAlarm;
}

const char* monthShortString(uint8_t mth) {

  // Initialize array of pointer
  const char *months[13] = { "Nil", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
  return months[mth];
}

// Adapted from https://github.com/SensorsIot/NTPtimeESP/blob/master/NTPtimeESP.cpp
boolean isDaylightSavingTime(RtcDateTime _tempDateTime) {
  // DST begins on second Sunday of March and ends on first Sunday of November.
  // Time change occurs at 2AM locally
  if (_tempDateTime.Month() < 3 || _tempDateTime.Month() > 11) return false;  //January, february, and december are out.
  if (_tempDateTime.Month() > 3 && _tempDateTime.Month() < 11) return true;   //April to October are in
  int previousSunday = _tempDateTime.Day() - (_tempDateTime.DayOfWeek());

  // -------------------- March ---------------------------------------
  //In march, we are DST if our previous Sunday was = to or after the 8th.
  if (_tempDateTime.Month() == 3 ) {  // in march, if previous Sunday is after the 8th, is DST
    // unless Sunday and hour < 2am
    if ( previousSunday >= 8 ) {
      // return true if day > 14 or (dow == 0 and hour >= 2)
      return ((_tempDateTime.Day() > 14) ||
              ((_tempDateTime.DayOfWeek() == 0 && _tempDateTime.Hour() >= 2) || _tempDateTime.DayOfWeek() > 0));
    }
    else
    {
      // previousSunday has to be < 8 to get here
      return false;
    }
  }

  // ------------------------------- November -------------------------------
  // gets here only if month = November
  //In november we must be before the first Sunday to be dst.
  //That means the previous Sunday must be before the 2nd.
  if (previousSunday < 1)
  {
    // is not true for Sunday after 2am or any day after 1st Sunday any time
    return ((_tempDateTime.DayOfWeek() == 0 && _tempDateTime.Hour() < 2) || (_tempDateTime.DayOfWeek() > 0));
  }
  else
  {
    // return false unless after first wk and dow = Sunday and hour < 2
    return (_tempDateTime.Day() < 8 && _tempDateTime.DayOfWeek() == 0 && _tempDateTime.Hour() < 2);
  }
}

as you already know, DS3231 is better because it is a bit more precise and uses I2C, so you can connect an I2C LCD to the same pins, sometimes directly on the RTC module.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.