#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
RTC_DS1307 rtc;
// זמן נוכחי
int h = 0, m = 0, s = 0;
// זמן השכמה
int alarmH = 0, alarmM = 0;
// כמה דקות לפני להתחיל באזר
int wakeBefore = 0;
// מצב הגדרה
int setState = 0;
// לחצנים
#define BTN_SET 4
#define BTN_UP 3
#define BTN_DOWN 5
#define BUTTON_PIN 12 // כפתור רגיל למעבר שירים
#define ALT_BUTTON_PIN 6 // כפתור שמפעיל את שיר 4 (כמו PIR)
#define BUZZER_PIN 8
// משתנים
unsigned long lastActionTime = 0;
unsigned long repeatDelay = 400;
unsigned long repeatRate = 150;
int currentSong = 1;
bool buttonPressed = false;
bool pirTriggered = false;
bool songStarted = false;
void setup() {
rtc.begin();
lcd.init();
lcd.backlight();
Serial.begin(9600);
pinMode(BTN_SET, INPUT_PULLUP);
pinMode(BTN_UP, INPUT_PULLUP);
pinMode(BTN_DOWN, INPUT_PULLUP);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(ALT_BUTTON_PIN, INPUT_PULLUP);
pinMode(BUZZER_PIN, OUTPUT);
if (!rtc.isrunning()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
// אין שיר בתחילת הדרך
songStarted = false;
}
void loop() {
DateTime now = rtc.now();
h = now.hour();
m = now.minute();
s = now.second();
// חישוב דקות כולל
int alarmMin = alarmH * 60 + alarmM;
int startMin = alarmMin - wakeBefore;
int nowMin = h * 60 + m;
// צליל הדרגתי לפי wakeBefore
if (nowMin >= startMin && nowMin < alarmMin) {
tone(BUZZER_PIN, 1000);
} else {
noTone(BUZZER_PIN);
}
// הפעלת שיר ראשון בדיוק בזמן השעון
if (nowMin == alarmMin && !songStarted) {
songStarted = true;
playSong(1);
}
// איפוס למחר (אם עבר הזמן)
if (nowMin > alarmMin && songStarted) {
songStarted = false;
pirTriggered = false;
currentSong = 1;
}
// כפתור חלופי לשיר 4
if (digitalRead(ALT_BUTTON_PIN) == LOW && !pirTriggered) {
delay(200);
pirTriggered = true;
Serial.println("🟢 Playing 'Happy' - button triggered");
playSong(4);
}
// כפתור רגיל לעבור בין שירים (רק אם לא הופעל כפתור שיר 4)
if (digitalRead(BUTTON_PIN) == LOW && !buttonPressed && !pirTriggered) {
buttonPressed = true;
delay(200);
if (currentSong == 1) {
playSong(2);
} else if (currentSong == 2) {
playSong(3);
}
}
if (digitalRead(BUTTON_PIN) == HIGH) {
buttonPressed = false;
}
// מעבר אוטומטי לשירים 2 ו־3 לפי זמן (אם שיר 4 לא הופעל)
unsigned long nowMillis = millis();
unsigned long elapsed = nowMillis - lastActionTime;
if (!pirTriggered) {
if (currentSong == 1 && elapsed >= 10UL * 60 * 1000) {
Serial.println("10 minutes have passed – moving to song 2");
playSong(2);
}
if (currentSong == 2 && elapsed >= 20UL * 60 * 1000) {
Serial.println("10 minutes have passed – moving to song 3");
playSong(3);
}
}
// מעבר בין מצבי הגדרה
if (digitalRead(BTN_SET) == LOW) {
delay(200);
setState++;
if (setState > 4) setState = 0;
}
// שליטה במספרים לפי מצב
if (setState == 1) {
updateWithHold(alarmH, 0, 23);
} else if (setState == 2) {
updateWithHold(alarmM, 0, 59);
} else if (setState == 3) {
updateWithHold(wakeBefore, 0, 59);
}
// תצוגת שורה ראשונה
lcd.setCursor(0, 0);
if (setState == 0) {
lcd.print("Set alarm ");
} else if (setState == 1) {
lcd.print("Set hour: ");
printTwoDigits(alarmH); lcd.print(" ");
} else if (setState == 2) {
lcd.print("Set min: ");
printTwoDigits(alarmM); lcd.print(" ");
} else if (setState == 3) {
lcd.print("Set awake: ");
lcd.print(wakeBefore); lcd.print("m ");
} else if (setState == 4) {
lcd.print("Alarm ");
printTwoDigits(alarmH); lcd.print(":");
printTwoDigits(alarmM);
lcd.print(", ");
lcd.print(wakeBefore); lcd.print("m ");
}
// תצוגת שורה שנייה
lcd.setCursor(0, 1);
lcd.print("Time ");
printTwoDigits(h); lcd.print(":");
printTwoDigits(m); lcd.print(":");
printTwoDigits(s);
lcd.print(" ");
delay(100);
}
// לחצני UP/DOWN עם לחיצה ארוכה
void updateWithHold(int &value, int minVal, int maxVal) {
static bool wasUpHeld = false;
static bool wasDownHeld = false;
static unsigned long lastRepeatTime = 0;
if (digitalRead(BTN_UP) == LOW) {
if (!wasUpHeld) {
lastActionTime = millis();
value = (value + 1 > maxVal) ? minVal : value + 1;
wasUpHeld = true;
} else if (millis() - lastActionTime > repeatDelay && millis() - lastRepeatTime > repeatRate) {
value = (value + 1 > maxVal) ? minVal : value + 1;
lastRepeatTime = millis();
}
} else {
wasUpHeld = false;
}
if (digitalRead(BTN_DOWN) == LOW) {
if (!wasDownHeld) {
lastActionTime = millis();
value = (value - 1 < minVal) ? maxVal : value - 1;
wasDownHeld = true;
} else if (millis() - lastActionTime > repeatDelay && millis() - lastRepeatTime > repeatRate) {
value = (value - 1 < minVal) ? maxVal : value - 1;
lastRepeatTime = millis();
}
} else {
wasDownHeld = false;
}
}
// הדפסת מספר עם אפס מוביל
void printTwoDigits(int number) {
if (number < 10) lcd.print("0");
lcd.print(number);
}
// ניגון שיר (מופיע ב־Serial בלבד כרגע)
void playSong(int songNumber) {
currentSong = songNumber;
lastActionTime = millis();
switch (songNumber) {
case 1:
Serial.println("🎵 Play rustling leaves sound");
break;
case 2:
Serial.println("🎵 Play bird chirping sound");
break;
case 3:
Serial.println("🎵 Play beeping truck reverse sound");
break;
case 4:
Serial.println("🎵 Playing 'Happy' – triggered by button");
break;
default:
Serial.println("⚠️ Playing");
}
}