/*
* Astronomik Zaman Saati - Yigit Can Sayar
*/
#include <WiFi.h>
#include <U8g2lib.h>
#include <Wire.h>
#include <time.h>
#include <math.h>
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 3 * 3600; // GMT+3
const int daylightOffset_sec = 0;
// Konum (İzmir)
const float LATITUDE = 38.4237;
const float LONGITUDE = 27.1428;
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
struct tm timeinfo;
int sunriseHour, sunriseMin;
int sunsetHour, sunsetMin;
float moonPhase;
// Yulyen Tarihi
double getJulianDate(int year, int month, int day) {
if (month <= 2) {
year -= 1;
month += 12;
}
int A = year / 100;
int B = 2 - A + (A / 4);
return floor(365.25 * (year + 4716)) + floor(30.6001 * (month + 1)) + day + B - 1524.5;
}
// Güneş Doğuş/Batış (Düzeltilmiş)
void calculateSunriseSunset(int year, int month, int day) {
double jd = getJulianDate(year, month, day);
double n = jd - 2451545.0;
// Ortalama güneş anomalisi
double M = fmod(357.5291 + 0.98560028 * n, 360.0);
double Mrad = M * PI / 180.0;
// Merkez denklemi
double C = 1.9148 * sin(Mrad) + 0.02 * sin(2 * Mrad) + 0.0003 * sin(3 * Mrad);
// Güneşin ekliptik boylamı
double lambda = fmod(M + C + 180 + 102.9372, 360.0);
double lambdaRad = lambda * PI / 180.0;
// Güneş öğle geçişi
double Jtransit = n + 0.0009 - LONGITUDE / 360.0 + 0.0053 * sin(Mrad) - 0.0069 * sin(2 * lambdaRad);
// Güneşin deklinasyonu
double delta = asin(sin(lambdaRad) * sin(23.44 * PI / 180.0));
// Saat açısı
double latRad = LATITUDE * PI / 180.0;
double cosH = (sin(-0.833 * PI / 180.0) - sin(latRad) * sin(delta)) / (cos(latRad) * cos(delta));
// Kutuplarda güneş doğmaz/batmaz kontrolü
if (cosH > 1) {
sunriseHour = 0; sunriseMin = 0;
sunsetHour = 0; sunsetMin = 0;
return;
} else if (cosH < -1) {
sunriseHour = 0; sunriseMin = 0;
sunsetHour = 23; sunsetMin = 59;
return;
}
double H = acos(cosH) * 180.0 / PI;
// Doğuş ve batış zamanları (Yulyen günü)
double Jrise = Jtransit - H / 360.0;
double Jset = Jtransit + H / 360.0;
// UTC'ye çevir
double sunriseUTC = fmod(Jrise * 24.0, 24.0);
double sunsetUTC = fmod(Jset * 24.0, 24.0);
// Yerel saate çevir (GMT+3)
double sunriseLocal = sunriseUTC + (gmtOffset_sec / 3600.0);
double sunsetLocal = sunsetUTC + (gmtOffset_sec / 3600.0);
// 24 saat formatına getir
if (sunriseLocal < 0) sunriseLocal += 24;
if (sunriseLocal >= 24) sunriseLocal -= 24;
if (sunsetLocal < 0) sunsetLocal += 24;
if (sunsetLocal >= 24) sunsetLocal -= 24;
sunriseHour = (int)sunriseLocal;
sunriseMin = (int)((sunriseLocal - sunriseHour) * 60);
sunsetHour = (int)sunsetLocal;
sunsetMin = (int)((sunsetLocal - sunsetHour) * 60);
}
// Ay Evresi
void calculateMoonPhase(int year, int month, int day) {
double jd = getJulianDate(year, month, day);
double daysSinceNew = jd - 2451549.5;
double newMoons = daysSinceNew / 29.53;
moonPhase = newMoons - floor(newMoons);
}
// Ay Çizimi
void drawMoon(int x, int y, int r) {
u8g2.drawCircle(x, y, r);
if (moonPhase < 0.25) {
u8g2.drawDisc(x - r/2, y, r/2);
} else if (moonPhase < 0.5) {
u8g2.drawBox(x, y - r, r, r * 2);
} else if (moonPhase < 0.75) {
u8g2.drawDisc(x, y, r - 1);
} else {
u8g2.drawBox(x - r, y - r, r, r * 2);
}
}
void setup() {
Serial.begin(115200);
// OLED Başlat
u8g2.begin();
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.drawStr(0, 15, "Astronomik Saat");
u8g2.drawStr(0, 30, "Baslatiliyor...");
u8g2.sendBuffer();
// WiFi
Serial.print("WiFi baglaniyor");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi baglandi!");
// NTP
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
u8g2.clearBuffer();
u8g2.drawStr(0, 15, "WiFi Baglandi!");
u8g2.drawStr(0, 30, "Zaman aliniyor...");
u8g2.sendBuffer();
delay(2000);
}
void loop() {
if (!getLocalTime(&timeinfo)) {
Serial.println("Zaman alinamadi!");
delay(1000);
return;
}
// Günlük hesaplama
static int lastDay = -1;
if (timeinfo.tm_mday != lastDay) {
calculateSunriseSunset(timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday);
calculateMoonPhase(timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday);
lastDay = timeinfo.tm_mday;
}
// Ekranı güncelle
u8g2.clearBuffer();
// Saat (Büyük)
u8g2.setFont(u8g2_font_ncenB14_tr);
char timeStr[10];
sprintf(timeStr, "%02d:%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
u8g2.drawStr(8, 16, timeStr);
// Tarih
u8g2.setFont(u8g2_font_6x10_tr);
char dateStr[15];
sprintf(dateStr, "%02d.%02d.%04d", timeinfo.tm_mday, timeinfo.tm_mon + 1, timeinfo.tm_year + 1900);
u8g2.drawStr(25, 28, dateStr);
// Çizgi
u8g2.drawLine(0, 32, 128, 32);
// Güneş Doğuş
u8g2.setFont(u8g2_font_6x10_tr);
u8g2.drawStr(0, 44, "Dogus:");
char sunriseStr[10];
sprintf(sunriseStr, "%02d:%02d", sunriseHour, sunriseMin);
u8g2.drawStr(40, 44, sunriseStr);
// Güneş Batış
u8g2.drawStr(0, 56, "Batis:");
char sunsetStr[10];
sprintf(sunsetStr, "%02d:%02d", sunsetHour, sunsetMin);
u8g2.drawStr(40, 56, sunsetStr);
// Ay Evresi
drawMoon(108, 50, 8);
u8g2.setFont(u8g2_font_5x7_tr);
if (moonPhase < 0.1 || moonPhase > 0.9) u8g2.drawStr(85, 63, "Yeni");
else if (moonPhase > 0.4 && moonPhase < 0.6) u8g2.drawStr(85, 63, "Dolu");
else if (moonPhase < 0.5) u8g2.drawStr(88, 63, "Ilk");
else u8g2.drawStr(88, 63, "Son");
u8g2.sendBuffer();
delay(1000);
}