2018-12-30

Der Lokalzeit Tab ist für die Berechnung erforderlich

Esp32 Sonnenaufgang als Arduino Tab.

Sonnenaufgang.ino

// ****************************************************************
// Sketch Esp32 Sonnen Auf/Untergang Modular(Tab)
// source: https://lexikon.astronomie.info/zeitgleichung/neu.html
// created: Jens Fleischer, 2018-12-29
// last mod: Jens Fleischer, 2018-12-30
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp32
// Getestet auf: ESP32 NodeMCU-32s
/******************************************************************
  Copyright (c) 2018 Jens Fleischer. All rights reserved.

  This file is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This file is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
*******************************************************************/
// Diese Version von Sonnenaufgang sollte als Tab eingebunden werden.
// Der Lokalzeit Tab (bzw. "struct tm") ist zum ausführen erforderlich.
// Gib beim Aufrufen der Funktion "twilight(Länge, Breite, UTC +/-)"
// den Längen- und Breitengrad sowie die Zeitzone deines Ortes an.
// "twilight(12.348283, 51.345751, 1);" https://www.laengengrad-breitengrad.de/
/**************************************************************************************/

struct sun {
  char sunrise[6];
  char sunset[6];
} sun;

const double PIx2 = PI * 2;
const double RAD = 0.017453292519943;

void twilight(const double longitude, const double latitude, double timeZone) {
  static byte lastday = 0;
  if (tm.tm_mday != lastday) {           // Sonnenaufgang Sonnenuntergang nur einmal Täglich berechnen
    lastday = tm.tm_mday;
    const double h = -0.833333333333333 * RAD;
    const double w = latitude * RAD;
    double JD = julianDate(1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday);
    double T = (JD - 2451545.0) / 36525.0;
    double DK;
    double EOT = calculateEOT(DK, T);
    double differenceTime = 12.0 * acos((sin(h) - sin(w) * sin(DK)) / (cos(w) * cos(DK))) / PI;
    strcpy(sun.sunrise, outputFormat((12.0 - differenceTime - EOT) - longitude / 15.0 + timeZone + tm.tm_isdst));
    strcpy(sun.sunset, outputFormat((12.0 + differenceTime - EOT) - longitude / 15.0 + timeZone + tm.tm_isdst));
    DEBUG((String)"Sonnenaufgang: " + sun.sunrise + "\nSonnenuntergang: " + sun.sunset);
  }
}

double julianDate (int y, int m, int d) {        // Gregorianischer Kalender
  if (m <= 2) {
    m = m + 12;
    y = y - 1;
  }
  int gregorian = (y / 400) - (y / 100) + (y / 4); // Gregorianischer Kalender
  return 2400000.5 + 365.0 * y - 679004.0 + gregorian + int(30.6001 * (m + 1)) + d + 12.0 / 24.0;
}

double InPi(double x) {
  int n = (int)(x / PIx2);
  x = x - n * PIx2;
  if (x < 0) x += PIx2;
  return x;
}

double calculateEOT(double &DK, double T) {
  double RAm = 18.71506921 + 2400.0513369 * T + (2.5862e-5 - 1.72e-9 * T) * T * T;
  double M  = InPi(PIx2 * (0.993133 + 99.997361 * T));
  double L  = InPi(PIx2 * (  0.7859453 + M / PIx2 + (6893.0 * sin(M) + 72.0 * sin(2.0 * M) + 6191.2 * T) / 1296.0e3));
  double e = RAD * (23.43929111 + (-46.8150 * T - 0.00059 * T * T + 0.001813 * T * T * T) / 3600.0);    // Neigung der Erdachse
  double RA = atan(tan(L) * cos(e));
  if (RA < 0.0) RA += PI;
  if (L > PI) RA += PI;
  RA = 24.0 * RA / PIx2;
  DK = asin(sin(e) * sin(L));
  RAm = 24.0 * InPi(PIx2 * RAm / 24.0) / PIx2;
  double dRA = RAm - RA;
  if (dRA < -12.0) dRA += 24.0;
  if (dRA > 12.0) dRA -= 24.0;
  dRA = dRA * 1.0027379;
  return dRA ;
}

char* outputFormat(double sunTime) {
  if (sunTime < 0) sunTime += 24;
  else if (sunTime >= 24) sunTime -= 24;
  int8_t decimal = 60 * (sunTime - (int)sunTime) + 0.5;
  int8_t predecimal = sunTime;
  if (decimal >= 60) {
    decimal -= 60;
    predecimal++;
  }
  else if (decimal < 0) {
    decimal += 60; predecimal--;
    if (predecimal < 0) predecimal += 24;
  }
  static char buf[6];
  snprintf(buf, sizeof(buf), "%.2d:%.2d", predecimal, decimal);
  return buf;
}

Der Aufruf der Funktion "twilight(Länge, Breite, Zeitzone)" ist nach ausführen von "setupTime();" möglich.
Die Berechnung des Sonnenaufgang und Sonnenuntergang durch "twilight(Länge, Breite, UTC +/-)" wird nur einmal am Tag durchgeführt.
Die Funktion "localTime();" muss entweder im "void loop" oder am Anfang der Funktion "twilight()" aufgerufen werden.

Beispiele


 
*************** Aufruf localTime() aus void loop() ******************

Bsp.: Melbourne Australien

void loop() {
 ......
  localTime();
  twilight(144.97, -37.75, 10);  // geographische Länge, Breite und Zeitzone setzen UTC +/-
 ......
}

Im Lokalzeit Tab die korrekte POSIX Zeitzone für Melbourne Australien einfügen.

bool getTime() {
  .....
  setenv("TZ", "AEST-10AEDT,M10.1.0,M4.1.0/3", 1);
  ....
}

Es ist unbedingt erforderlich die richtige POSIX Zeitzone zu setzen da diese die Information zur möglichen Sommerzeit enthält.



************* Aufruf localTime() aus void twilight() ****************

Bsp.: Leipzig Deutschland

void loop() {
 ......
  twilight(12.348283, 51.345751, 1);  // geographische Länge, Breite und Zeitzone setzen UTC +/-
 ......
}

void twilight(const double longitude, const double latitude, double timeZone) {
  localTime(); 
  static byte lastday = 0;
  ......
}

Im Lokalzeit Tab die korrekte POSIX Zeitzone für Leipzig Deutschland einfügen.

bool getTime() {
  .....
  setenv("TZ", "CET-1CEST,M3.5.0/02,M10.5.0/03", 1);
  ....
}

Zurück