Project showcase
Adjusting Dual Clock using DS3231 on 1.8" ST7735 Display

Adjusting Dual Clock using DS3231 on 1.8" ST7735 Display © GPL3+

This project explains how to use a dual Clock using DS3231 on 1.8" ST7735 Display

  • 5,479 views
  • 3 comments
  • 14 respects

Components and supplies

Apps and online services

About this project

This clock show you 2 clocks: local time and UTC/GMT time.

It has 3 buttons for MENU/OK, increase and decrease value for hours, minutes, day in week, year, month, day, difference between local time and UTC time (GMT time). Schematic is simple:

You can see the movie for understanding how this clock works:

Code

TFT_DualDigitalClock_RTC2.inoArduino
this is sketch for dual clock on SD7735 display
/*
 * original from http://www.instructables.com/id/Arduino-TFT-display-and-font-library/
 * some changes by Nicu FLORICA (niq_ro) from http://www.tehnic.go.ro
 * ver.1a- add flashing second signs
 * ver.1b - add temperature
 * ver.1c - add buttons for change the data and hours & eliminate RTC library
 * ver.2 - put dual clock (GMT/UTC and local time)
 * 
 An example digital clock using a TFT LCD screen to show the time.
 Demonstrates use of the font printing routines. (Time updates but date does not.)
 
 Now it use RTClib library bu Nicu FLORICA
 
 This examples uses the hardware SPI only. Non-hardware SPI
 is just too slow (~8 times slower!)
 
 Based on clock sketch by Gilchrist 6/2/2014 1.0
 Updated by Bodmer, using library from https://github.com/Bodmer/TFT_ST7735
   
A few colour codes:
 
code  color
0x0000  Black
0xFFFF  White
0xBDF7  Light Gray
0x7BEF  Dark Gray
0xF800  Red
0xFFE0  Yellow
0xFBE0  Orange
0x79E0  Brown
0x7E0 Green
0x7FF Cyan
0x1F  Blue
0xF81F  Pink
 */

#include <TFT_ST7735.h> // Graphics and font library for ST7735 driver chip
#include <SPI.h>
#include "EEPROM.h"

TFT_ST7735 tft = TFT_ST7735();  // Invoke library, pins defined in User_Setup.h
// see User_Setup.h: RST --> D7, CS --> D9, D/C --> D8, DIN --> D11, CLK --> D13


uint32_t targetTime = 0;       // for next 1 second timeout

byte omm = 99;
boolean initial = 1;
byte xcolon = 0;
byte xcolon2 = 0;
unsigned int colour = 0;

static uint8_t conv2d(const char* p) {
  uint8_t v = 0;
  if ('0' <= *p && *p <= '9')
    v = *p - '0';
  return 10 * v + *++p - '0';
}

#include <Wire.h>
// char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};  // english version
char daysOfTheWeek[7][12] = {"Duminica", "Luni", "Marti", "Miercuri", "Joi", "Vineri", "Sambata"};  // romanian version
byte hh, mm, ss;
byte yy, ll, dd, zz;

#define DS3231_I2C_ADDRESS 104
byte tMSB, tLSB;
float temp3231;
float temperatura, temperatura0;


#define meniu 2 
#define minus 3
#define plus 4
int nivel = 0;   // if is 0 - clock
                 // if is 1 - hour adjust
                 // if is 2 - minute adjust
                 // if is 3 - day of week adjust
                 // etc
byte jos = 10;
//byte hh1, mm1, zz1, dd1, ll1, yy1;   
int hh1, mm1, zz1, dd1, ll1, yy1;   
byte maxday;

int hh2;
int hh3;
byte hh4;
byte semn;

