#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
#include <Adafruit_NeoPixel.h>
// --- NeoPixel ---
#define NEOPIXEL_PIN 6
#define NUMPIXELS 16
#define BUTTON_PIN 2
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} // כחול
};
// --- LCD + RTC ---
LiquidCrystal_I2C lcd(0x27, 16, 2);
RTC_DS1307 rtc;
#define BTN_SET 4
#define POT_PIN A1
int h = 0, m = 0, s = 0;
int alarmH = 7, alarmM = 0;
int wakeBefore = 1;
int setState = 0;
bool lightSequenceStarted = false;
bool alarmWasSet = false;
void setup() {
lcd.init();
lcd.backlight();
Serial.begin(9600);
pinMode(BTN_SET, INPUT_PULLUP);
pinMode(BUTTON_PIN, 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 startMin = alarmMin - 3; // ✅ האור תמיד יתחיל דקה לפני הצלצול
// ✅ התנאי המתוקן: הפעלה רק בסטייט 0 או 4
if (!lightSequenceStarted && alarmWasSet && (setState == 0 || setState == 4) && nowMin == startMin) {
lightSequenceStarted = true;
Serial.println("🔔 Starting light sequence!");
startLightSequence();
}
// לחצן מעבר בין מצבי הגדרה
if (digitalRead(BTN_SET) == LOW) {
delay(200);
setState++;
if (setState > 4) setState = 0;
}
// קריאת פוטנציומטר
int potValue = analogRead(POT_PIN);
if (setState == 1) {
alarmH = map(potValue, 0, 1023, 0, 23);
alarmWasSet = true;
} else if (setState == 2) {
alarmM = map(potValue, 0, 1023, 0, 59);
alarmWasSet = true;
} else if (setState == 3) {
wakeBefore = map(potValue, 0, 1023, 0, 59);
alarmWasSet = true;
}
// LCD שורה 1
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 שורה 2 – זמן נוכחי
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 startLightSequence() {
uint8_t r = colors[0][0];
uint8_t g = colors[0][1];
uint8_t b = colors[0][2];
for (int i = 0; i < NUMPIXELS; i++) {
float minFactor = 0.5;
float range = 1.0 - minFactor;
float step = float(i) / (NUMPIXELS - 1);
float factor = minFactor + step * range;
uint8_t rr = r * factor;
uint8_t gg = g * factor;
uint8_t bb = b * factor;
strip.setPixelColor(i, strip.Color(rr, gg, bb));
strip.show();
delay(150);
}
fillAllPixels(r, g, b);
bool pressedDuringOrange = waitForButtonOrTimeout(10000);
if (!pressedDuringOrange) {
blinkWithButton(r, g, b, 10000, 300);
}
for (int c = 1; c < 4; c++) {
uint8_t rr = colors[c][0];
uint8_t gg = colors[c][1];
uint8_t bb = colors[c][2];
strip.clear();
strip.show();
for (int i = 0; i < NUMPIXELS; i++) {
uint8_t r2 = rr, g2 = gg, b2 = bb;
if (c != 2) {
float minFactor = 0.5;
float range = 1.0 - minFactor;
float step = float(i) / (NUMPIXELS - 1);
float brightnessFactor = minFactor + step * range;
r2 = rr * brightnessFactor;
g2 = gg * brightnessFactor;
b2 = bb * brightnessFactor;
}
strip.setPixelColor(i, strip.Color(r2, g2, b2));
strip.show();
delay(150);
}
fillAllPixels(rr, gg, bb);
bool skip = waitForButtonOrTimeout(10000);
if (skip) continue;
strip.clear();
strip.show();
delay(500);
}
}
bool waitForButtonOrTimeout(unsigned long durationMs) {
unsigned long start = millis();
unsigned long lastUpdate = 0;
while (millis() - start < durationMs) {
if (digitalRead(BUTTON_PIN) == LOW) {
delay(200);
return true;
}
if (millis() - lastUpdate > 500) {
updateClockDisplay();
lastUpdate = millis();
}
delay(20);
}
return false;
}
bool blinkWithButton(uint8_t r, uint8_t g, uint8_t b, unsigned long durationMs, int interval) {
unsigned long start = millis();
unsigned long lastUpdate = 0;
bool on = true;
while (millis() - start < durationMs) {
if (digitalRead(BUTTON_PIN) == LOW) {
delay(200);
return true;
}
if (on) {
fillAllPixels(r, g, b);
} else {
strip.clear();
strip.show();
}
if (millis() - lastUpdate > 500) {
updateClockDisplay();
lastUpdate = millis();
}
on = !on;
delay(interval);
}
return false;
}
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();
}