Go Down

Topic: RTC mit Sommerzeit (Read 6151 times) previous topic - next topic

maeckes

Hi!

Habe das Netz schon auf den Kopf gestellt, aber leider nicht das richtige gefunden, oder einfach nach dem Falschen gesucht.

Also - ich suche einen Code, den ich in meinen Sketch einfügen kann, damit ich die Uhrzeit vom DS1307 RTC-Modul auch bei Sommer/Winterzeit korrekt angezeigt bekomme.

Im Moment klappt das mit der Sommerzeit nicht.
Habe die Uhrzeit mit dem Pc gestellt. Obwohl mein Pc gerade 20:24 anzeigt, zeigt das Display vom Arduino 19:26 an?

Gestellt habe ich hiermit:
Code: [Select]
/*
* TimeRTCSet.pde
* example code illustrating Time library with Real Time Clock.
*
* RTC clock is set in response to serial port time message
* A Processing example sketch to set the time is inclided in the download
*/

#include <Time.h> 
#include <Wire.h> 
#include <DS1307RTC.h>  // a basic DS1307 library that returns time as a time_t


void setup()  {
  Serial.begin(9600);
  setSyncProvider(RTC.get);   // the function to get the time from the RTC
  if(timeStatus()!= timeSet)
     Serial.println("Unable to sync with the RTC");
  else
     Serial.println("RTC has set the system time");     
}

void loop()
{
  if(Serial.available())
  {
     time_t t = processSyncMessage();
     if(t >0)
     {
        RTC.set(t);   // set the RTC and the system time to the received value
        setTime(t);         
     }
  }
   digitalClockDisplay(); 
   delay(1000);
}

void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year());
  Serial.println();
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

/*  code to process time sync messages from the serial port   */
#define TIME_MSG_LEN  11   // time sync to PC is HEADER followed by unix time_t as ten ascii digits
#define TIME_HEADER  'T'   // Header tag for serial time sync message

time_t processSyncMessage() {
  // return the time if a valid sync message is received on the serial port.
  while(Serial.available() >=  TIME_MSG_LEN ){  // time message consists of a header and ten ascii digits
    char c = Serial.read() ;
    Serial.print(c); 
    if( c == TIME_HEADER ) {       
      time_t pctime = 0;
      for(int i=0; i < TIME_MSG_LEN -1; i++){   
        c = Serial.read();         
        if( c >= '0' && c <= '9'){   
          pctime = (10 * pctime) + (c - '0') ; // convert digits to a number   
        }
      }   
      return pctime;
    } 
  }
  return 0;
}


Kann da jemand helfen?

Gruß
Morris

guntherb

Das mit der Sommerzeit ist recht aufwändig zu berechnen, aber es gibt eine Lib "DS1307new.h", die das unterstützt.
Sie stellt (neben den üblichen anderen Funktionen) auch die Funktion isMEZSummerTime() zur Verfügung.
Grüße
Gunther

jurs


Das mit der Sommerzeit ist recht aufwändig zu berechnen, aber es gibt eine Lib "DS1307new.h", die das unterstützt.


Ich mache die Feststellung der Sommerzeit mit gerade mal sechs Zeilen Code im Codeblock, davon eine längere if-Abfrage.

Code: [Select]

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;
}


Zu übergeben an die Funktion ist eine "Zonenzeit", also die Zeit auf der man die Echtzeituhr am besten dauernd laufen läßt:
- Jahr
- Monat
- Tag
- Stunde
- Zeitzone (UTC=0, MEZ=1)
und Rückgabewert ist true oder false, je nachdem ob man für Sommerzeit eine Stunde draufschlagen muss oder nicht.

Im Fall der Time-Library, die mit Unix-Time "Sekunden seit 01.01.1970" arbeitet, würde man also bei Sommerzeit 3600 Sekunden auf die Zonenzeit UTC+1 draufschlagen.

maeckes

#3
Jun 15, 2013, 08:39 pm Last Edit: Jun 15, 2013, 09:19 pm by maeckes Reason: 1
Habe es mit der DS1307new (1.24) versucht.

