Zeitsynchronisation NTP, setSyncInterval setzt Sommerzeit wieder zurück

hallo,

ich verwende hier die timelib.h sowie timealarms.h als Zeitschaltuhr.
Die aktuelle Uhrzeit erhält der Arduino von einem lokalen Zeitserver.
Die Unix-zeit wird dann in einer Funktion umgerechnet.

Soweit funktioniert das auch ganz gut.

1 x pro Stunde wird die zeit via Zeitserver aktualisiert mit
setSyncInterval(interval);

setSyncInterval verwendet aber intern wohl hour().
Nach einer Stunde habe ich also wieder die Unix-zeit und nicht die Sommerzeit.

Da ich timealarms verwende ist das nicht schön und meine Zeitschaltuhr funktioniert so nicht sauber.

hier der Code

#include <Ethernet.h>
#include <EthernetUdp.h>
#include <TimeLib.h>
#include <TimeAlarms.h>

// Ethernet W5100 
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 2, 9 );
IPAddress myDns(192, 168, 2, 1);
IPAddress gateway(192, 168, 2, 1);
IPAddress subnet(255, 255, 255, 0);

// NTP Servers
IPAddress timeServer(192, 168, 2, 10); // lokaler Raspberry Zeitserver
const int timeZone  = 1;     // Central European Time
int stunde          = 0;
int minuten         = 0;
int sekunden        = 0;

const int relaisLicht_1 = 43;
const int relaisLicht_2 = 42;

EthernetUDP Udp;
unsigned int localPort = 8888;  // local port to listen for UDP packets


void setup() {
  Serial.begin(9600);

// Ethernet Start
  Ethernet.begin(mac, ip, myDns, gateway, subnet);
    Udp.begin(localPort);
  //int interval = 3600; // 1 x pro Stunde Zeit synchronisieren
  int interval = 60; // 1 x pro Stunde Zeit synchronisieren
  setSyncInterval(interval); 
  setSyncProvider(getNtpTime);
 Serial.print(" vor Settime hour(): ");Serial.print(hour()); 
Serial.print(" vor Settime minute(): ");Serial.println(minute());

  unixtime_umrechnen_aktualisieren();
  setTime(stunde, minuten, sekunden, month(), day(), year());

Serial.print(" nach Settime hour(): ");Serial.print(hour()); 
Serial.print(" nach Settime minute(): ");Serial.println(minute());
  Alarm.alarmRepeat(8,30,0, startBeleuchtung);  // 
  Alarm.alarmRepeat(20,30,0, stopBeleuchtung);  // 

pinMode(relaisLicht_1, OUTPUT);
pinMode(relaisLicht_2, OUTPUT);


  startBeleuchtung();
}


time_t prevDisplay = 0; // when the digital clock was displayed




void loop() {
    if (timeStatus() != timeNotSet) {
    if (now() != prevDisplay) { //update the display only if time has changed
      prevDisplay = now();
      digitalClockDisplay();  
    }
  }
Serial.print("  hour(): ");Serial.print(hour()); 
Serial.print("  minute(): ");Serial.println(minute());
Serial.print("  stunde  : ");Serial.print(stunde);
Serial.print(" minuten : ");Serial.println(minuten);
delay(3000);
}

void startBeleuchtung(){


  digitalWrite(relaisLicht_1, LOW);
  digitalWrite(relaisLicht_2, LOW);   

}
void stopBeleuchtung(){

  digitalWrite(relaisLicht_1, HIGH);
  digitalWrite(relaisLicht_1, HIGH);   

}

void digitalClockDisplay()
{
 // unixtime_umrechnen_aktualisieren();

Serial.print(stunde);
  //printDigits(minute());
printDigits(minuten);

  //printDigits(second());
printDigits(sekunden);

  Serial.println(); 

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

/*-------- NTP code ----------*/

const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets

time_t getNtpTime()
{
  while (Udp.parsePacket() > 0) ; // discard any previously received packets
  Serial.println("Transmit NTP Request");
  sendNTPpacket(timeServer);
  uint32_t beginWait = millis();
  while (millis() - beginWait < 1500) {
    int size = Udp.parsePacket();
    if (size >= NTP_PACKET_SIZE) {
      Serial.println("Receive NTP Response");
      Udp.read(packetBuffer, NTP_PACKET_SIZE);  // read packet into the buffer
      unsigned long secsSince1900;
      // convert four bytes starting at location 40 to a long integer
      secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
      secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
      secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
      secsSince1900 |= (unsigned long)packetBuffer[43];
      return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
    }
  }
  Serial.println("No NTP Response :-(");
  return 0; // return 0 if unable to get the time
}

void unixtime_umrechnen_aktualisieren()
{
 stunde=hour()+(int)summertime_EU(year(),month(),day(),hour(),1);
 minuten=minute();
 sekunden=second();

 
 if (stunde == 24){
  stunde = 00;
 
 }
}

boolean summertime_EU(int year, byte month, byte day, byte hour, byte tzHours)
{ 
  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;
}


// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;
  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:                 
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
}

