#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal.h>
RTC_DS3231 rtc;
LiquidCrystal lcd(36, 34, 32, 30, 28, 26); // SDA, SCL, RS, EN, D4, D5
const int ledPins[] = {31, 33, 35, 37};
const int buttonPinAtur = 40;
const int buttonPinUp = 42;
const int buttonPinDown = 44;
const int buttonPinEnter = 46;
const int numFeeders = 4;
int currentFeeder = 0;
int menuLevel = 0;
int setHour = 0;
int setMinute = 0;
int setSecond = 0;
int offHour = 0;
int offMinute = 0;
int offSecond = 0;
bool settingOnTime = false;
bool settingOffTime = false;
void setup() {
lcd.begin(16, 2);
for (int i = 0; i < numFeeders; i++) {
pinMode(ledPins[i], OUTPUT);
}
pinMode(buttonPinAtur, INPUT_PULLUP);
pinMode(buttonPinUp, INPUT_PULLUP);
pinMode(buttonPinDown, INPUT_PULLUP);
pinMode(buttonPinEnter, INPUT_PULLUP);
if (!rtc.begin()) {
lcd.print("RTC not found");
while (1);
}
if (rtc.lostPower()) {
lcd.print("RTC lost power, let's set the time!");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
}
void loop() {
DateTime now = rtc.now();
updateLCD(now);
lcd.clear();
switch (menuLevel) {
case 0: // Main menu
handleMainMenu();
break;
case 1: // Feeder
handleSetFeeder();
break;
case 2: // Set On Time Hour
handleSetOnTimeHour();
break;
case 3: // Set On Time Minute
handleSetOnTimeMinute();
break;
case 4: // Set Off Time Hour
handleSetOffTimeHour();
break;
case 5: // Set Off Time Minute
handleSetOffTimeMinute();
break;
}
delay(100); // Delay to prevent rapid button presses
}
void handleMainMenu() {
lcd.setCursor(0, 0);
lcd.print("Programmable Timer");
if (digitalRead(buttonPinAtur) == LOW) {
menuLevel = 1;
}
}
void handleSetFeeder() {
lcd.setCursor(0, 0);
lcd.print("Pilih Feeder:");
lcd.setCursor(0, 1);
lcd.print("Feeder " + String(currentFeeder + 1));
if (digitalRead(buttonPinUp) == LOW) {
currentFeeder = (currentFeeder + 1) % numFeeders;
} else if (digitalRead(buttonPinDown) == LOW) {
currentFeeder = (currentFeeder + numFeeders - 1) % numFeeders;
} else if (digitalRead(buttonPinEnter) == LOW) {
menuLevel = 2;
}
}
void handleSetOnTimeHour() {
lcd.setCursor(0, 0);
lcd.print("Set On Time Hour:");
lcd.setCursor(0, 1);
lcd.print(formatTime(setHour, setMinute, setSecond));
if (handleTimeSetting(buttonPinUp, buttonPinDown, buttonPinEnter, setHour, 0, 23, settingOnTime, 3)) {
setHour = (setHour + 1) % 24;
}
}
void handleSetOnTimeMinute() {
lcd.setCursor(0, 0);
lcd.print("Set On Time Minute:");
lcd.setCursor(0, 1);
lcd.print(formatTime(setHour, setMinute, setSecond));
if (handleTimeSetting(buttonPinUp, buttonPinDown, buttonPinEnter, setMinute, 0, 59, settingOnTime, 4)) {
setMinute = (setMinute + 1) % 60;
}
}
void handleSetOffTimeHour() {
lcd.setCursor(0, 0);
lcd.print("Set Off Time Hour:");
lcd.setCursor(0, 1);
lcd.print(formatTime(offHour, offMinute, offSecond));
if (handleTimeSetting(buttonPinUp, buttonPinDown, buttonPinEnter, offHour, 0, 23, settingOffTime, 5)) {
offHour = (offHour + 1) % 24;
}
}
void handleSetOffTimeMinute() {
lcd.setCursor(0, 0);
lcd.print("Set Off Time Minute:");
lcd.setCursor(0, 1);
lcd.print(formatTime(offHour, offMinute, offSecond));
if (handleTimeSetting(buttonPinUp, buttonPinDown, buttonPinEnter, offMinute, 0, 59, settingOffTime, 0)) {
offMinute = (offMinute + 1) % 60;
}
}
bool handleTimeSetting(int pinUp, int pinDown, int pinEnter, int &value, int minValue, int maxValue, bool &settingFlag, int nextMenu) {
if (digitalRead(pinUp) == LOW) {
value = (value + 1) % (maxValue + 1);
return true;
} else if (digitalRead(pinDown) == LOW) {
value = (value - 1 + maxValue + 1) % (maxValue + 1);
return true;
} else if (digitalRead(pinEnter) == LOW) {
settingFlag = true;
menuLevel = nextMenu;
return true;
}
return false;
}
String formatTime(int hour, int minute, int second) {
return String(hour) + ":" + (minute < 10 ? "0" : "") + String(minute) + ":" + (second < 10 ? "0" : "") + String(second);
}
void updateLCD(DateTime now) {
lcd.setCursor(0, 0);
lcd.print("Programmable Timer:");
lcd.setCursor(0, 1);
lcd.print(formatTime(now.hour(), now.minute(), now.second()));
delay(100);
}