Ergebnis vom Test:
Quote
DS1307 Testsketch
Format is "hh:mm:ss dd-mm-yyyy DDD"
MEZ=0, MESZ=1 : 1

19:40:14 15-06-2013 SAT seconds since 1.1.2000:424640414 MEZ=0, MESZ=1 : 1 - Address in NV-RAM is: 0 - Clock was set!
19:40:15 15-06-2013 SAT seconds since 1.1.2000:424640415 MEZ=0, MESZ=1 : 1 - Address in NV-RAM is: 1 - Clock was set!
19:40:16 15-06-2013 SAT seconds since 1.1.2000:424640416 MEZ=0, MESZ=1 : 1 - Address in NV-RAM is: 2 - Clock was set!


Es ist jedoch laut meinem Rechner 20:38. Also 1ne Stunde und 2 Minuten falsch


EDIT:
Ok, habe das Problem gelöst.
Habe einfach die aktuelle 1.0.5 installiert, die neue Time und DS1307 library installiert und die Zeit gestellt.
Nun ist die Uhrzeit korrekt!

Hoffmakl

Der thread ist einige Jahre alt, aber für mich ist das Sommerzeitthema immer noch aktuell.
jurs - schreibt

" Ich mache die Feststellung der Sommerzeit mit gerade mal sechs Zeilen Code im Codeblock, davon eine längere if-Abfrage."

Ich habe deine if - Abfrage übernommen und einen kleinen Testsketch geschieben.

Als Ergebnis bekommen ich nicht das richtige Datum für die Sommerzeit.

Sommerzeitbeginn "Ermittelter Sommerzeitbeginn"
31.03.2013              25.03.2013
30.03.2014              31.03.2014
29.03.2015              30.03.2015
27.03.2016              28.03.2016
26.03.2017              27.03.2017
25.03.2018              26.03.2018
31.03.2019              25.03.2019
29.03.2020              30.03.2020
28.03.2021              29.03.2021
27.03.2022              28.03.2022
26.03.2023              27.03.2023
31.03.2024              25.03.2024
30.03.2025              31.03.2025
29.03.2026              30.03.2026
28.03.2027              29.03.2027
26.03.2028              27.03.2028

Das scheint nicht zu funktieren, oder?   
- no experience with C++, my first steps with MKR1000 -

HotSystems

Das scheint nicht zu funktieren, oder?   
Wie kommst du da drauf ?

Ich setze den Sketch seit einigen Jahren ein, bisher immer fehlerfrei.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

uxomm

#6
Mar 09, 2018, 06:52 pm Last Edit: Mar 09, 2018, 06:56 pm by uxomm
Ja, Jurs Code rechnet richtig, aber die Jahreszahl muss 4stellig sein. Also nicht 18 sondern 2018, dann wird richtig gerechnet.

Hier nochmal der Code aus #4 mit der 4stelligen Jahreszahl - was dann zu richtigen Ergebnissen führt:
Code: [Select]
int year = 2013;    // nicht 13 sondern 2013
int month = 3;
int day = 1;
int hour = 2;
int MEZ = 0;
int Jahr;
bool Sommerzeit = false;


void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial) {
    ;                                   // wait for serial port to connect. Needed for native USB port only
  }
  Serial.print("Jahr: ");
  Serial.println(year);
}


void loop() {
  if (Sommerzeit) {
    year++;
    day = 1;
    Sommerzeit = false;
  }

  if (month == 3 && (hour + 24 * day) >= (1 + MEZ + 24 * (31 - (5 * year / 4 + 4) % 7)))
  {
    Sommerzeit = true;
    Serial.print("Sommerzeit: ");
    Serial.print(day);
    Serial.print(".03.");
    Serial.println(year);
  }

  day++;
  delay(10);

}


Edit: Dass die Jahreszahl 4stellig sein muss wird auch hier erwähnt.
Always decouple electronic circuitry.

noiasca

#7
Mar 09, 2018, 07:44 pm Last Edit: Mar 09, 2018, 07:44 pm by noiasca
und wenn du mit hour = 2 und tzHours = 0 abfragst,
dann fragst du mit GMT/UTC ab, die Sommerzeit schaltet aber in GMT erst um 3h um.