ich habe mir schon überlegt das Umrechnen zur Sommerzeit in der Timlib und dort in der setSyncInterval Funktion mit einzubauen…
geht das ? oder gibt es da eine bessere Lösung?

Grüße Sepp

edit: Interval habe ich auf 60 sekunden gesetzt nur zum testen! normal = 3600 sekunden

Ich würde es in getNtpTime() machen und dort bestimmen, ob timezone = 1 (wie bei Dir vorgegeben) oder = 2 (Sommerzeit) ist.

Suche mal hier im Forum, da gab es eine schöne Berechnung von Jurs.

Gruß Tommy

Tommy56:
Ich würde es in getNtpTime() machen und dort bestimmen, ob timezone = 1 (wie bei Dir vorgegeben) oder = 2 (Sommerzeit) ist.

Suche mal hier im Forum, da gab es eine schöne Berechnung von Jurs.

Gruß Tommy

Tommy, die verwendet der TO, setzt diese vermutlich nur an falscher Stelle ein.
Die Berechnung sollte nur für die Anzeige wirksam sein.

Hast Recht.
Wenn er aber nur in der Anzeige die Sommerzeit haben will und im Rest die Winterzeit, dann laufen halt seine Alarmfunktionen auch nach Winterzeit.

Ich sehe 2 Lösungswege:

  1. So wie ich beschrieben habe, die Sommerzeitumrechnung an anderer Stelle zu machen und überall mit der korrekten lokalen Zeit zu arbeiten

  2. intern mit UTC arbeiten und nur für Einstellung/Anzeige auf lokale Zeit umzurechnen.

Gruß Tommy

Tommy56:
timezone = 1 (wie bei Dir vorgegeben) oder = 2 (Sommerzeit) ist.

Gruß Tommy

ups...
sorry, dass hatte ich übersehen... muss das gleich mal prüfen ob es mit timezone -2 funktioniert. Dann bräuchte ich auch das Umrechnen zur Sommerzeit via funktion nicht

Tommy56:

  1. So wie ich beschrieben habe, die Sommerzeitumrechnung an anderer Stelle zu machen und überall mit der korrekten lokalen Zeit zu arbeiten

  2. intern mit UTC arbeiten und nur für Einstellung/Anzeige auf lokale Zeit umzurechnen.

Gruß Tommy

nein, ich brauch schon überall die Sommerzeit da ja anscheinend timealarms mit der Zeit rechnet die vom Zeitserver kommt und in hour() hinterlegt ist.
ich probiere es mal mit timezone = 2

@ hot systems
ja das kann wohl auch sein das ich es noch an falscher Stelle im Programm eingesetzt habe

Tommy56:
Hast Recht.
Wenn er aber nur in der Anzeige die Sommerzeit haben will und im Rest die Winterzeit, dann laufen halt seine Alarmfunktionen auch nach Winterzeit.

Ok, aber auch da kann er ja die Umrechnung durchführen.

Ich mache es mit meinem Radiowecker genau so und er weckt mich immer zur richtigen Zeit. :wink:

sepp01:
nein, ich brauch schon überall die Sommerzeit da ja anscheinend timealarms mit der Zeit rechnet die vom Zeitserver kommt und in hour() hinterlegt ist.

Der Zeitserver setzt die Systemzeit und hour() ruft die Stunde der Systemzeit ab.

Gruß Tommy

Tommy56:
Der Zeitserver setzt die Systemzeit und hour() ruft die Stunde der Systemzeit ab.

Gruß Tommy

Hallo
ok so wie es aussieht funktioniert das super mit timezone=2
ich kannte das nicht, ich hatte nur die Funktion von Jurs gefunden und eingesetzt. Dachte zuvor ich bräuchte extra diese timezone-lib.

Danke
Grüße Sepp

Eigentlich brauchst Du die Funktion von Jurs, um die Timezone zu bestimmen.
Ich habe das mal mit der TimeLib von Paul Stoffregen auf UTC umgesetzt. Evtl. kannst Du das ja nutzen.

