Sunday, August 31, 2025

ANTIKETHERA MECHANISM TANIK

 #include <Wire.h>

#include <RTClib.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

//
// ---- Display config ----
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -1         // Reset pin not used with I2C
#define OLED_ADDR     0x3C       // Change to 0x3D if your OLED uses that
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

//
// ---- RTC ----
RTC_DS3231 rtc;

//
// ---- Constants for astronomy approximations ----
// Reference new moon: 2000-01-06 18:14 UT (JD ≈ 2451550.1)
// Source: common approximation epoch for simple moon phase calc
const double NEW_MOON_JD_REF = 2451550.1;
const double SYNODIC_MONTH   = 29.53058867;

//
// ---- Utility: convert date/time to (approx) Julian Day ----
double julianDay(int y, int m, int d, int hh, int mm, int ss) {
  // Fliegel–Van Flandern algorithm (works for Gregorian dates)
  if (m <= 2) { y -= 1; m += 12; }
  int A = y / 100;
  int B = 2 - A + (A / 4);
  long C = (long)(365.25 * (y + 4716));
  long D = (long)(30.6001 * (m + 1));
  double dayFrac = (hh + (mm/60.0) + (ss/3600.0)) / 24.0;
  return C + D + d + B - 1524.5 + dayFrac;
}

//
// ---- Moon phase: age (days) and illumination (approx) ----
void moonPhase(double jd, double &ageDays, int &illumPercent) {
  double lunations = (jd - NEW_MOON_JD_REF) / SYNODIC_MONTH;
  double frac = lunations - floor(lunations);
  ageDays = frac * SYNODIC_MONTH;                            // 0..29.53
  // Illumination approximation using a simple cosine model
  // phase angle ≈ 2π * frac; illumination = (1 - cos(phase))/2
  double phaseAngle = 2.0 * PI * frac;
  double illum = 0.5 * (1.0 - cos(phaseAngle));
  illumPercent = (int)round(illum * 100.0);
}

//
// ---- Tropical zodiac from date (rough, by date ranges) ----
// Uses common Western (tropical) zodiac date boundaries.
const char* zodiacFromDate(int m, int d) {
  // date as MMDD integer for easy comparison
  int md = m*100 + d;
  if ((md >= 321  && md <= 419 )) return "Aries";
  if ((md >= 420  && md <= 520 )) return "Taurus";
  if ((md >= 521  && md <= 620 )) return "Gemini";
  if ((md >= 621  && md <= 722 )) return "Cancer";
  if ((md >= 723  && md <= 822 )) return "Leo";
  if ((md >= 823  && md <= 922 )) return "Virgo";
  if ((md >= 923  && md <= 1022)) return "Libra";
  if ((md >= 1023 && md <= 1121)) return "Scorpio";
  if ((md >= 1122 && md <= 1221)) return "Sagittarius";
  // Capricorn wraps year end
  if (md >= 1222 || md <= 119)   return "Capricorn";
  if ((md >= 120  && md <= 218 )) return "Aquarius";
  return "Pisces"; // 2/19–3/20
}

//
// ---- Cycles: Metonic (19y), Callippic (76y), Olympiad (4y) ----
int metonicYear(int year)   { return (year % 19) == 0 ? 19 : (year % 19); }
int callippicYear(int year) { int r = year % 76; return r == 0 ? 76 : r; }
int olympiadYear(int year)  { int r = year % 4;  return r == 0 ? 4  : r;  }

//
// ---- Optional: set RTC once from compile time ----
// Set to true on first upload to set the RTC, then set back to false.
bool SET_RTC_FROM_COMPILE_TIME = false;

void setup() {
  // I2C
  Wire.begin(21, 22); // ESP32 default pins; adjust if needed

  // Serial (debug)
  Serial.begin(115200);
  delay(200);

  // Display init
  if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
    // If it fails, try other address or wiring
    for (;;){
      Serial.println("SSD1306 init failed. Check wiring/address.");
      delay(2000);
    }
  }
  display.clearDisplay();
  display.display();

  // RTC init
  if (!rtc.begin()) {
    showFatal("RTC not found!");
  }
  if (rtc.lostPower()) {
    Serial.println("RTC lost power, setting time to compile time.");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  } else if (SET_RTC_FROM_COMPILE_TIME) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
}

void loop() {
  DateTime now = rtc.now();

  // Build Julian Day
  double jd = julianDay(now.year(), now.month(), now.day(),
                        now.hour(), now.minute(), now.second());

  // Moon
  double ageDays;
  int illum;
  moonPhase(jd, ageDays, illum);

  // Zodiac & cycles
  const char* zodiac = zodiacFromDate(now.month(), now.day());
  int metonic   = metonicYear(now.year());
  int callippic = callippicYear(now.year());
  int olympiad  = olympiadYear(now.year());

  // ---- Draw ----
  display.clearDisplay();

  // Header: time
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  char buf[32];
  sprintf(buf, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
  display.println(buf);

  // Date line
  sprintf(buf, "%04d-%02d-%02d", now.year(), now.month(), now.day());
  display.println(buf);

  // Moon line
  // Age with 1 decimal
  char moonBuf[32];
  dtostrf(ageDays, 5, 1, moonBuf);
  display.print("Moon: ");
  display.print(moonBuf);
  display.print(" d  ");
  display.print(illum);
  display.println("%");

  // Zodiac
  display.print("Zodiac: ");
  display.println(zodiac);

  // Cycles
  display.print("Metonic: ");
  display.print(metonic);
  display.print("  Callippic: ");
  display.println(callippic);

  display.print("Olympiad: ");
  display.print(olympiad);
  display.println(" of 4");

  // Tiny “phase bar”
  // Draw a simple horizontal bar to visualize illumination
  int barX = 0, barY = 56, barW = 128, barH = 8;
  display.drawRect(barX, barY, barW, barH, SSD1306_WHITE);
  int fillW = map(illum, 0, 100, 0, barW - 2);
  display.fillRect(barX + 1, barY + 1, fillW, barH - 2, SSD1306_WHITE);

  display.display();

  delay(250); // refresh ~4 fps
}

void showFatal(const char* msg) {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("FATAL:");
  display.println(msg);
  display.display();
  while (true) { delay(1000); }
}

No comments:

Post a Comment

MUD Three Mode operation Manual Automatic GPS

 Code for three mode operation: /*   3-Mode Headlight Controller   - Manual mode (driver uses a toggle to pick high/low)   - Auto mode (LDR...