This website uses cookies to ensure you get the best experience on our website.
Arduino Uno Bench Digital Clock

Make a Bench Arduino LCD CLock 

This code is a program for a digital clock with LCD display. The clock uses an RTC module (Real-Time Clock) and is controlled by Arduino Uno board. The clock displays time, date, and an optional alarm set indicator.

The program initializes various variables for clock functions, such as the back-light of the LCD display, a PIR motion sensor to turn on the back-light when movement is detected, and a beeper to sound the alarm when activated.

The setup() function sets the initial configuration, including setting the serial communication and configuring the RTC. If the RTC is not running, it prints an error message on the serial monitor.

The loop() function updates the clock display and checks for motion using the PIR sensor. If movement is detected, the back-light turns on. If there is no motion for 30 cycles, the back-light turns off automatically.

There are several utility functions defined in the code. The digitalClockDisplay() function updates the display of the clock, including the time, date, and alarm set indicator. The printDigits() function adds a preceding colon and leading zero to the digital clock display.

The button_loop() function checks for button presses on the LCD display and selects the corresponding menu options.

To use the LCD clock, connect the Arduino board with RTC module and upload the code. The clock will display the current time and date, and you can set the alarm by pressing the select button and navigating the menu options using the up and down buttons. When the alarm goes off, the beeper will sound for a short or long duration depending on the type of alarm set. The PIR sensor will detect motion and turn on the back-light of the LCD display to make it visible. The back-light will automatically turn off after 30 cycles of no motion to save power.

#include <Wire.h>

#include <RTClib.h>

#include "Wire.h"

#include "LiquidCrystal.h"


// A4 = SDA,A5 = SCL

LiquidCrystal lcd(0);

RTC_DS1307 RTC;

DateTime now;

// define variables

int lcd_key = 0;

int adc_key_in = 0;

int lastDay = 0;

int lastMonth = 0;

int lastYear = 0;

int lastHour = 0;

int lastMinute = 0;

int movementTimer = 0;

int menuOptions = 3;

int menuOption = 0;

int alarmHours = 0;

int alarmMinutes = 0;

bool alarmPM = 0;

bool alarmSet = 0;

bool backLightOn = 1;

// 8/1/2012 Fixed default day and hour settings on set date/time

bool resetClock = false;


// define constants

const int backLight = 10; 

const int pirPin = 16;//A2

#define btnRIGHT  0

#define btnUP     1

#define btnDOWN   2

#define btnLEFT   3

#define btnSELECT 4

#define btnNONE   5

#define beeper A1

#define shortBeep 100

#define longBeep  500


void setup () {

  Serial.begin(57600);

  pinMode(backLight, OUTPUT);

  digitalWrite(backLight, LOW); // turn backlight off  

  pinMode(beeper, OUTPUT);

  digitalWrite(beeper, LOW);  

  pinMode(pirPin, INPUT);  

  Wire.begin();

  RTC.begin();


  if (! RTC.isrunning()) {

    Serial.println("RTC is NOT running!");

    // following line sets the RTC to the date & time this sketch was compiled

    //RTC.adjust(DateTime(__DATE__, __TIME__));

  }

}


void loop () {

  now = RTC.now();

  digitalClockDisplay( ); // update clock

  movementTimer++;

  if (movementTimer > 30) //turn off backlight after 30 cycles

  {

    digitalWrite(backLight, LOW); // turn backlight off

    movementTimer = 0;

  }

  for (int i = 0; i < 10000; i++)

  {

    button_loop(); //check for button pushed

    int val = digitalRead(pirPin); //read motion sensor

    if (val == HIGH)

    {

      //sense movement?

      digitalWrite(backLight, HIGH); // turn backlight on

      movementTimer = 0;

    }

  }

}


void printDigits(byte digits)

{

  // utility function for digital clock display: prints preceding colon and leading 0

  lcd.print(":");

  if(digits < 10)

    lcd.print('0');

  lcd.print(digits,DEC);

}


void digitalClockDisplay()