// nach European Daylight Savings Time calculation by "jurs" for German Arduino Forum
// Param: UTC-Unixtime
// Return local-Unixtime
time_t localTimeFromUTC(time_t utc) {
const uint8_t tz_utc = 0;
uint16_t y = year(utc);
uint8_t m,h,d;
  m = month(utc);
  h = hour(utc);
  d = day(utc);
  if (m < 3 || m > 10) return utc + 3600; // +1h
  if (m > 3 && m < 10) return utc + 7200; // +2h
  if ((((m == 3) && ((h +24 * d) >= (1+ tz_utc + 24 * (31 - (5 * y / 4 +4) % 7))))
    || ((m == 10) && ((h +24 * d) >= (1+ tz_utc + 24 * (31 - (5 * y / 4 +4) % 7)))))) return utc + 7200;
  else return utc + 3600;  
}

Ich muste es nur wieder finden :wink:

Gruß Tommy

Tommy56:
Eigentlich brauchst Du die Funktion von Jurs, um die Timezone zu bestimmen.

Ich muste es nur wieder finden :wink:

Gruß Tommy

das verstehe ich nicht ganz.
Aktuell mit der Einstellung timezone=2 zeigt er mir auch nach einem ntp-interval auch noch die Sommerzeit. Die Zeit stimmt also.
Weshalb brauche ich dann die Funktion von jurs?

setze ich timezone= 2 und die timelib ändert schon sofort die Zeit auf Sommerzeit dann würde doch die zusätzliche Funktion von Jurs nur nochmals 1 Std drauf zählen oder?

Besonders wichtig ist für mich ja, das timealarms was ja bestimmt die timelib nutzt auch zu meinen korrekten Zeiten schaltet. Eine Unixzeit brauche ich nicht.

Es ist ja nicht immer Sommerzeit. Die Lib von Jurs kann den Wechsel genau bestimmen.

Gruß Tommy

Hallo

Derzeit machst du das ja manuell indem du entweder 2 oder 1 eingibst und dann den Sketch neu auf den Arduino lädst.

Die Funktion von Jurs macht die Umschaltung von Sommer auf Winterzeit automatisch.
Wenn ich mich richtig erinnere ist nach einem Systemstart die Zeit aber erst nach der zweiten Synchronisation richtig . Natürlich darfst du dann nicht zusätzlich noch was eintragen, dann wäre es doppelt

Heinz

Rentner:
Wenn ich mich richtig erinnere ist nach einem Systemstart die Zeit aber erst nach der zweiten Synchronisation richtig .

Warum sollte das so sein? Bei mir ist sie bereits nach dem 1. Sync richtig.

Gruß Tommy

Tommy56:
Warum sollte das so sein? Bei mir ist sie bereits nach dem 1. Sync richtig.

Gruß Tommy

Hallo Tommy,
ich bin fast überzeugt das der Rentner und ich die gleichen Gedankengänge haben.

kannst du bitte Deinen nochmal überprüfen und es uns erklären.
Siehe Begründung: (alles bezieht sich drauf das man seine Unix-zeit bekommt)

  1. der Arduino ist aus, und wir haben hier in D aktuell Sommerzeit
  2. der Arduino wird mit timezone=2 konfiguriert und bekommt so eine Stunde Pauschal oben drauf gepackt
    und das ja immer beim Neustart
  3. weiter wurde jurs Funktion im Programm mit eingebaut so dass die Sommerzeit der timezone nicht starr und ständig ist
  4. ich starte den Arduino und die Sommerzeit ist dann noch korrekt wenn die jurs-funktion nicht aufgerufen wurde
  5. das programm und es wird immer wieder gecheckt ob es nun winter oder sommer ist in der jurs-funktion
    Die funktion merkt es ist sommer und dann?... ich meine sie addiert genau jetzt nochmal 1 Std oben drauf

Ich verstehe nun den Sinn weshalb ich jurs Funktion benötige... aber ich sehe den fehler wie "Rentner" das stets beim Neustart eine Stunde oben drauf gepackt wird

oder haben ich sehe wieder mal den wald vor Bäumen nicht

Bitte erkläre mir das kurz wieso warum das nicht so ist

Danke
Grüße sepp

sepp01:
haben hier in D aktuell Sommerzeit
2) der Arduino wird mit timezone=2 konfiguriert

Und im Winter??

Gruß Fips

Hi