void setup(void) {
  tft.init();
  tft.setRotation(1);
  tft.fillScreen(ST7735_BLACK);

  tft.setTextColor(ST7735_YELLOW, ST7735_BLACK); // Note: the new fonts do not draw the background colour

pinMode(meniu, INPUT); 
pinMode(plus, INPUT); 
pinMode(minus, INPUT); 
digitalWrite(meniu, HIGH);  // put inputs in high state (when push is to ground -> low state)
digitalWrite(plus, HIGH);
digitalWrite(minus, HIGH);

 Serial.begin(9600);
 Wire.begin();
// setDS3231time(30, 42, 21, 4, 26, 11, 1);
  targetTime = millis() + 1000; 

hh4 = EEPROM.read(100);
semn = EEPROM.read(101);

if ((hh4 < 0) || (hh4 > 12)) hh4 = 2;
if ((semn < 0) || (semn > 1)) semn = 1;   // if 1 -> +, 0 -> -

if (semn == 1) hh3 = hh4;
if (semn == 0) hh3 = -hh4;

hh2 = hh - hh3;  
}

void loop() {

if (nivel == 0)
{
if (digitalRead(meniu) == LOW)
  {
  nivel = nivel+1;
  delay(500);
  hh1=hh;
//  tft.fillScreen(ST7735_BLACK);
 sterg();
  }
tft.setTextSize(1);
  if (targetTime < millis()) {
    targetTime = millis()+1000;

// readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,&year);
 readDS3231time(&ss, &mm, &hh, &zz, &dd, &ll,&yy);
hh2 = hh - hh3;
if (hh2 > 23) hh2 = hh2-24;
if (hh2 < 0) hh2 = 24+hh2;

//temperatura = get3231Temp();

    tft.setTextSize(1);
    if (ss==0 || initial) {

   for (int y=52+jos; y < 60+jos; y+=1) 
   {
   tft.drawFastHLine(0, y, tft.width(), ST7735_BLACK);
   }
      
      initial = 0;
      tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
      tft.setCursor (15, 52+jos);
      tft.print(daysOfTheWeek[zz]);
      tft.setCursor (90, 52+jos);

      if (dd <10) tft.print("0");
      tft.print(dd);
      tft.print(".");
      if (ll <10) tft.print("0");
      tft.print(ll);
      tft.print(".");
      tft.print(yy+2000);
/*
if (temperatura0 != temperatura) 
    {
  if (digitalRead(meniu) == LOW) 
  {
  nivel = nivel+1;
  delay(500);
  hh1=hh;
  tft.fillScreen(ST7735_BLACK);    
    }
   for (int y=85; y < tft.height(); y+=1) {
   tft.drawFastHLine(0, y, tft.width(), ST7735_BLACK);
   }
int temperatura1 = temperatura;
float temperatura2 = 100*(temperatura - temperatura1);
   tft.setTextSize(3);
   tft.setTextColor(TFT_YELLOW);
   tft.setCursor (30, 85+jos);
   if (temperatura <10) tft.print(" ");
 //  tft.print(temperatura);
   tft.print(temperatura1);
   tft.print(".");
   tft.setCursor (85, 90+jos);
   tft.setTextSize(2); 
   if (temperatura2 == 0) tft.print("00");  
   else tft.print(temperatura2,0);
   tft.setCursor (124, 85+jos);
   tft.setTextSize(3);      
   tft.print("C");
   tft.setTextSize(2);       
   tft.setCursor (110, 84+jos);
   tft.print("O");
   tft.setTextSize(1);      
   temperatura0 = temperatura;
    }
*/
     }

    // Update digital time
    byte xpos = 16;
    byte ypos = 0+jos;
    byte xpos2 = 16;
    byte ypos2 = 65+jos;

      tft.setTextColor(ST7735_BLUE, ST7735_BLACK);
      tft.setCursor (0, 0);
      tft.print("GMT");
/*
      tft.setCursor (0, ypos+2);
      tft.print("G");
      tft.setCursor (0, ypos+10);
      tft.print("M");
      tft.setCursor (0, ypos+18);
      tft.print("T");
      tft.setCursor (0, ypos+34);
*/
      if (hh3 == 0) tft.print("=");
      if (hh3 > 0) tft.print("+");
      tft.print(hh3);
  

      tft.setCursor (0, ypos2+2);
      tft.print("G");
      tft.setCursor (0, ypos2+10);
      tft.print("M");
      tft.setCursor (0, ypos2+18);
      tft.print("T");


    
    if (omm != mm) { // Only redraw every minute to minimise flicker
    if (digitalRead(meniu) == LOW) {
    nivel = nivel+1;
    tft.fillScreen(ST7735_BLACK);
    delay(500);
    tft.fillScreen(ST7735_BLACK);
    }
      // Uncomment ONE of the next 2 lines, using the ghost image demonstrates text overlay as time is drawn over it
      //tft.setTextColor(ST7735_RED, ST7735_BLACK);  // Leave a 7 segment ghost image, comment out next line!
      tft.setTextColor(ST7735_BLACK, ST7735_BLACK); // Set font colour to back to wipe image
      // Font 7 is to show a pseudo 7 segment display.
      // Font 7 only contains characters [space] 0 1 2 3 4 5 6 7 8 9 0 : .
      tft.drawString("88:88",xpos,ypos,7); // Overwrite the text to clear it
      tft.drawString("88:88",xpos2,ypos2,7); // Overwrite the text to clear it
      tft.setTextColor(ST7735_RED, ST7735_BLACK); // Red
      omm = mm;

      if (hh<10) xpos+= tft.drawChar('0',xpos,ypos,7);
      xpos+= tft.drawNumber(hh,xpos,ypos,7);
      xcolon=xpos;
      xpos+= tft.drawChar(':',xpos,ypos,7);
      if (mm<10) xpos+= tft.drawChar('0',xpos,ypos,7);
      tft.drawNumber(mm,xpos,ypos,7);

// second clock
      tft.setTextColor(ST7735_YELLOW, ST7735_BLACK); // Red
      if (hh2<10) xpos2+= tft.drawChar('0',xpos2,ypos2,7);
      xpos2+= tft.drawNumber(hh2,xpos2,ypos2,7);
      xcolon2=xpos2;
      xpos2+= tft.drawChar(':',xpos2,ypos2,7);
      if (mm<10) xpos2+= tft.drawChar('0',xpos2,ypos2,7);
      tft.drawNumber(mm,xpos2,ypos2,7);   
    }

//animated points for clocks
    if (ss%2) { // Flash the colon
      tft.setTextColor(0x39C4, ST7735_BLACK);
      xpos2+= tft.drawChar(':',xcolon2,ypos2,7);
      //tft.setTextColor(0x39C4, ST7735_BLACK);
      xpos+= tft.drawChar(':',xcolon,ypos,7);

     // tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);
    }
    else {
      tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);
      tft.drawChar(':',xcolon2,ypos2,7);
      tft.setTextColor(ST7735_RED, ST7735_BLACK);
      tft.drawChar(':',xcolon,ypos,7);
      
       }
    
  }
}  // end loop for nivel = 0 (just clock)

