Sommer/Winterzeit der RTC-DS3231

Hallo liebes Forum und ein Frohes neues Jahr🎆

ich versuche mein Sketch fĂŒr die Wetterstation anzupassen damit die Sommer und Winterzeit korrekt angepasst wird. Die uhrzeit soll nach diesem Schema angepasst werden:

  1. MĂ€rz (Beginn der Sommerzeit):
    Um 01:59 Uhr wechselt die Uhr auf 03:00 Uhr.

  2. Oktober (Ende der Sommerzeit):
    Um 02:00 Uhr wechselt die Uhr auf 01:00 Uhr.

Um zu prĂŒfen, ob die Zeit korrekt angepasst wird, habe ich die RTC auf den 31.03.2024 und 1:59 Uhr eingestellt, dies wurde von der RTC auch so ĂŒbernommen, das Problem ist das der Sketch nicht bei 1:59 Uhr anfĂ€ngt zu zĂ€hlen, sondern bei 0:59 Uhr und dann auf 3 Uhr springt, ich habe Ewigkeiten probiert und etliche varianten ausprobiert aber dieser Fehler verschwindet nicht, ich wĂŒrde mich Seher freuen, wenn jemand weiß, wo ich was Korrigieren muss und wo mein Fehler liegt, vielen Dank im Voraus.

Der Code zum Anzeigen der Uhrzeit und des Datums:

#include "RTClib.h"
RTC_DS3231 rtc; 

void setup()
{
    Serial.begin(115200);
    rtc.begin();
}

bool isDST(const DateTime& dt) 
{
  // Sommerzeit in Deutschland: Letzter Sonntag im MĂ€rz bis letzter Sonntag im Oktober
  if (dt.month() < 3 || dt.month() > 10) 
  {
    return false;
  } 
  else if (dt.month() > 3 && dt.month() < 10) 
  {
    return true;
  } 
  else if (dt.month() == 3) 
  {
    int lastSunday = 31 - ((5 + dt.year() * 5 / 4) % 7);
    return (dt.day() >= lastSunday && dt.hour() >= 2); // Sommerzeit beginnt um 02:00 Uhr
  } 
  else 
  {
    int lastSunday = 31 - ((5 + dt.year() * 5 / 4) % 7);
    return (dt.day() < lastSunday || (dt.day() == lastSunday && dt.hour() < 2)); // Sommerzeit endet um 02:00 Uhr
  }
}

void adjustForDST(DateTime& dt) 
{
  // Sommerzeit in Deutschland: Letzter Sonntag im MĂ€rz bis letzter Sonntag im Oktober
  if (isDST(dt)) 
  {
    // Sommerzeit: Eine Stunde vorstellen
    dt = dt + TimeSpan(0, 1, 0, 0); // Eine Stunde zur Uhrzeit hinzufĂŒgen
  } 
  else 
  {
    // Winterzeit: Eine Stunde zurĂŒckstellen
    dt = dt - TimeSpan(0, 1, 0, 0); // Eine Stunde von der Uhrzeit abziehen
  }
}

void readAndPrintRTC() 
{
  DateTime now = rtc.now();
  adjustForDST(now);

  char dateDisplay[15];
  char timeDisplay[15];
  
  sprintf(dateDisplay, "%.1d.%.02d.%.2d", now.day(), now.month(), now.year());
  sprintf(timeDisplay, "%.02d:%02d", now.hour(), now.minute());

  Serial.print("Date: ");
  Serial.print(dateDisplay);
  Serial.print("  Time: ");
  Serial.println(timeDisplay);
}

void loop() 
{
  readAndPrintRTC();
  delay(1000);
}

In der Funktion von Jurs findest du, wie es fĂŒr eine RTC gemacht werden kann. Das funktioniert mit einer DS3231 hervorragend.

nach dem schema hab ich es schon probiert, lÀsst sich garnicht erst kompilieren

Dann hast du es nicht richtig gemacht.
Ich habe es ĂŒber Jahre so genutzt. Du musst es nur richtig einbinden.

habe mich nach dem Forum gerichtet, werde mir das von dir verlinkte nochmals durchlesen

