Hackster is hosting Hackster Holidays, Ep. 7: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Friday!Stream Hackster Holidays, Ep. 7 on Friday!
WayneChan
Published

High Precision Digital Clock

The Arduino high-precision digital clock is a multi-module DIY combination that uses the most complete Uno starter kit.

BeginnerFull instructions provided672
High Precision Digital Clock

Things used in this project

Story

Read more

Code

Arduino Digital Clock

C/C++
Arduino IDE
#include <Wire.h>
#include <DS3231.h>
#include <LiquidCrystal.h>
 
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd( 7, 8, 9, 10, 11, 12);


DS3231 Clock;
bool h12, PM, Century=false;
byte year, month, date, DoW, hour, minute, second;
bool ADy, A12h, Apm;
byte A1Day, A1Hour, A1Minute, A1Second, A1Bits;

  

const byte Set=2;  // buttons
const byte Adj=3;
byte button[2] = {Set, Adj};


void setup()
{
  Serial.begin(9600);
  Wire.begin();
lcd.begin(16,2); 
 pinMode(Set,INPUT);  // Button pins
  pinMode(Adj,INPUT);
 pinMode(4,OUTPUT);  // Buzzer stitch
}


/* ~~~~~~~~~~~~~~~~~~~~~~Display Time~~~~~~~~~~~~~~~~~~~~~~~ */
void Pritime()
{
  int second,minute,hour,date,month,year,dow,temperature; 
  second=Clock.getSecond();
  minute=Clock.getMinute();
  hour=Clock.getHour(h12, PM);
  date=Clock.getDate();
  month=Clock.getMonth(Century);
  year=Clock.getYear();
  dow=Clock.getDoW();

  temperature=Clock.getTemperature();

  lcd.setCursor(0, 0);
  lcd.print("20");  // Show the 20th century
    if (year>=10)  
      {
      lcd.print(year,DEC);
      }
      else
      {
      lcd.print("0");
      lcd.print(year,DEC);
      }
       
      lcd.print("-");
   

  lcd.setCursor(5, 0);
    if (month>=10)  
      {
      lcd.print(month,DEC);
      }
      else
      {
      lcd.print("0");
      lcd.print(month,DEC);
      }
      lcd.print("-");
      //lcd.write(sel_char[8]);
  

  lcd.setCursor(8, 0);
    if (date>=10)  
      {
      lcd.print(date,DEC);
      }
      else
      {
      lcd.print("0");
      lcd.print(date,DEC);
      }
    
    // lcd.write(bell_day[8]);
        
  lcd.setCursor(12, 0);
    switch (dow)  // shows the week
      {
      case 1:  //When dow equals 1, execute the following statement
        lcd.print("Mon");
        break;
      case 2:  //When dow equals 2, execute the following statement
        lcd.print("Tue");
        break;
      case 3:
        lcd.print("Wed");
        break;
      case 4:
        lcd.print("Thu");
        break;
      case 5:
        lcd.print("Fri");
        break;
      case 6:
        lcd.print("Sat");
        break;
      case 7:
        lcd.print("Sun");
        break;
      }

  lcd.setCursor(0, 1); //Move the cursor to line 2
    if (hour>=10)  // Shows hours
      {
      lcd.print(hour,DEC);
      }
      else
      {
      lcd.print("0");
      lcd.print(hour,DEC);
      }
  lcd.print(':');

 lcd.setCursor(3, 1);
    if (minute>=10)  
      {
      lcd.print(minute,DEC);
      }
      else
      {
      lcd.print("0");
      lcd.print(minute,DEC);
      }
  lcd.print(':');

  lcd.setCursor(6, 1);
    if (second>=10)  
      {
      lcd.print(second,DEC);
      }
      else
      {
      lcd.print("0");
      lcd.print(second,DEC);
      }

  lcd.setCursor(11, 1);
  lcd.print(temperature);  // display temperature
  lcd.write(0xdf);  // Display temperature unit
  lcd.print("C");
}


/* ~~~~~~~~~~~~~~~~~~~~~~ The time colon flashes ~~~~~~~~~~~~~~~~~~~~~~~ */
void Tictime()
{
  lcd.setCursor(2, 1); 
  lcd.print(' ');
  lcd.setCursor(5, 1); 
  lcd.print(' ');
}