Das würde mir die vermeintlichen Off-by-One Fehler erklären.

how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

Hoffmakl

Kaum macht man's richtig und funktioniert.
Vielen Dank, für die schnellen und guten Antworten.
Das die Jahreszahl 4-stellig sein muss, hatte ich überlesen.

Mit der Uhrzeit will ich noch testen.
Benutze NTP und stelle den interne RTC des MKR1000 mit MEZ.
- no experience with C++, my first steps with MKR1000 -

Hoffmakl

#9
Mar 10, 2018, 09:08 am Last Edit: Mar 10, 2018, 09:19 am by Hoffmakl
Noch eine Frage zur Wochentagsberechnung:
Ich berechne den Wochentag mit folgenden Zeilen


/* Tag 0 bis 6 (year 2-stellig für Jahr 2000 bis 2099) */
uint8_t KM[] = {23, 7, 8, 20, 0, 12, 20, 4, 16, 24, 8, 16};
WoTag = ((5 * year + KM[(month - 1)]) / 4 + day ) % 7 ;     

oder (auch möglich)

/*  Tag 0 bis 6 (Jahr 4-stellig 1901 bis 2099) */
WoTag = ((5 * Jahr + KM[(month - 1)]) / 4 + day -1 ) % 7

wie kommt man auf
WoTag = (5 * year /4 + 4) % 7   // (Jahr 4-stellig - Monat März)

würde gern auf (Jahr 2-stellig) umstellen.
- no experience with C++, my first steps with MKR1000 -

noiasca

Frage zu deiner Frage, warum nicht einfach das Jahr 4stellig machen?

WoTag = (5 * (2000+twoDigitYear) /4 + 4) % 7
how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

Hoffmakl

stimmt, ist irrelevant. Man kann einfach 2000 addieren.
- no experience with C++, my first steps with MKR1000 -

Daves_DIY

Hallo zusammen.

Ich weiss der Thread ist schon etwas älter.
Ich habe den original Thread in dem Jurs seine geniale Formel vorstellt nicht mehr gefunden.
Ich habe diese bei mir in eine Bibliothek eingebaut und beim testen gemerkt, dass etwas nicht stimmt.

Hier noch einmal die betreffende Codezeile von Jurs
Code: [Select]
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;
}


So lange ich mit MEZ, also tzHours= 1 teste, ist alles ok.
Wenn ich aber mit GMT also tzHours = 0 teste, funktioniert die Umschaltung nicht um 2:00 Uhr sondern um 1:00

Wenn ich die entsprechende Zeile im Code (den ich nur ansatzweise verstehe) :o so ändere, funktioniert alles.
Code: [Select]
if (month==3 && (hour + 24 * day)>=(2 - tzHours + 24*(31 - (5 * year /4 + 4) % 7)) || month==10 && (hour + 24 * day)<(2 - tzHours + 24*(31 - (5 * year /4 + 1) % 7)))

Die Detektierung der Umschaltung gilt ja immer für die Ortszeit. bei tzHours = 1 + 1 bin ich bei 2:00 Uhr Ortszeit. Bei tzHours = 0 (GMT) + 1 ist das Resultat aber schon um 1:00 true, also eine Stunde zu früh.

Vermutlich mache ja ich einen Überlegungsfehler. Immer wenn es um Verschiebung von Zeit geht wird mir ganz schummrig.  :smiley-confuse:

Kann das jemand ohne viel Aufwand nachvollziehen?
Umstellung 2018: 25. März 2:00 Ein  /  28. Okt. 2:00 Aus

Danke schon jetzt.

agmue

Ich habe den original Thread in dem Jurs seine geniale Formel vorstellt nicht mehr gefunden.
http://forum.arduino.cc/index.php?topic=313047.msg2193148#msg2193148

Von mir verbesserte Version im originalen Thema:
http://forum.arduino.cc/index.php?topic=313047.msg3483400#msg3483400

Probiere mal, ob es Dir hilft.
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

Go Up