#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "RTClib.h"
#include <EEPROM.h>
// sensor suara
#define SPEAKER_PIN 7
#define buzzer 7
RTC_DS1307 rtc; // sensor jam
LiquidCrystal_I2C lcd(0x27, 16, 2); // komponen LCD
// variable push button
int btnMode = 8; // tombol warna biru
int btnAdd = 9; // tombol warna hijau (untuk menambah jam atau menit)
int btnMin = 10; // tombol warna merah (untuk mengurangi jam atau menit)
// variable untuk menampung waktu
int tmpHour = 0;
int tmpMinute = 0;
// variable variant menu
int menu = 0;
// variable untuk menampung jam dan menit ke memory
int storageHour = 0;
int storageMinute = 1;
// variable delay
const int debounce = 35;
// variable untuk suara
int song[] = {500, 1000, 1500, 2000, 1500, 1000, 500};
int durasi[] = {80, 180, 280, 380, 500, 1000, 1500};
// variable nama hari dalam seminggu
int jam,menit,detik,tanggal,bulan,tahun,hari;
char temp[60];
char nama_hari[7][12]={"Minggu", "Sen","Sel","Rabu", "Kamis","Jumat","Sabtu"};
void setup () {
Serial.begin(9600);
pinMode(buzzer, OUTPUT);
pinMode(btnMode, INPUT);
pinMode(btnAdd, INPUT);
pinMode(btnMin, INPUT);
lcd.init(); lcd.backlight(); lcd.setCursor(0,0);
lcd.print("JAM DIGITAL");
// mengecek keadaan RTC atau sensor jam
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
lcd.setCursor(0,0);lcd.print("RTC err");
}
else {
Serial.println("finded RTC");
lcd.setCursor(0,1);lcd.print("RTC OK");
}
rtc.adjust(DateTime(2023, 06, 14, 11, 13, 0));
delay(5000);lcd.clear();
}
void loop () {
// tampilan menu dari LCD
switch(menu) {
case 0:
// menampilkan tanggal dan jam pada LCD
displayTime();
break;
case 1:
// menampilkan menu ubah jam
displayChangeHour();
break;
case 2:
// menampilkan menu ubah menit
displayChangeMinute();
break;
case 3:
// proses menyimpan settingan alarm
saveSetup();
break;
}
// proses pengecekan alarm
if (EEPROM.read(storageHour) != 255 && EEPROM.read(storageMinute) != 255) {
alarm(tmpHour, tmpMinute);
}
delay(50);
}
// menampilkan informasi tanggal dan jam secara realtime dari sensor RTC
void displayTime() {
DateTime now = rtc.now();
jam = now.hour();
menit=now.minute();
detik=now.second();
tanggal=now.day();
bulan=now.month();
tahun=now.year();
hari=now.dayOfTheWeek();
sprintf(temp,"%02d:%02d:%02d WIB",jam,menit,detik);
Serial.println(temp);
lcd.setCursor(2,0);lcd.print(temp);
sprintf(temp,"%s %02d:%02d:%d",nama_hari[hari],tanggal,bulan,tahun);
Serial.println(temp);
lcd.setCursor(0,1);lcd.print(temp);
// mengambil jam dan menit dari sensor RTC
tmpHour = now.hour();
tmpMinute = now.minute();
// proses pembacaan settingan alarm jam dan menit dari memory
if (EEPROM.read(storageHour) != 255) {
tmpHour = EEPROM.read(storageHour) <= 23 ? EEPROM.read(storageHour) : 0;
} if (EEPROM.read(storageMinute) != 255) {
tmpMinute = EEPROM.read(storageMinute) <= 59 ? EEPROM.read(storageMinute) : 0;
}
// jika tombol warna biru di klik, maka munculkan tampilan pengaturan jam alarm
if(digitalRead(btnMode)) {
menu = 1;
delay(debounce);
}
}
void displayChangeHour() {
// menampilkan informasi / menu pengaturan jam untuk alarm
lcd.clear();
DateTime now = rtc.now();
lcd.setCursor(0,0);
lcd.print("SET HOUR:");
lcd.setCursor(0, 1);
lcd.print(tmpHour);
// kondisi ini dimaksudkan ketika tombol biru tidak diklik, maka dapat mengatur jam dan menit
while(!digitalRead(btnMode)) {
// event klik tombol berwarna hijau (untuk menambahkan jam)
if(digitalRead(btnAdd) == HIGH) {
if(tmpHour >= 23) {
tmpHour = 0;
} else {
tmpHour = tmpHour + 1;
}
delay(debounce);
} if(digitalRead(btnMin) == HIGH) { // event klik tombol berwarna merah (untuk mengurangi jam)
if(tmpHour == 0) {
tmpHour = 23;
} else {
tmpHour = tmpHour - 1;
}
delay(debounce);
}
DateTime now = rtc.now();
// menampilkan perubahan jam secara realtime ketika tombol hijau dan merah diklik
lcd.setCursor(0, 0);
lcd.print("SET HOUR:");
lcd.setCursor(0, 1);
lcd.print(tmpHour);
lcd.print(" ");
}
// ketika tombol warna biru diklik, maka pindah ke menu pengaturan menit
menu = 2;
delay(debounce);
}
void displayChangeMinute() {
// menampilkan informasi / menu untuk mengatur menit pada alarm
lcd.clear();
DateTime now = rtc.now();
// menampilkan informasi menit
lcd.setCursor(0,0);
lcd.print("SET MINUTE:");
lcd.setCursor(0, 1);
lcd.print(tmpMinute);
// logic ini dimaksudkan ketika tombol warna biru tidak diklik, maka fungsikan tombol hijau dan merah
while(!digitalRead(btnMode)) {
if(digitalRead(btnAdd) == HIGH) { // event klik tombol berwarna hijau (untuk menambah menit)
if(tmpMinute == 59) {
tmpMinute = 0;
} else {
tmpMinute = tmpMinute + 1;
}
delay(debounce);
} if(digitalRead(btnMin) == HIGH) { // event klik tombol berwarna merah (untuk mengurangi menit)
if(tmpMinute == 0) {
tmpMinute = 59;
} else {
tmpMinute = tmpMinute - 1;
}
delay(debounce);
}
DateTime now = rtc.now();
// menampilkan perubahan menit secara realtime saat tombol warna hijau dan merah diklik
lcd.setCursor(0, 0);
lcd.print("SET MINUTE:");
lcd.setCursor(0, 1);
lcd.print(tmpMinute);
lcd.print(" ");
}
// pindah ke menu simpan pengaturan alarm
menu = 3;
delay(debounce);
}
void saveSetup() {
// fungsi ini digunakan untuk menyimpan settingan alarm
lcd.clear();
// menampilkan informasi pada baris pertama di LCD
lcd.setCursor(0,0);
lcd.print("SAVING IN");
// menampilkan informasi pada baris kedua di LCD
lcd.setCursor(0,1);
lcd.print("PROGRESS");
lcd.clear();
// menyimpan settingan jam dan menit ke memory
EEPROM.write(storageMinute, tmpMinute);
EEPROM.write(storageHour, tmpHour);
// ketika proses simpan selesai maka LCD menampilkan informasi tanggal jam waktu secara realtime
menu = 0;
delay(200);
}
void alarm(int clock, int minute) {
// mengambil tanggal dan waktu secara realtime dari sensor RTC
DateTime now = rtc.now();
int jam = now.hour(); // mengambil jam saat ini
int menit = now.minute(); // mengambil menit saat ini
if (clock == jam && minute == menit) { // jika jam dan meni sesuai alarm, maka tampilkan alarm on dan munculkan suara
// menampilkan informasi bahwa alarm sudah hidup
lcd.clear();
lcd.print("ALARM ON !!!");
// memunculkan suara alarm melalui sensor buzzer
for (int note = 0; note < sizeof(note); note ++) {
tone(buzzer, song[note], durasi[note]); // memutar suara berdasarkan pola
delay(durasi[note]);
}
}
}