/* ~~~~~~~~~~~~~~~~~~~~~~ Display setting time ~~~~~~~~~~~~~~~~~~~~~~~ */
void PritimeSet(byte syear,byte smonth,byte sdate,byte sdow,byte shour,byte sminute,byte ssecond)
{
  lcd.setCursor(0, 0);
  lcd.print("20");  
    if (syear>=10)  
      {
      lcd.print(syear,DEC);
      }
      else
      {
      lcd.print("0");
      lcd.print(syear,DEC);
      }
  lcd.print('-');

  lcd.setCursor(5, 0);
    if (smonth>=10)  
      {
      lcd.print(smonth,DEC);
      }
      else
      {
      lcd.print("0");
      lcd.print(smonth,DEC);
      }
  lcd.print('-');

  lcd.setCursor(8, 0);
    if (sdate>=10)  
      {
      lcd.print(sdate,DEC);
      }
      else
      {
      lcd.print("0");
      lcd.print(sdate,DEC);
      }

  lcd.setCursor(12, 0);
    switch (sdow)  
      {
      case 1:  
        lcd.print("Mon");
        break;
      case 2:  
        lcd.print("Tue");
        break;
      case 3:
        lcd.print("Wed");
        break;
      case 4:
        lcd.print("Thu");
        break;
      case 5:
        lcd.print("Fri");
        break;
      case 6:
        lcd.print("Sat");
        break;
      case 7:
        lcd.print("Sun");
        break;
      }

  lcd.setCursor(0, 1);  
    if (shour>=10)  
      {
      lcd.print(shour,DEC);
      }
      else
      {
      lcd.print("0");
      lcd.print(shour,DEC);
      }
  lcd.print(':');

  lcd.setCursor(3, 1);
    if (sminute>=10)  
      {
      lcd.print(sminute,DEC);
      }
      else
      {
      lcd.print("0");
      lcd.print(sminute,DEC);
      }
  lcd.print(':');

  lcd.setCursor(6, 1);
    if (ssecond>=10)  
      {
      lcd.print(ssecond,DEC);
      }
      else
      {
      lcd.print("0");
      lcd.print(ssecond,DEC);
      }
}


/* ~~~~~~~~~~~~~~~~~~~~~~ Time setting bit flicker ~~~~~~~~~~~~~~~~~~~~~~~ */
void TicSet(byte c,byte l)
{
  lcd.setCursor(c,l); 
  lcd.print("  ");
}


/* ~~~~~~~~~~~~~~~~~~~~~~ Show alarm ~~~~~~~~~~~~~~~~~~~~~~~ */
void PriA1()
{
  lcd.setCursor(0, 0);  
  lcd.print("Alarm1 ");
  if (Clock.checkAlarmEnabled(1))  
    {
    lcd.print("On");
    }
    else
    {
    lcd.print("Off");
    }

  Clock.getA1Time(A1Day, A1Hour, A1Minute, A1Second, A1Bits, ADy, A12h, Apm);

  lcd.setCursor(0, 1); 
  if (A1Hour>=10)  
    {
    lcd.print(A1Hour,DEC);
    }
    else
    {
    lcd.print("0");
    lcd.print(A1Hour,DEC);
    }
  lcd.print(':');

  lcd.setCursor(3, 1);
  if (A1Minute>=10) 
    {
    lcd.print(A1Minute,DEC);
    }
    else
    {
    lcd.print("0");
    lcd.print(A1Minute,DEC);
    }
  lcd.print(':');

  lcd.setCursor(6, 1);
  if (A1Second>=10) 
    {
    lcd.print(A1Second,DEC);
    }
    else
    {
    lcd.print("0");
    lcd.print(A1Second,DEC);
    }
}

/* ~~~~~~~~~~~~~~~~~~~~~~ Key test ~~~~~~~~~~~~~~~~~~~~~~~ */
unsigned long LastP;
boolean buttonPress(byte button)
{

  if(digitalRead(button)==HIGH) // Detect whether the button is pressed
    {
     
    unsigned long NowP = millis();
    unsigned long buttonChange=NowP-LastP;  // Compared to the last time the button was pressed
    if (buttonChange>500)  //Whether the key spacing is greater than 500ms
      {
      LastP = millis();  // Record the time when the key is pressed
      return true;
      }
      else
      {
      return false;
      }
    }
    else
    {
    return false;
    }
}