{

  bool clockPM = 0;

  // 8/1/2012 Fixed default day and hour settings on set date/time

  if (now.day() != lastDay || resetClock == true)

  {

    lcd.begin(16,2);

    lcd.setCursor(3,0);


    if(now.month() < 10)

      lcd.print('0');

    lcd.print(now.month(), DEC);

    lcd.print("/");


    if(now.day() < 10)

      lcd.print('0');

    lcd.print(now.day(), DEC);

    lcd.print("/");


    int thisYear = now.year();

    lcd.print(thisYear, DEC);

  }

  // 8/1/2012 Fixed default day and hour settings on set date/time

  if (now.minute() != lastMinute || resetClock == true)

  {

    if(now.hour() < 10)

      lcd.setCursor(5,1);

    lcd.setCursor(4,1);


    // 7/29/2012 Fixed noon showing as 12am

    //    if(now.hour() > 12)

    if(now.hour() > 11)

    {

      // 8/19/2013 Fixed noon showing as 0:00pm

      if (now.hour() == 12)

      {

        lcd.print(now.hour(), DEC);

      }

      else{

        lcd.print(now.hour()-12, DEC);

      }

      printDigits(now.minute());

      clockPM = true;

      // 7/29/2012 Fixed displaying PMM; added space after "PM"

      lcd.print(" PM "); 

      // 7/29/2012 Added alarm set indicator

      if (alarmSet)

        lcd.print("*");

    }

    else

    {

      lcd.print(now.hour(), DEC);

      printDigits(now.minute());

      clockPM = false;      

      lcd.print(" AM ");

      // 7/29/2012 Added alarm set indicator

      if (alarmSet)

        lcd.print("*");      

    }

  }


  // 8/1/2012 Fixed default day and hour settings on set date/time

  resetClock = false;


  lastDay = now.day();

  lastMonth = now.month();

  lastYear = now.year();

  lastHour = now.hour();

  lastMinute = now.minute();


  //check for alarm

  if (alarmSet)

  {

    // 8/1/2012 Fixed alarm set PM

    if (alarmHours == lastHour && alarmMinutes == lastMinute)

    {

      //sound alarm

      setOffAlarm();

    } 

  }

}


void button_loop()

{

  int button = read_LCD_buttons();

  if (button == btnSELECT)

  {

    timedBeep(shortBeep,1); 

    selectMenu();

  }

}


void selectMenu()

{

  int button = 0; 

  menuOption = 1;

  lcdClear();

  lcd.print("Minute Timer");  


  while (menuOption <= menuOptions)

  {

    button = read_LCD_buttons();

    if (button == btnSELECT)

    {

      timedBeep(shortBeep,1);   

      menuOption++;


      if (menuOption == 2)

      {

        lcdClear();

        // 7/29/2012 Added clearAlarm feature

        lcd.print("Set/Clear Alarm");            

      }

      if (menuOption == 3)

      {

        lcdClear();

        lcd.print("Set Date/Time");            

      }

    } 


    if (button == btnLEFT)

    {

      if (menuOption == 1)

      {

        timedBeep(shortBeep,1);

        minuteTimer();

        return;

      }

      if (menuOption == 2)

      {

        timedBeep(shortBeep,1);

        // 7/29/2012 Added clearAlarm feature

        //check for existing alarm

        if (alarmSet)

        {

          clearAlarm();

        }

        else

        {

          setAlarm();

        }

        return;

      }

      if (menuOption == 3)

      {

        timedBeep(shortBeep,1);

        // 7/29/2012 Added setDateTime feature

        setDateTime();

        return;

      } 

    }

  }

}  


// 7/29/2012 Added clearAlarm feature

void clearAlarm()

{

  int button = 0;

  bool clearIt = true;

  char *ampm = "AM";


  lcdClear();

  lcd.print("Alarm Set For");

  lcd.setCursor(0,1);

  lcd.print(alarmHours);   

  lcd.print(":");

  lcd.print(alarmMinutes);

  lcd.print(" ");

  if (alarmPM == 1)

    ampm = "PM";

  lcd.print(ampm);

  delay(2000);

  lcdClear();

  lcd.print("Clear Alarm?");

  lcd.setCursor(0,1);

  lcd.print("Yes");  


  while (button != btnSELECT)

  {

    button = read_LCD_buttons();

    if (button == btnUP)

    {

      timedBeep(shortBeep,1);

      clearIt = !clearIt;

    }

    if (button == btnDOWN)

    {

      timedBeep(shortBeep,1);

      clearIt = !clearIt;

    }

    if (button == btnRIGHT)

    {

      timedBeep(shortBeep,1);

      alarmSet = !clearIt;

      if (clearIt)

      {

        lcdClear();

        timedBeep(shortBeep,2);

        lcd.print("Alarm Cleared!");

        delay(2000);

      }

      return; 

    }

    lcd.setCursor(0,1);

    if (clearIt)

    {

      lcd.print("Yes"); 

    }

    else{

      lcd.print("No ");

    }

  }   

}


void minuteTimer()

{

  // 8/1/2012 Pass maxCount to getTimerMinutes

  int timerMinutes = getTimerMinutes("Set Minutes", 0, 60);

  if (timerMinutes > 0)

  {

    timedCountDown(timerMinutes*60, "Minute Timer");

  }

  else

  {

    timerCancelled("Timer");       

  }

  return;

}


void setAlarm()