@my_xy_projekt hat auch mall was gebaut, zu zum suchen bin zu faul.

Ach und wenn es Fehler zeigt, muss man die sicher beseitigen.

Ja das weiß ich, nur kommen 3 weitere fehler hinzu wenn ich einen Fehler beseitige, deshalb habe ich ja nachgefragt

Sorry, ich sehe hier aber keine Fehlermeldung, oder wie meinst du das ?

Zum Beilspiel bekam ich diese fehlermeldung: 'year' was not declared in this scope
Das war der Code:

#include "RTClib.h"
RTC_DS3231 rtc; 
boolean isSummer; // Globale Variable deklarieren

void setup()
{
    Serial.begin(115200);
    rtc.begin();
}

// Sommerzeit holen
void check_SummerTime()
{
  isSummer = summertime_EU(year(), month(), day(), hour(), 1);
}


// Sommerzeit rechnen
//-------- utility code from jurs ----------
boolean summertime_EU(int year, byte month, byte day, byte hour, byte tzHours)
// European Daylight Savings Time calculation by "jurs" for German Arduino Forum
// input parameters: "normal time" for year, month, day, hour and tzHours (0=UTC, 1=MEZ)
// return value: returns true during Daylight Saving Time, false otherwise
{
  if (month < 3 || month > 10) return false; // keine Sommerzeit in Jan, Feb, Nov, Dez
  if (month > 3 && month < 10) return true; // Sommerzeit in Apr, Mai, Jun, Jul, Aug, Sep
  if (month == 3 && (hour + 24 * day) >= (1 + tzHours + 24 * (31 - (5 * year / 4 + 4) % 7)) || month == 10 && (hour + 24 * day) < (1 + tzHours + 24 * (31 - (5 * year / 4 + 1) % 7)))
    return true;
  else
    return false;
}


void readAndPrintRTC() 
{
  DateTime now = rtc.now();
  adjustForDST(now);

  char dateDisplay[15];
  char timeDisplay[15];
  
  sprintf(dateDisplay, "%.1d.%.02d.%.2d", now.day(), now.month(), now.year());
  sprintf(timeDisplay, "%.02d:%02d", now.hour(), now.minute());

  Serial.print("Date: ");
  Serial.print(dateDisplay);
  Serial.print("  Time: ");
  Serial.println(timeDisplay);
}

void loop() 
{
  readAndPrintRTC();
  delay(1000);
}

Du musst natĂŒrlich die einzelnen "Variablen" auch zu deinem RCT-Sketch anpassen.
Das mag in deinem Sketch ganz anders sein.
Versuche es doch mal mit now.year() usw.

ja auch schon probiert, lÀsst sich zwar Kompilieren, aber die Sommer/Winterzeit umstellungs Funktion hat kein effekt mehr:

#include "RTClib.h"
RTC_DS3231 rtc;
#include <Time.h>

boolean isSummer; // Globale Variable deklarieren
void adjustForDST(DateTime &dateTime) 
{
  if (isSummer) 
  {
    dateTime = dateTime + TimeSpan(1, 0, 0, 0); // Eine Stunde hinzufĂŒgen
  }
}

void setup() {
  Serial.begin(115200);
  rtc.begin();
}


void check_SummerTime() 
{
  DateTime now = rtc.now();
  isSummer = summertime_EU(now.year(), now.month(), now.day(), now.hour(), 1);
}
boolean summertime_EU(int year, byte month, byte day, byte hour, byte tzHours) 
{
  if (month < 3 || month > 10) return false;
  if (month > 3 && month < 10) return true;
  if (month == 3 && (hour + 24 * day) >= (1 + tzHours + 24 * (31 - (5 * year / 4 + 4) % 7)) || month == 10 && (hour + 24 * day) < (1 + tzHours + 24 * (31 - (5 * year / 4 + 1) % 7)))
    return true;
  else
    return false;
}

