#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
#include <Adafruit_NeoPixel.h>
#define NEOPIXEL_PIN 6
#define NUMPIXELS 16
#define BUTTON_PIN 2
#define BTN_SET 4
#define BTN_CONTROL 2
#define BTN_END 10
#define POT_PIN A1
Adafruit_NeoPixel strip(NUMPIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
uint8_t colors[][3] = {
{255, 164, 61}, // כתום
{241, 252, 119}, // צהוב
{255, 255, 255}, // לבן
{139, 215, 252} // כחול
};
int fadeDelays[] = {300, 200, 100, 150};
LiquidCrystal_I2C lcd(0x27, 16, 2);
RTC_DS1307 rtc;
int h = 0, m = 0, s = 0;
int alarmH = 7, alarmM = 0;
int wakeBefore = 1;
int setState = 0;
bool preWarmStarted = false;
bool lightSequenceStarted = false;
bool alarmWasSet = false;
unsigned long lastSettingTime = 0;
bool alarmTriggered = false;
bool song1Started = false;
bool song2Started = false;
bool song3Started = false;
bool song4Started = false;
bool song5Started = false;
bool sequenceEnded = false;
int currentSong = 0;
unsigned long songStartTime = 0;
bool buttonPressed = false;
bool calmMode = false;
bool stayOnSong3 = false;
void setup() {
lcd.init();
lcd.backlight();
Serial.begin(9600);
pinMode(BTN_SET, INPUT_PULLUP);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(BTN_CONTROL, INPUT_PULLUP);
pinMode(BTN_END, INPUT_PULLUP);
strip.begin();
strip.show();
rtc.begin();
if (!rtc.isrunning()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
}
void loop() {
DateTime now = rtc.now();
h = now.hour(); m = now.minute(); s = now.second();
int nowMin = h * 60 + m;
int alarmMin = alarmH * 60 + alarmM;
int blinkStartMin = alarmMin - wakeBefore;
int preWarmMin = alarmMin - 2;
// כפתור סיום תמידי
if (digitalRead(BTN_END) == LOW && !song5Started) {
playSong(5);
gradualFill(colors[3][0], colors[3][1], colors[3][2], fadeDelays[3]);
sequenceEnded = true;
return;
}
if (!preWarmStarted && nowMin == preWarmMin && alarmWasSet && (setState == 0 || setState == 4)) {
preWarmStarted = true;
gradualWarmup();
}
if (!alarmTriggered && nowMin == blinkStartMin && alarmWasSet && (setState == 0 || setState == 4)) {
alarmTriggered = true;
songStartTime = millis();
if (digitalRead(BTN_CONTROL) == LOW) calmMode = true;
lightSequenceStarted = true;
startLightSequence();
}
if (sequenceEnded) return;
if (digitalRead(BTN_CONTROL) == HIGH) buttonPressed = false;
if (digitalRead(BTN_SET) == LOW) {
delay(200);
setState = (setState + 1) % 5;
}
int potValue = analogRead(POT_PIN);
if (setState == 1) { alarmH = map(potValue, 0, 1023, 0, 23); alarmWasSet = true; lastSettingTime = millis(); }
else if (setState == 2) { alarmM = map(potValue, 0, 1023, 0, 59); alarmWasSet = true; lastSettingTime = millis(); }
else if (setState == 3) { wakeBefore = map(potValue, 0, 1023, 0, 59); alarmWasSet = true; lastSettingTime = millis(); }
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 ");
}
updateClockDisplay();
delay(100);
}
void printTwoDigits(int number) {
if (number < 10) lcd.print("0");
lcd.print(number);
}
void updateClockDisplay() {
DateTime now = rtc.now();
h = now.hour(); m = now.minute(); s = now.second();
lcd.setCursor(0, 1);
lcd.print("Time ");
printTwoDigits(h); lcd.print(":");
printTwoDigits(m); lcd.print(":");
printTwoDigits(s);
lcd.print(" ");
}
void gradualWarmup() {
gradualFill(colors[0][0], colors[0][1], colors[0][2], fadeDelays[0]);
}
void gradualFill(uint8_t r, uint8_t g, uint8_t b, int delayMs) {
for (int i = 0; i < NUMPIXELS; i++) {
for (int step = 0; step <= 100; step += 10) {
float factor = step / 100.0;
strip.setPixelColor(i, strip.Color(r * factor, g * factor, b * factor));
strip.show();
delay(5);
}
delay(delayMs);
}
}
void fillAllPixels(uint8_t r, uint8_t g, uint8_t b) {
for (int i = 0; i < NUMPIXELS; i++) {
strip.setPixelColor(i, strip.Color(r, g, b));
}
strip.show();
}
void playSong(int songNum) {
currentSong = songNum;
songStartTime = millis();
switch (songNum) {
case 1: song1Started = true; Serial.println("🎵 Play rustling leaves sound"); break;
case 2: song2Started = true; Serial.println("🎵 Play bird chirping sound"); break;
case 3: song3Started = true; Serial.println("🎵 Play harp sound melody"); break;
case 4: song4Started = true; Serial.println("🎵 Play beeping truck reverse sound"); break;
case 5: song5Started = true; Serial.println("🎵 Playing 'Happy' – motion detected"); break;
}
}
void startLightSequence() {
// שלב 1: כתום מהבהב + סאונד 1
playSong(1);
unsigned long blinkStart = millis();
while (millis() - blinkStart < 10000) {
if (digitalRead(BTN_END) == LOW && !song5Started) {
playSong(5);
gradualFill(colors[3][0], colors[3][1], colors[3][2], fadeDelays[3]);
sequenceEnded = true;
return;
}
if (millis() % 500 < 250) {
fillAllPixels(colors[0][0], colors[0][1], colors[0][2]);
} else {
strip.clear();
strip.show();
}
if (digitalRead(BTN_CONTROL) == LOW && !buttonPressed) {
buttonPressed = true;
stayOnSong3 = true;
playSong(3);
gradualFill(colors[2][0], colors[2][1], colors[2][2], fadeDelays[2]);
return;
}
updateClockDisplay();
}
// שלב 2: צהוב + סאונד 2
playSong(2);
gradualFill(colors[1][0], colors[1][1], colors[1][2], fadeDelays[1]);
unsigned long yellowStart = millis();
while (millis() - yellowStart < 10000) {
if (digitalRead(BTN_END) == LOW && !song5Started) {
playSong(5);
gradualFill(colors[3][0], colors[3][1], colors[3][2], fadeDelays[3]);
sequenceEnded = true;
return;
}
if (digitalRead(BTN_CONTROL) == LOW && !buttonPressed) {
buttonPressed = true;
stayOnSong3 = true;
playSong(3);
gradualFill(colors[2][0], colors[2][1], colors[2][2], fadeDelays[2]);
return;
}
updateClockDisplay();
}
// שלב 3: לבן + סאונד 4 אם לא נלחץ קודם
playSong(4);
gradualFill(colors[2][0], colors[2][1], colors[2][2], fadeDelays[2]);
unsigned long whiteStart = millis();
while (millis() - whiteStart < 10000) {
if (digitalRead(BTN_END) == LOW && !song5Started) {
playSong(5);
gradualFill(colors[3][0], colors[3][1], colors[3][2], fadeDelays[3]);
sequenceEnded = true;
return;
}
if (digitalRead(BTN_CONTROL) == LOW && !buttonPressed) {
buttonPressed = true;
stayOnSong3 = true;
return;
}
updateClockDisplay();
}
}