{

  int button = 0;

  char *ampm = "AM";

  // 8/1/2012 Pass maxCount to getTimerMinutes

  alarmHours = getTimerMinutes("Set Alarm Hour", alarmHours, 12);  

  // 7/29/2012 Validate alarm hours > 0 and < 13

  if (alarmHours > 0 && alarmHours < 13)

  {

    // 8/1/2012 Pass maxCount to getTimerMinutes

    alarmMinutes = getTimerMinutes("Set Minutes", alarmMinutes, 59);

    // 7/29/2012 Fixed allow alarm minutes to be 0

    //if (alarmMinutes > 0)

    if (alarmMinutes < 60)

    {

      lcdClear();

      lcd.print("Toggle AM/PM");

      lcd.setCursor(0,1);

      //display alarm time

      lcd.print(alarmHours);       

      lcd.print(":");

      if (alarmMinutes < 10)

        lcd.print("0");

      lcd.print(alarmMinutes);

      lcd.setCursor(6,1);

      lcd.print(ampm);

      //get AM/PM

      button = 6;

      while (button != btnSELECT && button != btnRIGHT)

      {

        button = read_LCD_buttons();

        if (button == btnUP || button == btnDOWN)

        {

          timedBeep(shortBeep,1);

          if (ampm == "AM")

          {

            ampm = "PM";

          }

          else

          {

            ampm = "AM";

          }

          lcd.setCursor(6,1);

          lcd.print(ampm);  

        }

      }


      if (button == btnRIGHT)

      {

        timedBeep(shortBeep,1);

        alarmSet = true; 

        // 8/1/2012 Fixed alarm set PM

        if (ampm == "PM") alarmHours += 12;        

        lcd.setCursor(0,0);

        lcd.print("Alarm Set for");

        delay(1000);

        return;       

      }

      else

      {

        timerCancelled("Alarm");

        return;  

      }   

    }

    else

    {

      timerCancelled("Alarm");     

    }    

  }     

  else

  {

    timerCancelled("Alarm");       

  }

}


// 7/29/2012 Added setDateTime feature

void setDateTime()

{

  int button = 0;

  char *ampm = "AM";


  //get month

  // 8/1/2012 Pass maxCount to getTimerMinutes

  int setMonth = getTimerMinutes("Set Month", lastMonth, 12);

  if (setMonth > 0 && setMonth < 13)

  {

    //get day

    // 8/1/2012 Fixed default day and hour settings on set date/time

    // 8/1/2012 Pass maxCount to getTimerMinutes

    int setDay = getTimerMinutes("Set Day", lastDay, 31);

    if (setDay > 0 && setDay < 32)

    {

      //get year

      // 8/1/2012 Pass maxCount to getTimerMinutes

      int setYear = getTimerMinutes("Set Year", lastYear, 2999);

      if (setYear > 2000 && setYear < 3000)

      {

        //get hour

        int thisHour = lastHour;

        // 8/1/2012 Fixed default day and hour settings on set date/time

        if (thisHour > 12) 

        {

          thisHour -= 12;

          ampm = "PM";

        }

        // 8/1/2012 Pass maxCount to getTimerMinutes

        int setHour = getTimerMinutes("Set Hour", thisHour, 12);

        if (setHour > 0 && setHour < 13)

        {

          //get minutes

          // 8/1/2012 Fixed default day and hour settings on set date/time

          // 8/1/2012 Pass maxCount to getTimerMinutes

          int setMinute = getTimerMinutes("Set Minute", lastMinute, 59);

          if (setMinute < 60)

          {

            //get ampm

            lcdClear();

            lcd.print("Toggle AM/PM");

            lcd.setCursor(0,1);

            //display alarm time

            lcd.print(setHour);       

            lcd.print(":");

            if (setMinute < 10)

              lcd.print("0");

            lcd.print(setMinute);

            lcd.setCursor(6,1);

            lcd.print(ampm);

            //get AM/PM

            button = 6;

            while (button != btnSELECT && button != btnRIGHT)

            {

              button = read_LCD_buttons();

              if (button == btnUP || button == btnDOWN)

              {

                timedBeep(shortBeep,1);

                if (ampm == "AM")

                {

                  ampm = "PM";

                }

                else

                {

                  ampm = "AM";

                }

                lcd.setCursor(6,1);

                lcd.print(ampm);         

              }

            }

            if (button == btnRIGHT)

            {

              timedBeep(shortBeep,1);

              if (ampm == "PM")

                setHour = setHour + 12;

              RTC.adjust(DateTime(setYear,setMonth,setDay,setHour,setMinute));


              lcd.setCursor(0,0);

              // 8/1/2012 Fixed default day and hour settings on set date/time

              lcd.print("Saving...     ");

              delay(1000);

              return;       

            }

            else

            {

              timerCancelled("");

              return;  

            }  

          }

          else

          {

            timerCancelled("");     

          }    

        }     

        else

        {

          timerCancelled("");       

        }

      }

      else

      {

        timerCancelled("");     

      }    

    }     

    else

    {

      timerCancelled("");       

    }

  }

  else

  {

    timerCancelled("");       

  }


}