void readAndPrintRTC() 
{
  DateTime now = rtc.now();
  check_SummerTime(); // Aufruf der Funktion zur ÜberprĂŒfung der Sommerzeit
  adjustForDST(now);

  char dateDisplay[15];
  char timeDisplay[15];

  sprintf(dateDisplay, "%.1d.%.02d.%.2d", now.day(), now.month(), now.year());
  sprintf(timeDisplay, "%.02d:%02d", now.hour(), now.minute());

  Serial.print("Date: ");
  Serial.print(dateDisplay);
  Serial.print("  Time: ");
  Serial.println(timeDisplay);
}

void loop() 
{
  readAndPrintRTC();
  delay(1000);
}

Dann solltest du der Sache mit dem seriellen Monitor auf den Grund gehen.

Der Funktioniert ja sonnst könnte ich das nicht testen !?

EDIT
ich habe das auch mit 31.3.2024 probiert, mit 23:59 Uhr sowie 1:59 Uhr

Also, da du erstmal nur den nÀchsten Wechsel auf Sommerzeit testen willst, hab ich mal
darauf summertime_EU angesetzt:

uint16_t year = 2024;
byte day = (31 - (5 * year / 4 + 4) % 7);
void setup() {
  Serial.begin(9600);
  Serial.print(year);
  Serial.print( " wird am ");
  Serial.print(day);
  Serial.println(".MĂ€rz auf Sommerzeit umgestellt");

}
boolean summertime_EU(int year, byte month, byte day, byte hour, byte tzHours)
// European Daylight Savings Time calculation by "jurs" for German Arduino Forum
// input parameters: "normal time" for year, month, day, hour and tzHours (0=UTC, 1=MEZ)
// return value: returns true during Daylight Saving Time, false otherwise
{
  if (month < 3 || month > 10) return false; // keine Sommerzeit in Jan, Feb, Nov, Dez
  if (month > 3 && month < 10) return true; // Sommerzeit in Apr, Mai, Jun, Jul, Aug, Sep
  if (month == 3 && (hour + 24 * day) >= (1 + tzHours + 24 * (31 - (5 * year / 4 + 4) % 7)) || month == 10 && (hour + 24 * day) < (1 + tzHours + 24 * (31 - (5 * year / 4 + 1) % 7)))
    return true;
  else
    return false;
}

void loop() {
  byte month = 3;
  static byte hour = 0;
  if ( hour < 24 ) {
    bool isSummer = summertime_EU(year, month, day, hour, 1);
    char timestring[30];
    sprintf(timestring, "%02d.%02d.%4d %02d Uhr ist %s", day, month, year, hour, 
       isSummer?"Sommer":"Winter");
    Serial.println(timestring);
    hour++;
  }
}
2024 wird am 31.MĂ€rz auf Sommerzeit umgestellt 
31.03.2024 00 Uhr ist Winter 
31.03.2024 01 Uhr ist Winter 
31.03.2024 02 Uhr ist Sommer 
31.03.2024 03 Uhr ist Sommer
....

Dass die Funktion TimeSpan in deiner <Time.h> nicht funktioniert, mag ich nicht glauben

@michael_x Hast du meinen Code ausprobiert, diesen hier ?

#include "RTClib.h"
RTC_DS3231 rtc;
#include <Time.h>

boolean isSummer; // Globale Variable deklarieren
void adjustForDST(DateTime &dateTime) 
{
  if (isSummer) 
  {
    dateTime = dateTime + TimeSpan(1, 0, 0, 0); // Eine Stunde hinzufĂŒgen
  }
}

void setup() {
  Serial.begin(115200);
  rtc.begin();
}


void check_SummerTime() 
{
  DateTime now = rtc.now();
  isSummer = summertime_EU(now.year(), now.month(), now.day(), now.hour(), 1);
}
boolean summertime_EU(int year, byte month, byte day, byte hour, byte tzHours) 
{
  if (month < 3 || month > 10) return false;
  if (month > 3 && month < 10) return true;
  if (month == 3 && (hour + 24 * day) >= (1 + tzHours + 24 * (31 - (5 * year / 4 + 4) % 7)) || month == 10 && (hour + 24 * day) < (1 + tzHours + 24 * (31 - (5 * year / 4 + 1) % 7)))
    return true;
  else
    return false;
}