if (nivel == 1)   // change hours
{
   
if (digitalRead(meniu) == LOW)
  {
  nivel = nivel+1;
  delay(500);
  mm1 = mm;
 sterg();
  }    

   // Update digital time
    byte xpos = 6;
    byte ypos = 0+jos;
   
      tft.setTextColor(ST7735_BLACK, ST7735_BLACK); // Set font colour to back to wipe image
 //     tft.drawString("88:88",xpos,ypos,7); // Overwrite the text to clear it
      tft.drawString("88",xpos,ypos,7); // Overwrite the text to clear it
      tft.setTextColor(ST7735_RED, ST7735_BLACK); // Red
 delay(50);
      
      if (hh1<10) xpos+= tft.drawChar('0',xpos,ypos,7);
      xpos+= tft.drawNumber(hh1,xpos,ypos,7);

       tft.setTextColor(ST7735_RED, ST7735_BLACK); // Red
       
      xcolon=xpos;
      xpos+= tft.drawChar(':',xpos,ypos,7);
      if (mm<10) xpos+= tft.drawChar('0',xpos,ypos,7);
      tft.drawNumber(mm,xpos,ypos,7);
delay(50);
     
if (digitalRead(plus) == LOW)
    {
    hh1 = hh1+1;
    delay(150);
    }
if (digitalRead(minus) == LOW)
    {
    hh1 = hh1-1;
    delay(150);
    }    
if (hh1 > 23) hh1 = 0;
if (hh1 < 0) hh1 = 23;       
     
}  // end loop stare = 1 (change the hours)