// read the buttons

int read_LCD_buttons()

{

  adc_key_in = analogRead(0);      // read the value from the sensor

  // my buttons when read are centered at these valies: 0, 144, 329, 504, 741

  // we add approx 50 to those values and check to see if we are close

  if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result

  if (adc_key_in < 50)   return btnRIGHT; 

  if (adc_key_in < 195)  return btnUP;

  if (adc_key_in < 380)  return btnDOWN;

  if (adc_key_in < 555)  return btnLEFT;

  if (adc_key_in < 790)  return btnSELECT;  

  return btnNONE;  // when all others fail, return this...


}


void timedCountDown(int secondCount, char countLabel[])

{

  long seconds = 0;

  long minutes = 0; 


  lcdClear();

  lcd.print(countLabel);

  for (int i = secondCount; i >= 0; i--)

  {

    seconds = i;

    minutes = i / 60;

    if (minutes > 0)

    {

      seconds = seconds - (minutes * 60);  

    }     


    if (minutes > 0)

    {

      lcd.setCursor(0,1);

      lcd.print(minutes);

      lcd.print(" min ");

    }

    else

    {

      lcd.setCursor(0,1);

    }

    if (seconds < 10) lcd.print("0");

    lcd.print(seconds);

    lcd.print(" sec remaining");

    if (seconds > 0) delay(1000); 

    if (read_LCD_buttons() == btnSELECT) //cancel

    {

      timerCancelled("Timer");

      i = 0;

      return;

    }

  }

  lcd.setCursor(6,1);

  timedBeep(longBeep,3);

}


// 8/1/2012 Pass maxCount to getTimerMinutes

int getTimerMinutes(char timerText[], int startNum, int maxCount)

{

  int minutes = startNum;

  int button = 0;

  lcdClear();

  lcd.print(timerText);

  lcd.setCursor(0,1);

  lcd.print(minutes);   


  while (button != btnSELECT)

  {

    button = read_LCD_buttons();

    Serial.println(button);

    // 8/1/2012 Pass maxCount to getTimerMinutes

    if (button == btnLEFT)

    {

      if ((minutes + 10) <= maxCount)

      {

        timedBeep(shortBeep,1);

        minutes = minutes + 10;

      }

      else

      {

        timedBeep(shortBeep,2); 

      }

    }

    // 8/1/2012 Pass maxCount to getTimerMinutes

    if (button == btnUP)

    {

      if (minutes < maxCount)

      {

        timedBeep(shortBeep,1);

        minutes++;

      }

      else

      {

        timedBeep(shortBeep,2); 

      }

    }

    if (button == btnDOWN)

    {

      if (minutes > 0)

      {

        timedBeep(shortBeep,1);

        minutes--;

      }

      else

      {

        timedBeep(shortBeep,2); 

      }   

    } 

    if (button == btnRIGHT)

    {

      timedBeep(shortBeep,1);

      return minutes; 

    }

    lcd.setCursor(0,1);

    lcd.print(minutes); 

    lcd.print("   ");

  }

  return 0;

}


void timedBeep(int beepTime, int beepCount)

{

  for (int i = 0; i < beepCount; i ++)

  {

    digitalWrite(beeper, HIGH);

    delay(beepTime);

    digitalWrite(beeper, LOW);

    delay(beepTime);

  }

}


void lcdClear(){

  // 8/1/2012 Fixed default day and hour settings on set date/time

  //lastDay = 0;

  //lastMinute = 0;

  resetClock = true;

  lcd.clear();

  lcd.begin(16,2);

  lcd.setCursor(0,0); 

}


void timerCancelled(char message[])

{

  lcdClear();

  lcd.print(message);

  lcd.print(" Cancelled");

  timedBeep(shortBeep,3);    

}


void setOffAlarm()

{

  int button = 0;

  int i = 0;

  Serial.println(i);

  digitalWrite(backLight, HIGH); // turn backlight on

  while (button != btnSELECT)

  {

    button = read_LCD_buttons();

    lcdClear();

    i++;

    if (i > 50)

    {

      lcdClear();

      lcd.print("Alert Alert");

      lcd.setCursor(0,1);

      lcd.print("     Alert Alert");      

      i = 0;

      timedBeep(shortBeep,3);

    }


  }     

  timerCancelled("Alarm"); 

  alarmSet = false;  

}


Leave a Reply

Your email address will not be published. Required fields are marked *


Math Captcha
63 − = 56