/* ~~~~~~~~~~~~~~~~~~~~~~ time set ~~~~~~~~~~~~~~~~~~~~~~~ */
void SetTime()
{
  bool h12, PM, Century=false;
  byte syear, smonth, sdate, sdow, shour, sminute, ssecond;

  if(buttonPress(Set))
    {
    lcd.clear();
    delay(200);
    Clock.getTime(syear, smonth, sdate, sdow, shour, sminute, ssecond);
    bool SetY=true;

/* ~~~~~~~~~~~~~~~~~~~~~~ Enter the year setting state ~~~~~~~~~~~~~~~~~~~~~~~ */
  while(SetY)
    {
    unsigned long Rt=millis()%1000;
    if(Rt<500)  // Flicker once every 500ms
      {
      PritimeSet(syear, smonth, sdate, sdow, shour, sminute, ssecond);
      }
      else
      {
      lcd.setCursor(0,0); 
      lcd.print("    ");
      }

/* ~~~~~~~~~~~~~~~~~~~~~~~~~ Set year ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
      if(buttonPress(Adj)) 
        {
        syear=syear+1;
        }

/* ~~~~~~~~~~~~~~~~~~~~~~ Enter the month setting state ~~~~~~~~~~~~~~~~~~~~~ */
  if(buttonPress(Set))
    {
    lcd.clear();
    bool SetMon=true;
    while(SetMon)
      {
      unsigned long Rt=millis()%1000;
      if(Rt<500)
        {
        PritimeSet(syear, smonth, sdate, sdow, shour, sminute, ssecond);
        }
        else
        {
        TicSet(5,0);
        }

/* ~~~~~~~~~~~~~~~~~~~~~~~~~ Set month ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
      if(buttonPress(Adj)) 
        {
        smonth=smonth+1;
        if(smonth>12)
          {
          smonth=1;
          }
        }

/* ~~~~~~~~~~~~~~~~~~~~~~ Enter date setting status~~~~~~~~~~~~~~~~~~~~~ */
  if(buttonPress(Set))
    {
    lcd.clear();
    bool SetD=true;
    while(SetD)
      {
      unsigned long Rt=millis()%1000;
      if(Rt<500)
        {
        PritimeSet(syear, smonth, sdate, sdow, shour, sminute, ssecond);
        }
        else
        {
        TicSet(8,0);
        }

/* ~~~~~~~~~~~~~~~~~~~~~~~~~ Set date ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
      if(buttonPress(Adj)) 
        {
        sdate=sdate+1;
        if(sdate>31)
          {
          sdate=1;
          }
        }
                  
/* ~~~~~~~~~~~~~~~~~~~~~~ Enter the week setting status ~~~~~~~~~~~~~~~~~~~~~ */
  if(buttonPress(Set))
    {
    lcd.clear();
    bool SetW=true;
    while(SetW)
      {
      unsigned long Rt=millis()%1000;
      if(Rt<500)
        {
        PritimeSet(syear, smonth, sdate, sdow, shour, sminute, ssecond);
        }
        else
        {
        lcd.setCursor(12,0);
        lcd.print("   ");
        }

/* ~~~~~~~~~~~~~~~~~~~~~~~~~ Set week ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
      if(buttonPress(Adj)) 
        {
        sdow=sdow+1;
        if(sdow>7)
          {
          sdow=1;
          }
        }

/* ~~~~~~~~~~~~~~~~~~~~~~ Enter the hour setting state ~~~~~~~~~~~~~~~~~~~~~ */
  if(buttonPress(Set))
    {
    lcd.clear();
    long AdjP=0;
    bool SetH=true;
    while(SetH)
      {
      unsigned long Rt=millis()%1000;
      if(Rt<500)
        {
        PritimeSet(syear, smonth, sdate, sdow, shour, sminute, ssecond);
        }
        else
        {
        TicSet(0,1);
        }

/* ~~~~~~~~~~~~~~~~~~~~~~~~~ Set hours ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
      if(buttonPress(Adj)) 
        {
        AdjP=AdjP+1;
        shour=shour+1;
        if(shour>23)
          {
          shour=0;
          }
        }

/* ~~~~~~~~~~~~~~~~~~~~~~ Enter the minute setting state ~~~~~~~~~~~~~~~~~~~~~ */
  if(buttonPress(Set))
    {
    lcd.clear();
    bool SetMin=true;
    while(SetMin)
      {
      unsigned long Rt=millis()%1000;
      if(Rt<500)
        {
        PritimeSet(syear, smonth, sdate, sdow, shour, sminute, ssecond);
        }
        else
        {
        TicSet(3,1);
        }

/* ~~~~~~~~~~~~~~~~~~~~~~~~~ Set minutes ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
      if(buttonPress(Adj)) 
        {
        AdjP=AdjP+1;
        sminute=sminute+1;
        if(sminute>59)
          {
          sminute=0;
          }
        }

/* ~~~~~~~~~~~~~~~~~~~~~~ Enter the second setting state ~~~~~~~~~~~~~~~~~~~~~ */
  if(buttonPress(Set))
    {
    lcd.clear();
    bool SetS=true;
    while(SetS)
      {
      unsigned long Rt=millis()%1000;
      if(Rt<500)
        {
        PritimeSet(syear, smonth, sdate, sdow, shour, sminute, ssecond);
        }
        else
        {
        TicSet(6,1);
        }

/* ~~~~~~~~~~~~~~~~~~~~~~~~~ Set seconds ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
      if(buttonPress(Adj)) 
        {
        AdjP=AdjP+1;
        ssecond=ssecond+1;
        if(ssecond>59)
          {
          ssecond=0;
          }
        }

/* ~~~~~~~~~~~~~~~~~~~~~~~~~ Save and exit the time Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  if(buttonPress(Set))
    {
    Clock.setYear(syear);
    Clock.setMonth(smonth);
    Clock.setDate(sdate);
    Clock.setDoW(sdow);
    if (AdjP>0)
      {
      Clock.setHour(shour);
      Clock.setMinute(sminute);
      Clock.setSecond(ssecond);
      }

/* ~~~~~~~~~~~~~~~~~~~~~~ Enter the alarm clock hour setting state ~~~~~~~~~~~~~~~~~~~~~~~ */
    lcd.clear();
    delay(200);

    bool SetA1H=true;
    while(SetA1H)
      {
      unsigned long RA1=millis()%1000;
      if(RA1<500)  
        {
        PriA1();
        }
        else
        {
        TicSet(0,1);
        }

/* ~~~~~~~~~~~~~~~~~~~~~~~~~ Set alarm hour ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
    if(buttonPress(Adj)) 
      {
      Clock.getA1Time(A1Day, A1Hour, A1Minute, A1Second, A1Bits, ADy, A12h, Apm);
      A1Hour=A1Hour+1;
      if(A1Hour<24)
        {
        Clock.setA1Time(A1Day, A1Hour, A1Minute, A1Second, B1000, ADy, false, Apm);  // 设置闹钟每天响一次
        }
        else
        {
        A1Hour=0;
        Clock.setA1Time(A1Day, A1Hour, A1Minute, A1Second, B1000, ADy, false, Apm);
        }
      }

/* ~~~~~~~~~~~~~~~~~~~~~~ Enter the alarm clock minute setting state ~~~~~~~~~~~~~~~~~~~~~ */
    if(buttonPress(Set))
      {
      lcd.clear();
      bool SetA1M=true;
      while(SetA1M)
        {
        unsigned long RA1=millis()%1000;
        if(RA1<500)
          {
          PriA1();
          }
          else
          {
          TicSet(3,1);
          }

/* ~~~~~~~~~~~~~~~~~~~~~~~~~ Set the alarm minute ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
      if(buttonPress(Adj))
        {
        Clock.getA1Time(A1Day, A1Hour, A1Minute, A1Second, A1Bits, ADy, A12h, Apm);
        A1Minute=A1Minute+1;
        if(A1Minute<60)
          {
          Clock.setA1Time(A1Day, A1Hour, A1Minute, A1Second, B1000, ADy, false, Apm);
          }
          else
          {
          A1Minute=0;
          Clock.setA1Time(A1Day, A1Hour, A1Minute, A1Second, B1000, ADy, false, Apm);
          }
        }

/* ~~~~~~~~~~~~~~~~~~~~~~ Enter the alarm clock second setting state ~~~~~~~~~~~~~~~~~~~~~ */
      if(buttonPress(Set))
        {
      lcd.clear();
      bool SetA1S=true;
      while(SetA1S)
        {
        unsigned long RA1=millis()%1000;
        if(RA1<500)
          {
          PriA1();
          }
          else
          {
          TicSet(6,1);
          }

/* ~~~~~~~~~~~~~~~~~~~~~~~~~ Set the alarm seconds ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
        if(buttonPress(Adj))
          {
          Clock.getA1Time(A1Day, A1Hour, A1Minute, A1Second, A1Bits, ADy, A12h, Apm);
          A1Second=A1Second+1;
          if(A1Second<60)
            {
            Clock.setA1Time(A1Day, A1Hour, A1Minute, A1Second, B1000, ADy, false, Apm);
            }
            else
            {
            A1Second=0;
            Clock.setA1Time(A1Day, A1Hour, A1Minute, A1Second, B1000, ADy, false, Apm);
            }
          }

/* ~~~~~~~~~~~~~~~~~~~~~~ Enter the alarm switch setting status ~~~~~~~~~~~~~~~~~~~~~ */
      if(buttonPress(Set))
        {
        lcd.clear();
        bool SetA1R=true;
        while(SetA1R)
          {
          unsigned long RA1=millis()%1000;
          if(RA1<500)
            {
            lcd.setCursor(0, 0); 
            PriA1();
            }
            else
            {
            lcd.setCursor(7, 0); 
            lcd.print("   ");
            }

/* ~~~~~~~~~~~~~~~~~~~~~~~~~ Set the alarm switch ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
          if(buttonPress(Adj))
            {
            digitalWrite(Adj,LOW);
            
            if(Clock.checkAlarmEnabled(1))
              {
              Clock.turnOffAlarm(1);
              }
              else
              {
              Clock.turnOnAlarm(1);
              }
            }

/* ~~~~~~~~~~~~~~~~~~~~~~~~~ Exit alarm Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~ */
          if(buttonPress(Set))
            {
            lcd.clear();
            delay(200);
            goto exit;
            }

        }
        }
        }
        }
        }
      }
      }
    }
  }
  }
  }
  }
  }
  }
  }
  }
  }
  }
  }
  }
  }
  }
  exit:  ;
}