if (nivel == 2)   // change minutes
{
if (digitalRead(meniu) == LOW)
  {
  delay(500);
  zz1 = zz;  // next step
  sterg();
  nivel = nivel+1;
  }    

   // Update digital time
    byte xpos = 6;
    byte ypos = 0+jos;

  //     tft.drawString("88:88",xpos,ypos,7); // Overwrite the text to clear it

      tft.setTextColor(ST7735_RED, ST7735_BLACK); // Red
      if (hh1<10) xpos+= tft.drawChar('0',xpos,ypos,7);
      xpos+= tft.drawNumber(hh1,xpos,ypos,7);
      xcolon=xpos;
      xpos+= tft.drawChar(':',xpos,ypos,7);
      
     tft.setTextColor(ST7735_BLACK, ST7735_BLACK); // Set font colour to back to wipe image
     tft.drawString("88",xpos,ypos,7); // Overwrite the text to clear it
 delay(50);
       tft.setTextColor(ST7735_RED, ST7735_BLACK); // Red
         
      if (mm1<10) xpos+= tft.drawChar('0',xpos,ypos,7);
      tft.drawNumber(mm1,xpos,ypos,7);
delay(50);
     
if (digitalRead(plus) == LOW)
    {
    mm1 = mm1+1;
    delay(150);
    }
if (digitalRead(minus) == LOW)
    {
    mm1 = mm1-1;
    delay(150);
    }    
if (mm1 > 59) mm1 = 0;
if (mm1 < 0) mm1 = 59;       
     
}  // end loop nivel = 2 (change the minutes)

if (nivel == 3)   // change day in week
{
if (digitalRead(meniu) == LOW)
  {
  nivel = nivel+1;
  delay(500);
  yy1 = yy;;  // next step
 sterg();
  }    

  for (int y=52+jos; y < 60+jos; y+=1) 
   {
   tft.drawFastHLine(0, y, tft.width(), ST7735_BLACK);
   }
   delay(50);
      tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
      tft.setCursor (15, 52+jos);
      tft.print(daysOfTheWeek[zz1]);
    delay(50);   
     
if (digitalRead(plus) == LOW)
    {
    zz1 = zz1+1;
    delay(150);
    }
if (digitalRead(minus) == LOW)
    {
    zz1 = zz1-1;
//    if (zz1 < 0) zz1 = 6;       
    delay(150);
    }    
if (zz1 > 6) zz1 = 0;
if (zz1 < 0) zz1 = 6;       
Serial.println(zz1);
     
}  // end loop stare = 3 (change the day of the week)


if (nivel == 4)   // change year
{
if (digitalRead(meniu) == LOW)
  {
  delay(500);
  ll1 = ll;;  // next step
  sterg();
  nivel = nivel+1;
  }    

  for (int y=52+jos; y < 60+jos; y+=1) 
   {
     tft.drawFastHLine(125, y, 35, ST7735_BLACK);
   }
   delay(50);
      tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
      tft.setCursor (90, 52+jos);
/*      
      if (ll <10) tft.print("0");
      tft.print(ll);
      tft.print("/");
      if (dd <10) tft.print("0");
      tft.print(dd);
      tft.print("/");
*/
      if (dd <10) tft.print("0");
      tft.print(dd);
      tft.print(".");
      if (ll <10) tft.print("0");
      tft.print(ll);
      tft.print(".");
      tft.print(yy1+2000);
    delay(50);   
     
if (digitalRead(plus) == LOW)
    {
    yy1 = yy1+1;
    delay(150);
    }
if (digitalRead(minus) == LOW)
    {
    yy1 = yy1-1;
    delay(150);
    }    
if (yy1 > 49) yy1 = 49;
if (yy1 < 16) yy1 = 16;       
     
}  // end loop stare = 4 (change the year)



