#include <RTClib.h>
#include<ezButton.h>
#include <LiquidCrystal_I2C.h>
// lcd object : setting register address 0x27
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Create an object to work with the RTC module
RTC_DS1307 rtc;
// clock variables
int year = 0;
int month = 0;
int day = 0;
int hour = 0;
int minute = 0;
int second = 0;
// alarm variables
int alarm_hours = 0;
int alarm_minutes = 0;
// encoder variables
byte clk = 2;
byte dt = 3;
byte sw = 4;
int counter = 0;
int flag = 1,prev_counter=-1; //values changed to 1 and -1
//(the 1st option should also be display automatically)
ezButton button(sw);
void setup()
{
Serial.begin(9600);
lcd.init(); // initialize the lcd.
lcd.clear(); // clears screen & moves cursor to top left corner.
lcd.backlight(); // turn on the backlight.
// initial messages
lcd.clear();
if (!rtc.begin()) {
lcd.clear();
// lcd_print(0,0,"RTC not initialised");
while (true);
}
lcd_print(0, 0, "RTC found");
delay(1000);
lcd.clear();
lcd_print(0, 0, "Welcome!");
delay(2000);
// Specifies a function to call when an external interrupt occurs.
// when CLK pin goes LOW, the encoder() is called
attachInterrupt(digitalPinToInterrupt(clk), encoder, FALLING);
// attachInterrupt(interrupt, function, mode)
// interrupt: the number of the interrupt (int)
// function: the function to call when the interrupt occurs;
// this function must take no parameters and return nothing.
// This function is sometimes referred
// to as an interrupt service routine.
// mode defines when the interrupt should be triggered.
//Four constants are predefined
// a. LOW to trigger the interrupt whenever the pin is low,
// b. CHANGE to trigger the interrupt whenever the pin changes value
// c. RISING to trigger when the pin goes from low to high,
// d. FALLING for when the pin goes from high to low
// digitalPinToInterrupt(pin)
// Pin number of the interrupt, tells the microprocessor which pins
// to monitor. The pin depends on the microcontroller being used.
button.setDebounceTime(25);
}
void loop()
{
button.loop();
if (button.isPressed())
{
select_mode();
}
mode_selector();
// for better working of simulator
delay(10);
}
void encoder()
{
prev_counter = counter;
// if rotated clockwise increase 'counter' else decrease 'counter'
if (digitalRead(dt) == HIGH)
counter++;
else
counter--;
/*Delete from her and pu in mode_selector()
// restricts counters min value to go below 0 and max value to go above 3
counter = constrain(counter, 0, 3);*/
flag = 1;
}
void mode_selector()
{
// restricts counters min value to go below 0 and max value to go above 3
//shifted here so its applicable only to this function
counter = constrain(counter, 0, 3);
if ((flag == 1) && (prev_counter != counter))
{
if (counter == 0)
{
lcd.clear();
lcd_print(0,0,"Date and Time");
}
else if (counter == 1)
{
lcd.clear();
lcd_print(0,0,"Set Alarm");
}
else if (counter == 2)
{
lcd.clear();
lcd_print(0,0,"Stopwatch");
}
else if (counter == 3)
{
lcd.clear();
lcd_print(0,0,"Countdown Timer");
}
flag = 0;
}
}
void select_mode()
{
if (counter == 0)
get_time();
if (counter == 1)
set_alarm();
if (counter == 2)
start_stopwatch();
if (counter == 3)
countdown();
}
void current_time()
{
// getting current date and time
DateTime current = rtc.now();
year = current.year();
month = current.month();
day = current.day();
hour = current.hour();
minute = current.minute();
second = current.second();
}
// udf function to print message on lcd
void lcd_print(int x, int y, String message)
{
lcd.setCursor(x, y);
lcd.print(message);
}
void get_time()
{
// while loop used so that the digital clock animation can be seen
// while doing this animayion under date time, when a button
// click is encountered, exit the current (DateTime) mode
while (true)
{
// looping button
button.loop();
if (button.isPressed())
{
lcd.clear();
// let's run the mode_selector
prev_counter = -1;
flag = 1;
// break the loop
break;
}
// getting current time
current_time();
String current_date = "Date : " + String(day) + "/" + String(month) +
"/" + String(year);
lcd_print(0, 0, "Date and Time");
lcd_print(0, 1, current_date);
String hr="",minu="",sec="";
if (hour <10)
hr="0"+String(hour);
else
hr=String(hour);
if (minute <10)
minu="0"+String(minute);
else
minu=String(minute);
if (second <10)
sec="0"+String(second);
else
sec=String(second);
String current_time = "Time : " + hr + ":" + minu + ":" + sec ;
lcd_print(0, 2, current_time);
}
}
void set_alarm()
{
lcd_print(0, 0, "Enter hours : ");
alarm_hours = set_value(0, 23);
Serial.print(alarm_hours);
lcd_print(0, 0, "Enter Minutes : ");
alarm_minutes = set_value(0, 59);
// printing data
lcd.clear();
lcd_print(0, 0, "Alarm is set for ");
lcd_print(0, 1, String(alarm_hours));
lcd_print(3, 1, " Hours and ");
lcd_print(0, 2, String(alarm_minutes));
lcd_print(3, 2, " Minutes");
delay(5000);
}
void start_stopwatch()
{
int stopwatch_hour, stopwatch_minute, stopwatch_second = 0,last_second;
while (true)
{
button.loop();
if (button.isPressed())
{
prev_counter = -1;
flag = 1;
//Giving a delay of 5 Secs,to give a feel that we
//have stopped the watch and then, back to selector mode
delay(5000);
lcd.clear();
break;
}
//this method is important when compared to the previousdelay menthod,
// bcz while being on delay the button pressed of encoder is not detected,
// when contineous checking is done, there is no loop hole for missing button click
current_time();
// stopwatch algo
if (abs(second - last_second) >= 1)
{
last_second = second;
String stopwatch_time = String(stopwatch_hour) +
" : " + String(stopwatch_minute) +
" : " + String(stopwatch_second);
lcd.clear();
lcd_print(0, 0, "Stopwatch");
lcd_print(0, 1, String(stopwatch_time));
stopwatch_second++;
}
if (stopwatch_second > 59)
{
stopwatch_second = 0;
stopwatch_minute++;
}
else if (stopwatch_minute > 59)
{
stopwatch_minute = 0;
stopwatch_hour++;
}
else if (stopwatch_hour > 24)
{
stopwatch_second, stopwatch_minute, stopwatch_hour = 0;
}
}
}
void countdown()
{
}
int set_value(int min_val, int max_val) {
int value = 0;
int last_counter = -1;
counter = 0;
while (true) {
button.loop();
if (button.isPressed())
break;
counter = constrain(counter, min_val, max_val);
if (last_counter != counter)
{
lcd_print(0, 1, " ");
lcd_print(0, 1, String(counter));
last_counter = counter;
}
}
value = counter;
counter = 0;
last_counter = -1;
return value;
}
// void play_buzzer(int frequency, int duration) {
// tone(buzzer_pin, frequency);
// delay(duration);
// noTone(buzzer_pin);
// }