void readAndPrintRTC() 
{
  DateTime now = rtc.now();
  check_SummerTime(); // Aufruf der Funktion zur ÜberprĂŒfung der Sommerzeit
  adjustForDST(now);

  char dateDisplay[15];
  char timeDisplay[15];

  sprintf(dateDisplay, "%.1d.%.02d.%.2d", now.day(), now.month(), now.year());
  sprintf(timeDisplay, "%.02d:%02d", now.hour(), now.minute());

  Serial.print("Date: ");
  Serial.print(dateDisplay);
  Serial.print("  Time: ");
  Serial.println(timeDisplay);
}

void loop() 
{
  readAndPrintRTC();
  delay(1000);
}

Ich werde mir spÀter im laufe des Tages deinen Code zu Herzen nehmen und anschauen

Dieser Code hier hat zumindest ansatzweise Funktioniert:

#include "RTClib.h"
RTC_DS3231 rtc; 

void setup()
{
    Serial.begin(115200);
    rtc.begin();
}

bool isDST(const DateTime& dt) 
{
  // Sommerzeit in Deutschland: Letzter Sonntag im MĂ€rz bis letzter Sonntag im Oktober
  if (dt.month() < 3 || dt.month() > 10) 
  {
    return false;
  } 
  else if (dt.month() > 3 && dt.month() < 10) 
  {
    return true;
  } 
  else if (dt.month() == 3) 
  {
    int lastSunday = 31 - ((5 + dt.year() * 5 / 4) % 7);
    return (dt.day() >= lastSunday && dt.hour() >= 2); // Sommerzeit beginnt um 02:00 Uhr
  } 
  else 
  {
    int lastSunday = 31 - ((5 + dt.year() * 5 / 4) % 7);
    return (dt.day() < lastSunday || (dt.day() == lastSunday && dt.hour() < 2)); // Sommerzeit endet um 02:00 Uhr
  }
}

void adjustForDST(DateTime& dt) 
{
  // Sommerzeit in Deutschland: Letzter Sonntag im MĂ€rz bis letzter Sonntag im Oktober
  if (isDST(dt)) 
  {
    // Sommerzeit: Eine Stunde vorstellen
    dt = dt + TimeSpan(0, 1, 0, 0); // Eine Stunde zur Uhrzeit hinzufĂŒgen
  } 
  else 
  {
    // Winterzeit: Eine Stunde zurĂŒckstellen
    dt = dt - TimeSpan(0, 1, 0, 0); // Eine Stunde von der Uhrzeit abziehen
  }
}

void readAndPrintRTC() 
{
  DateTime now = rtc.now();
  adjustForDST(now);

  char dateDisplay[15];
  char timeDisplay[15];
  
  sprintf(dateDisplay, "%.1d.%.02d.%.2d", now.day(), now.month(), now.year());
  sprintf(timeDisplay, "%.02d:%02d", now.hour(), now.minute());

  Serial.print("Date: ");
  Serial.print(dateDisplay);
  Serial.print("  Time: ");
  Serial.println(timeDisplay);
}

void loop() 
{
  readAndPrintRTC();
  delay(1000);
}

Nein. Ist mir zu mĂŒhsam, deine Time.h lib zu suchen. Die time.h von wokwi kennt keinen Datentyp DateTime

Hast du geschaut, was in deiner adjustForDST(now); mit now passiert?

Wenn Serial.print einem nicht zeigt, was passiert, braucht man eben andere Testausgaben.

Es reicht nicht, an einer Stelle zu schauen.
Du must schon an mehreren Stellen den seriellen Monitor prĂŒfen lassen.

Das Problem habe ich auch, es gibt KEIN umsprung, normalerweise sollte die Zeit bei 1:59 Uhr auf 3 Uhr springen

Du musst den Beitrag von @michael_x auch richtig lesen.
Seine Testfunktion zeigt nur den Wechsel von Winter auf Sommerzeit an.
Die Uhrzeit musst du dann selbst noch umstellen (programmieren) .

1 Like