if (nivel == 5)   // change mounth
{
if (digitalRead(meniu) == LOW)
  {
  delay(500);
  dd1 = dd;;  // next step
  sterg();
  nivel = nivel+1;
  }    

  for (int y=52+jos; y < 60+jos; y+=1) 
   {
//   tft.drawFastHLine(90, y, 14, ST7735_BLACK);
tft.drawFastHLine(106, y, 14, ST7735_BLACK);
   }
   delay(50);
 
      tft.setCursor (90, 52+jos);
      if (dd <10) tft.print("0");
      tft.print(dd);
      tft.print(".");
      if (ll1 <10) tft.print("0");
      tft.print(ll1);
      tft.print(".");
      tft.print(yy1+2000);    
    delay(50);   
     
if (digitalRead(plus) == LOW)
    {
    ll1 = ll1+1;
    delay(150);
    }
if (digitalRead(minus) == LOW)
    {
    ll1 = ll1-1;
    delay(150);
    }    
   
if (ll1 > 12) ll1 = 1;
if (ll1 < 1) ll1 = 12;       
     
}  // end loop stare = 5 (change the day as data)



if (nivel == 6)   // change day as data
{
if (digitalRead(meniu) == LOW)
  {
   delay(500);
   sterg();
   nivel = nivel+1;
  }    

  for (int y=52+jos; y < 60+jos; y+=1) 
   {
tft.drawFastHLine(90, y, 14, ST7735_BLACK);    
//   tft.drawFastHLine(106, y, 14, ST7735_BLACK);
   }
   delay(50);
 
      tft.setCursor (90, 52+jos);
  /*
      if (ll1 <10) tft.print("0");
      tft.print(ll1);
      tft.print("/");
      if (dd1 <10) tft.print("0");
      tft.print(dd1);
      tft.print("/");
  */
    if (dd1 <10) tft.print("0");
      tft.print(dd1);
      tft.print(".");
      if (ll1 <10) tft.print("0");
      tft.print(ll1);
      tft.print(".");    
      tft.print(yy1+2000);
      delay(50);   
     
if (digitalRead(plus) == LOW)
    {
    dd1 = dd1+1;
    delay(150);
    }
if (digitalRead(minus) == LOW)
    {
    dd1 = dd1-1;
    delay(150);
    }    
    
 // Dawn & Dusk controller. http://andydoz.blogspot.ro/2014_08_01_archive.html
 if (ll == 4 || ll == 5 || ll == 9 || ll == 11) { //30 days hath September, April June and November
    maxday = 30;
  }
  else {
  maxday = 31; //... all the others have 31
  }
  if (ll ==2 && yy % 4 ==0) { //... Except February alone, and that has 28 days clear, and 29 in a leap year.
    maxday = 29;
  }
  if (ll ==2 && ll % 4 !=0) {
    maxday = 28;
  }

if (dd1 > maxday) dd1 = 1;
if (dd1 < 1) dd1 = maxday;       
     
}  // end loop nivel = 6 (change the day as data)


