#include <Wire.h>
#include <RTClib.h>
#include <Adafruit_SSD1306.h>
// ==== OLED ====
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// ==== RTC ====
RTC_DS1307 rtc;
// ==== پینها ====
#define LDR_PIN 34
#define LED_PIN 26
#define BUZZER_PIN 27
// ==== متغیرهای عمومی ====
volatile int lightPercent = 0;
DateTime currentTime;
#define MAX_RECORDS 7
int sunriseMinutes[MAX_RECORDS];
int sunriseCount = 0;
bool sunriseDetectedToday = false;
int smartWakeupMinute = -1;
bool alarmTriggered = false;
// ==== Task Handles ====
TaskHandle_t TaskLightSensorHandle;
TaskHandle_t TaskRTCTimeHandle;
TaskHandle_t TaskLogicHandle;
TaskHandle_t TaskDisplayHandle;
TaskHandle_t TaskAlarmHandle;
// ==== توابع کمکی ====
int timeToMinutes(DateTime t) {
return t.hour() * 60 + t.minute();
}
// پیشبینی زمان طلوع با توجه به روند
int predictSunrise() {
if (sunriseCount < 2) return -1;
int deltas[MAX_RECORDS - 1];
for (int i = 1; i < sunriseCount; i++) {
deltas[i - 1] = sunriseMinutes[i] - sunriseMinutes[i - 1];
}
long sumDelta = 0;
for (int i = 0; i < sunriseCount - 1; i++) {
sumDelta += deltas[i];
}
int avgDelta = sumDelta / (sunriseCount - 1);
int predicted = sunriseMinutes[sunriseCount - 1] + avgDelta;
if (predicted < 0) predicted = 0;
if (predicted > 1439) predicted = 1439;
return predicted;
}
// ==== Task 1: خواندن نور ====
void TaskLightSensor(void *pvParameters) {
while (1) {
int raw = analogRead(LDR_PIN);
lightPercent = map(raw, 0, 4095, 100, 0); // Inverse mapping
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
// ==== Task 2: خواندن ساعت ====
void TaskRTCTime(void *pvParameters) {
while (1) {
currentTime = rtc.now();
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
// ==== Task 3: تحلیل طلوع ====
void TaskLogic(void *pvParameters) {
while (1) {
int hour = currentTime.hour();
int minute = currentTime.minute();
int nowMinutes = timeToMinutes(currentTime);
// تشخیص طلوع
if (hour >= 5 && hour < 8 && !sunriseDetectedToday) {
if (lightPercent > 60) {
if (sunriseCount < MAX_RECORDS) {
sunriseMinutes[sunriseCount++] = nowMinutes;
} else {
for (int i = 1; i < MAX_RECORDS; i++) {
sunriseMinutes[i - 1] = sunriseMinutes[i];
}
sunriseMinutes[MAX_RECORDS - 1] = nowMinutes;
}
sunriseDetectedToday = true;
}
}
// ریست روزانه
if (hour >= 8) {
sunriseDetectedToday = false;
alarmTriggered = false;
}
// پیشبینی طلوع
smartWakeupMinute = predictSunrise();
vTaskDelay(10000 / portTICK_PERIOD_MS);
}
}
// ==== Task 4: نمایش OLED ====
void TaskDisplay(void *pvParameters) {
while (1) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("Time: ");
display.print(currentTime.hour());
display.print(":");
if (currentTime.minute() < 10) display.print("0");
display.print(currentTime.minute());
display.setCursor(0, 10);
display.print("Light: ");
display.print(lightPercent);
display.println("%");
// display.setCursor(0, 20);
// display.print("Sunrises: ");
// display.print(sunriseCount);
display.setCursor(0, 20);
display.print("Predicted:");
if (smartWakeupMinute > 0) {
display.print(smartWakeupMinute / 60);
display.print(":");
int m = smartWakeupMinute % 60;
if (m < 10) display.print("0");
display.print(m);
} else {
display.print("Learning...");
}
display.setCursor(0, 45);
int nowMins = timeToMinutes(currentTime);
if (smartWakeupMinute > 0 && nowMins >= smartWakeupMinute && lightPercent > 60) {
display.print("Status: Wake up!");
} else {
display.print("Status: Sleeping");
}
display.display();
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
}
// ==== Task 5: هشدار (LED و Buzzer) ====
void TaskAlarm(void *pvParameters) {
while (1) {
int nowMins = timeToMinutes(currentTime);
if (!alarmTriggered && smartWakeupMinute > 0 &&
nowMins >= smartWakeupMinute && lightPercent > 60) {
digitalWrite(LED_PIN, HIGH);
digitalWrite(BUZZER_PIN, HIGH);
vTaskDelay(5000 / portTICK_PERIOD_MS);
digitalWrite(BUZZER_PIN, LOW);
alarmTriggered = true;
}
if (alarmTriggered && currentTime.hour() >= 8) {
digitalWrite(LED_PIN, LOW);
}
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
// ==== setup ====
void setup() {
Serial.begin(115200);
Wire.begin();
// OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("OLED not found");
while (1);
}
// RTC
if (!rtc.begin()) {
Serial.println("RTC not found");
while (1);
}
if (!rtc.isrunning()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
analogReadResolution(12);
// خروجیها
pinMode(LED_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
digitalWrite(BUZZER_PIN, LOW);
// ساخت تسکها
xTaskCreatePinnedToCore(TaskLightSensor, "LightSensor", 2048, NULL, 1, &TaskLightSensorHandle, 1);
xTaskCreatePinnedToCore(TaskRTCTime, "RTC", 2048, NULL, 1, &TaskRTCTimeHandle, 1);
xTaskCreatePinnedToCore(TaskLogic, "Logic", 4096, NULL, 2, &TaskLogicHandle, 1);
xTaskCreatePinnedToCore(TaskDisplay, "Display", 4096, NULL, 1, &TaskDisplayHandle, 1);
xTaskCreatePinnedToCore(TaskAlarm, "Alarm", 2048, NULL, 2, &TaskAlarmHandle, 1);
}
// ==== loop ====
void loop() {
// همه چیز با RTOS اجرا میشود
}