/* ~~~~~~~~~~~~~~~~~~~~~~ the alarm clock rings ~~~~~~~~~~~~~~~~~~~~~ */
void Alarm()
{
  if(Clock.checkIfAlarm(1))
    {
    long Rdt;
    do
      {
      unsigned long Rt=millis()%1000;
      if(Rt<500) 
        {
        Pritime();
        delay(100);  
        tone(4,2000,50);  // Output frequency 2000Hz on port 12, maintain 50ms
        delay(100);      
        tone(4,2000,50);
        delay(100);
        tone(4,2000,50);
        delay(100);
        tone(4,2000,50);
        delay(100);
        }
        else
        {
        Tictime();
        }
      Clock.getA1Time(A1Day, A1Hour, A1Minute, A1Second, A1Bits, ADy, A12h, Apm);
      Clock.getTime(year, month, date, DoW, hour, minute, second);
      if (hour==0)
        {
        hour=24;
        }
      Rdt=hour*3600+minute*60+second-A1Hour*3600-A1Minute*60-A1Second;
      }
    while(Rdt>=0&&Rdt<5000);  // The alarm clock sounds for 300 seconds
    }
    else
    {
    digitalWrite(4,LOW);
    }
}

void loop()
{
  unsigned long Rt=millis()%1000;
  if(Rt<500)  // flashes once every 500ms
    {
    Pritime();
    }
    else
    {
    Tictime();
    }

 SetTime();
 Alarm();
}

Credits

WayneChan
21 projects • 4 followers
Arduino, Raspberry Pi & 3D

Comments