if (nivel == 7)   // change hours
{
   
if (digitalRead(meniu) == LOW)
  {
  delay(500);
  sterg();
  nivel = nivel+1;
  }    

      tft.setCursor (90, 42+jos);
      tft.print("GMT");
      
  for (int y=52+jos; y < 60+jos; y+=1) 
   {
tft.drawFastHLine(90, y, 69, ST7735_BLACK);
   }
   delay(50);
 
      tft.setCursor (90, 52+jos);
      if (hh3 > 0) tft.print("+");
      tft.print(hh3);
      delay(50);   

     
if (digitalRead(plus) == LOW)
    {
    hh3 = hh3+1;
    delay(150);
    }
if (digitalRead(minus) == LOW)
    {
    hh3 = hh3-1;
    delay(150);
    }    
if (hh3 > 12) hh3 = 12;
if (hh3 < -12) hh3 = -12;       
     
}  // end loop stare = 7 (change the hours)



 if (nivel == 8)  // adjust the clock
 {
sterg();

// setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year);
setDS3231time(0, mm1, hh1, zz1, dd1, ll1, yy1);

if (hh3 > 0)
{
  hh4 = hh3;
  semn = 1;
}
if (hh3 <0)
{
  hh4 = -hh3;
  semn = 0;
}
if (hh3 == 0)
{
  hh4 = 0;
  semn = 1;
}

  EEPROM.write(100, hh4);
  EEPROM.write(101, semn);
  

 nivel = 9;
 } // end loop nivel = 8

 
 if (nivel >=9)  // readfy to return to main loop
 {nivel = 0;  
 omm = 99;
 temperatura0 = 0.0;
 initial = 1;
 }
}  // end main loop

// http://forum.arduino.cc/index.php?topic=398891.0
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte
                   dayOfMonth, byte month, byte year)
{
    // sets time and date data to DS3231
    Wire.beginTransmission(DS3231_I2C_ADDRESS);
    Wire.write(0); // set next input to start at the seconds register
    Wire.write(decToBcd(second)); // set seconds
    Wire.write(decToBcd(minute)); // set minutes
    Wire.write(decToBcd(hour)); // set hours
    Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
    Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
    Wire.write(decToBcd(month)); // set month
    Wire.write(decToBcd(year)); // set year (0 to 99)
    Wire.endTransmission();
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
    return ( (val / 16 * 10) + (val % 16) );
}

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
    return ( (val / 10 * 16) + (val % 10) );
}

void readDS3231time(byte *second,
                    byte *minute,
                    byte *hour,
                    byte *dayOfWeek,
                    byte *dayOfMonth,
                    byte *month,
                    byte *year)
{
    Wire.beginTransmission(DS3231_I2C_ADDRESS);
    Wire.write(0); // set DS3231 register pointer to 00h
    Wire.endTransmission();
    Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
    // request seven bytes of data from DS3231 starting from register 00h
    *second = bcdToDec(Wire.read() & 0x7f);
    *minute = bcdToDec(Wire.read());
    *hour = bcdToDec(Wire.read() & 0x3f);
    *dayOfWeek = bcdToDec(Wire.read());
    *dayOfMonth = bcdToDec(Wire.read());
    *month = bcdToDec(Wire.read());
    *year = bcdToDec(Wire.read());
}

void sterg()
   {for (int y=0; y < 127; y+=1) 
   {
   tft.drawFastHLine(0, y, tft.width(), ST7735_BLACK);
   }
   }

Schematics

clock schematic
how you cconnect all pieces
Pjw2imqbqne8csx3bn7v

Comments

Similar projects you might like

Talking Clock 2 - New Version (Bilingual: EN-PT)

Project tutorial by LAGSILVA

  • 7,347 views
  • 19 comments
  • 33 respects

Weather Clock

Project showcase by Tittiamo

  • 7,665 views
  • 7 comments
  • 22 respects

Sensal - All Senses Alarm Clock

Project in progress by Leonid Piliptsevich

  • 8,860 views
  • 2 comments
  • 28 respects

Digital & Binary Clock In 8 Digits x 7 Segments LED Display

Project showcase by LAGSILVA

  • 1,827 views
  • 2 comments
  • 9 respects

Simple Arduino Digital Clock Without RTC

Project in progress by Annlee Fores

  • 96,437 views
  • 23 comments
  • 81 respects

Clock Set Date Time

Project tutorial by Tittiamo

  • 34,198 views
  • 26 comments
  • 43 respects
Add projectSign up / Login