Wenn doch 'jurs' benötigt wird, um Sommer/Winterzeit zu erkennen, 'jurs' aber zusätzlich im Sommer eine Stunde oben drauf packt - warum lasse ich dann zuvor nicht einfach eine Stunde per se weg?
'jurs' kümmert sich schon darum, daß Diese 'wieder kommt'.
Ok, dafür braucht Er das aktuelle Datum - bis Das nicht klar ist, wird in NORMALZEIT geantwortet (=Winterzeit).
Erst, wen definitiv Sommer ist, wird mit SOMMERZEIT geantwortet.
Ganz Nebenbei schiebt 'jurs' die Uhrzeit auf Alpha-Zeitzone (wir hier, wir sind eine Stunde 'hinter' der Zulu-Zeitzone = Greenwich) und im Sommer zusätzlich noch eine Stunde weiter weg, da wir später aufstehen wollen, um mehr von der Sonne zu haben.

Um den Sketch auch für Andere interessant zu machen, würde ich auf UTC (=Greenwich, =Zulu) belassen und 'jurs' sich um den Rest kümmern lassen.
Intern würde ich eh in UTC rechnen, da so keine Zeit zwei Mal vorkommen kann.
Interessant wird's eh erst, wenn Du auf Zeiten prüfen willst, Die Es in Deutschland nicht oder doppelt gibt.
Beim VOR-stellen werden Zielzeiten zwischen 2:00 ... 3:00 nicht vorkommen, beim ZURÜCK-stellen dafür doppelt.
Zu Welcher soll Dein Wecker nun zuschlagen?
(auch ein Grund, weshalb ich bei der Sommerzeit-Befragung für 'NEIN, Durchgehend Winterzeit' gestimmt habe - die Schauen unter den Abstimmern fanden aber 'Durchgehend Sommerzeit' besser ... dadurch ist's auch direkt viel wärmer ... blödes Volk, Blödes - dadurch wird -D- das einzige Land sein, in Dem die Zeit durchgehend eine Stunde über der geographischen Lage laufen wird - wie immer, eine Extra-Wurst für Deutschland)

Aber sonst hatte Das auch was - das Groh der Welt kennt Sommerzeit gar nicht und ruck zuck ist man als Deutscher einer der Exoten, bei Denen man schon immer Mal Urlaub machen wollte :slight_smile:

MfG

Tommy56:
Warum sollte das so sein? Bei mir ist sie bereits nach dem 1. Sync richtig.

Gruß Tommy

hallo tommy,

ich habe gerade noch ein ganz anderes Problem gefunden da ja mein timealarms nicht funktionierte... ich dachte es läge an der Sommerzeit/Winterzeit

Auch wenn das mit Sommer/Winterzeit bei mir noch nicht passt, siehe die letzten Posts... so gibts einen dickeren Hund der hier begraben ist

Beispiel:

ich rufe im Setup erstmalig den Zeitserver auf
definiere meine zwei Timealarms
und stelle den setinterval(3600) auf 1 Std.
Der Alarm soll testhalber gleich mal nach 10 Minuten starten und nach 2 minuten stoppen
Das funktioniert 1a

setze ich den intervall auf z.B. 500 Sekunden (das tat ich nur weil ich mit dem timealarm etwas testen musste

so funktioniert der Timealarm nicht mehr.... in dem Moment wo der Zeitserver während dass das Prpgramm läuft aufgerufen wird funktioniert im Anschluss kein timealarrm mehr

Ich habe das mit versch. Sachen probiert... immer das gleiche

Setze ich den interval auf 3600 und lasse zw. Systemstart und ersten interval mal 2 timealarms aufrufen so geht das 1a

was ist das?
gibt es dazu ein bekanntes Problem?

Grüße sepp

Sorry, ich werde aus Deiner Beschreibung nicht schlau. Kannst Du das noch mal anders formulieren und evtl. mit einem Code unterstützen?

Gruß Tommy

postmaster-ino:
Hi

Wenn doch 'jurs' benötigt wird, um Sommer/Winterzeit zu erkennen, 'jurs' aber zusätzlich im Sommer eine Stunde oben drauf packt - warum lasse ich dann zuvor nicht einfach eine Stunde per se weg?
'jurs' kümmert sich schon darum, daß Diese 'wieder kommt'.

MfG

wieso?
ganz einfach aus dem Grund.
So wie ich die Funktion kenne, funktioniert diese Funktion mit Alternativvariablen für Std, min, etc...
Klar bis dahin kann ich das Programm mit timezone= 1 starten... Jurs übernimmt den Rest... super bis dahin. Aber nur wenn ich dann im Programm auch mit den Alternativvariablen arbeite die nun ja die Deutsche-zeit haben.

Was mache ich aber wenn ich mit timealarms arbeite und timealarms mit hour() etc. arbeitet....Hier müsste jurs Funktion die hour() ändern und nicht die Alternativvariable... sonst klappt das alles wunderbar solange man kein timealarms verwendet

oder mache ich was falsch. wenn ja bitte was?