Problem mit Datum/Zeit

Hallo,

ich habe da ein etwas seltsamen Problem mit meiner Wetterstation. Das Problem ist bis jetzt zwei mal aufgetreten jeweils etwa nach 3 Wochen Betrieb ohne Probleme.

Anwendung
Wetterstation mit Hardware ESP8266-01 und BME 280

als NTP Timeserver verwende ich die Fritzbox und als interne Uhr die standard Time.h. Synchronisiert wird die Zeit jede Stunde . Alle zwei Stunden schreibe ich per FTP Daten auf die Fritzbox. Zusätlich ist noch ein Webserver enthalten Auf der Webseite werden die aktuellen Messwerte und eine Grafik der letzten 4 Stunden dargestellt . Die jeweiligen Ereignisse zum Messen und das Daten in´s FIFO für die Grafik schreiben werden mittels Abfrage der Zeit now() getriggert.

if ( tnow >= last_mess + 10) { // Messen
last_mess = tnow;
Serial.print("gemessen ");Serial.println(tnow);
messen();
}

Das Problem :
in der auf die Fitzbox geschreibenen CSV Datei ist zu sehen das es einen Eintrag mit völlig falschem Datum/Zeit gibt.

2036-02-07 08:28:25; 23,91; 44,45; 1016,68

danach wird dann wahrscheinlich noch einmal gemessen und dann nicht mehr, da die Varialbe zum speichen der letzten Messzeit "last_mess" auf einem hohen Wert steht und die >= nicht mehr erfüllt ist.

Irgendwann scheint dann die Zeit wieder richtig zu sein und es wird wieder in die CSV geschrieben. Der Trigger dazu wird durch die aktuelle Uhrzeit mit hour(), minute(), second() gebildet. Allerdings immer die gleichen Messwerte da der Trigger zum messen wegen des immer noch falschen "last_mess" nicht funzt.

2018-06-12 00:00:17; 24,19; 51,85; 1013,58
2018-06-12 02:00:17; 24,13; 49,76; 1013,46
2018-06-12 04:00:16; 23,91; 49,62; 1013,61
2018-06-12 06:00:17; 23,90; 48,63; 1013,68
2018-06-12 08:00:17; 23,86; 48,07; 1014,20
2018-06-12 10:00:17; 23,86; 47,73; 1014,47
2018-06-12 12:00:17; 23,96; 47,03; 1015,17
2018-06-12 14:00:17; 24,30; 45,11; 1015,16
2018-06-12 16:00:18; 24,26; 44,46; 1015,31
2018-06-12 18:00:17; 22,90; 46,14; 1015,25
2018-06-12 20:00:17; 23,45; 45,54; 1015,59
2018-06-12 22:00:17; 24,03; 46,71; 1016,44
2018-06-13 00:00:17; 23,91; 48,62; 1016,38
2036-02-07 08:28:25; 23,91; 44,45; 1016,68  <----- falsch
2018-06-13 10:00:17; 23,60; 43,51; 1016,86
2018-06-13 12:00:17; 23,60; 43,51; 1016,86
2018-06-13 14:00:17; 23,60; 43,51; 1016,86
2018-06-13 16:00:17; 23,60; 43,51; 1016,86
2018-06-13 18:00:17; 23,60; 43,51; 1016,86

Handelt es sich bei dem falschen Datum eventuell um den Überlaufwert ? von tnow. Ist jemandem sowas bekannt?
Ich denke eigendlch es kann nur daran liegen das bei dem Sync mit dem NTP was falsch läuft. Aber warum nur alle ca.3 Wochen da sind dann ca. 500 Sync´s gut gelaufen.

#include <Time.h>
#include <TimeLib.h>

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

#include <string.h>

#include <BME280I2C.h>
#include <Wire.h>


char ssid[] = "xxxxx";         // lokales Netzwerk
char pass[] = "xxxxx";       // passwort
unsigned int localPort = 2390;      // lokaler port für UDP

IPAddress FritzboxIP(192, 168, 178, 1); // Fritzbox
const int NTP_PACKET_SIZE = 48;         // NTP Paket länge
byte paket[ NTP_PACKET_SIZE];           // NTP puffer
boolean sommerzeit = true;
boolean status_messen = false;

String file = "wetter.csv";

unsigned long last_mess, last_buf;

unsigned long alarmzeit[12];
boolean alarmquit[12];

float temperatur, humidity, luftdruck;    // aktualwerte
float tempMittelbuf, humMittelbuf, luftMittelbuf; // puffer gleitender Mittelwert
float buftemp[18], bufhum[18], bufluft[18]; // Kurzzeitspeicher
float Steigung, Abschnitt;
int ZeigerBuf = -1;
// UDP Instanz erstellen
WiFiUDP udp;

// Server Instanz erstellen
ESP8266WebServer server(80);

// FTP Instanz erstellen
WiFiClient ftpClient;// client Port 21
WiFiClient dClient;// client für daten Portnr. kommt vom Server

// BME settings
BME280I2C::Settings settings(
  BME280::OSR_X1,
  BME280::OSR_X1,
  BME280::OSR_X1,
  BME280::Mode_Forced,
  BME280::StandbyTime_1000ms,
  BME280::Filter_4,
  BME280::SpiEnable_False,
  0x77 // I2C address. I2C specific.
);
BME280I2C bme(settings);


//======================= Set up ============================
void setup() {
  Serial.begin(115200);

  Serial.println("-------------");
  Serial.printf("Connecting to ", ssid);

  wificonnect();

  // NTP Zeit abrufen und läuft so automatisch zyklisch ab
  setSyncProvider(get_time);
  setSyncInterval(3600);
  Serial.println(DatumZeit());

  // WebServer starten
  if (MDNS.begin("esp8266")) {
    Serial.println("MDNS responder started");
  }

  server.on("/", handleRoot);
  server.on ( "/test1.svg", drawGraph1 );
  server.on ( "/test2.svg", drawGraph2 );
  server.on ( "/test3.svg", drawGraph3 );
  server.onNotFound(handleNotFound);
  server.begin();
  Serial.println("HTTP server started");


  // I2C Bus starten an pin 1 u pin 2
  Wire.begin(0, 2);
  delay(2000);
  while (!bme.begin()) {
    Serial.println(F(" Kann BME 280 Sensor nicht finden"));
  }



  // Alarmwerte vorbesetzeten ab  0:00:15 alle zwei Stunden
  for (int i = 0; i <= 11; i++) {
    alarmzeit[i] = i * 7200 + 15;
    // Serial.println(alarmzeit[i]);
  }
  bool dummy = alarm(); // Alarm initialisieren auf aktuelle Zeit

}
//======================= loop ============================
void loop() {

  if (WiFi.status() != WL_CONNECTED) {
    wificonnect();
    delay(1000);
  }


  time_t tnow = now();
  server.handleClient();

  if ( tnow >= last_mess + 10) {   // Messen
    last_mess = tnow;
    Serial.print("gemessen ");Serial.println(tnow);
    messen();
  }

  if (tnow >= last_buf + 900) {  // Kurzzeitspeicher schreiben
    last_buf = tnow;
    fill_buffer();

  }


  if (alarm()) {            // Daten auf Fritzbox schreiben
    if ( ftp_write()) {
      Serial.println(F("Daten geschrieben"));
    }
  }


}

Sync

// -------------- Datum Zeit von Timeserver holen-------------
time_t get_time() {
  Serial.println(F("UDP starten"));
  udp.begin(localPort);

  // Paketdaten zur NTP Anfrage
  memset(paket, 0, 48);
  paket[0] = 0b11100011;
  paket[1] = 0;
  paket[2] = 6;
  paket[3] = 0xEC;
  paket[12] = 49;
  paket[13] = 0x4E;
  paket[14] = 49;
  paket[15] = 52;

  udp.beginPacket(FritzboxIP, 123);
  udp.write(paket, NTP_PACKET_SIZE);
  udp.endPacket();
  delay(1000);
  int cb = udp.parsePacket();
  if (!cb) {
    Serial.println("kein NTP Paket");
  }
  else {

    udp.read(paket, NTP_PACKET_SIZE);
    Serial.println("Zeit synchron");
  }
  udp.stop();


  unsigned long secsSince1900;
  // convert four bytes starting at location 40 to a long integer
  secsSince1900 =  (unsigned long)paket[40] << 24;
  secsSince1900 |= (unsigned long)paket[41] << 16;
  secsSince1900 |= (unsigned long)paket[42] << 8;
  secsSince1900 |= (unsigned long)paket[43];
  const unsigned long seventyYears = 2208988800UL;

  unsigned long aktTime = secsSince1900 - seventyYears;

  // UTC -> Europa und sommerzeit
  if (sommerzeit) {
    aktTime += 7200L;
  }
  else {
    aktTime += 3600L;
  }
  return aktTime;
}

PS : sehe gerade muss das nicht

// UTC -> Europa und sommerzeit
if (sommerzeit) {
aktTime += 7200UL;
}
else {
aktTime += 3600UL;

könnte es daran liegen ?

Versuche es mal mit der Standard-Abfrage:
 if (now-startTime > interval) ....
mit unsigned long Zeiten. Dann werden Überläufe richtig behandelt.

Ohne zu wissen wie dein Sketch arbeitet (weil ich noch am lernen bin), habe ich eine Verständnisfrage. Warum muss da eine if Anweisung für Sommerzeit enthalten sein, wenn du die Zeit doch von der Fritzbox holst?

Zum Problem, warum lässt du es zu, dass eine "Zeit" die mehr als x Minuten von der vorhergehenden Zeitsynchronisation abweicht als neue Zeit akzeptiert wird?

Gruß

MiReu

Rentner:
... jeweils etwa nach 3 Wochen Betrieb ohne Probleme.

Nur mal Ideen:

  1. 0xFFFFFFFF Millisekunden = 7 Wochen, mit Vorzeichen dreieinhalb Wochen.

unsigned long alarmzeit[12];
...
  for (int i = 0; i <= 11; i++) {
    alarmzeit[i] = i * 7200 + 15;
  }

Links vom ist unsigned long, rechts hingegen int, das könnte zu Überläufen führen. 11*7200+15=79.215

In dieser Richtung würde ich mal suchen.

Hallo,
ich hatte auch einmal ein ähnliches Problem bei meiner Bewässerung.
Die wird mit DCF77 synchronisiert.
Da hatte ich komischerweise auch immer mal ein Datum aus dem Jahr 2036 dabei.
Es wird 3 mal Abgefragt und alle Paritäten überprüft.
Also eigentlich kann da nichts falsches komme, außer es wird falsch gesendet.

Ich konnte das Problem nur lösen indem alles was über 2035 hinaus ging als Fehler werte.

MiReu:
Ohne zu wissen wie dein Sketch arbeitet (weil ich noch am lernen bin), habe ich eine Verständnisfrage. Warum muss da eine if Anweisung für Sommerzeit enthalten sein, wenn du die Zeit doch von der Fritzbox holst?

MiReu

Meine Fritzbox liefert auch nur Winterzeit.

Gruß Daneie

MiReu:
Ohne zu wissen wie dein Sketch arbeitet (weil ich noch am lernen bin), habe ich eine Verständnisfrage. Warum muss da eine if Anweisung für Sommerzeit enthalten sein, wenn du die Zeit doch von der Fritzbox holst?

Zum Problem, warum lässt du es zu, dass eine "Zeit" die mehr als x Minuten von der vorhergehenden Zeitsynchronisation abweicht als neue Zeit akzeptiert wird?

Gruß

MiReu

Hallo,

danke für deinen Beitrag

NTP Zeit schau mal hier

Die interne Uhr im ESP & Arduino ist keine Echtzeituhr da sie von der internen Quarzfrequenz abgeleite ist. Die ist insbesondere von der Thempertur abhängig nicht besonders genau. Es ist also üblich die Zeit regelmässig zu synchronisieren. Als Standard wird da meinst jede Stunde genommen, damit eine eventuelle Korkektur sehr klein bleibt.

Eine andere Variante ist der Einsatz von einem RTC Modul.

Heinz

agmue:
Nur mal Ideen:

  1. 0xFFFFFFFF Millisekunden = 7 Wochen, mit Vorzeichen dreieinhalb Wochen.

unsigned long alarmzeit[12];

...
  for (int i = 0; i <= 11; i++) {
    alarmzeit[i] = i * 7200 + 15;
  }



Links vom ist unsigned long, rechts hingegen int, das könnte zu Überläufen führen. 11*7200+15=79.215

In dieser Richtung würde ich mal suchen.

Hallo ,

danke für den Hinweis, aber an der Stelle kann es nicht sein, das ist die Stelle an der die Uhrzeiten gebildet werden an denen dan später per FTP an die Fritzbox gesendet wird. Das klappt eigendlich immer. Dennoch hast Du recht ich muss die Stellen noch mal prüfen.

Ich denke immer noch das Datum mit dem Jahr 2035 ist der eigentliche Urheber des Problems.

falls noch einem was auffällt , bin für jeden Hinweis dankbar.

Heinz

Hallo,

Ich konnte das Problem nur lösen indem alles was über 2035 hinaus ging als Fehler werte.

Ja, da hab ich auch schon dran gedacht, ich muss mir ja eigendlich keine Sorgen machen das mein Ding 2036 noch läuft. 1.1.2000 lässt grüssen :slight_smile: wenn ich nix mehr finde werde ich das machen.

Muss dann mal rausbekommen was die NTP Zeit für den 1.1.2036 ist.

Heinz

Hi

Damit das Ergebnis als unsigned long gerechnet wird, musst Du die erste Rechenoperation mit UL durchführen - hierfür die 7200 als UL deklarieren - dann sollten die Überläufe Geschichte sein.

alarmzeit[i] = 7200UL * i + 15;

Für den Timestamp:
Klick
(Mir spielen hier Ghostery und/oder NoScript einen Streich und spucken mir in die Suppe - bekomme nur den aktuellen Timestamp angezeigt ...)

MfG

postmaster-ino:
Hi

Damit das Ergebnis als unsigned long gerechnet wird, musst Du die erste Rechenoperation mit UL durchführen - hierfür die 7200 als UL deklarieren - dann sollten die Überläufe Geschichte sein.

MfG

Hallo,

ich hab die Berechnungen mit UL jetzt alle angepasst. mal sehen was in 3 Wochen passiert , da ist es wieder das Eichhörnchen :slight_smile: und der kleine steht auch wieder hinter der Ecke (Murfy meine ich ) . Und ich dachte mit der Rente wäre ich ihn endlich los geworden. :wink: 8)

Zu dem Link Timestamp

irgendwie klappt die Seite nicht, bei mir gibt die immer nur das aktulle Datum Zeit und den aktuellen Timestamp aus. Die Eingabe Felder werden immer damit überschrieben.

Wenn das in 3 Wochen dann immer noch auftritt werde ich den return wert der Sync Function nur aktualisieren wenn er plausiebel ist. Ansonsten kommt dann der alte now() Wert rein.

Danke Gruß Heinz

Hi

Irgendwie kann ich unter Linux aus einem Timestamp ein Datum machen (Das klappt - habe irgendwo einen Alias o.Ä. erstellt ... klar -> finde ich gerade nicht) - Das geht auch 'anders herum' ... nur eben akut keine Ahnung, wie ... oder wo :wink:

Zumindest bin ich beruhigt, daß mein Browser wohl doch nicht Alles von mir fern hält, sondern einfach die verlinkte Seite Mist ist :wink:
Man kann heute halt leider nicht mehr jedem Google-Treffer trauen feix.

MfG

Rentner:
... ich muss mir ja eigendlich keine Sorgen machen das mein Ding 2036 noch läuft. 1.1.2000 lässt grüssen :slight_smile:

Da kannst Du mal von Glück sprechen, es gibt ja auch noch das Jahr-2038-Problem :slight_smile:

aus Wikipedia...

Verwandtes Jahr-2036-Problem[Bearbeiten | Quelltext bearbeiten]
Eng verwandt zum Jahr-2038-Problem ist das Jahr 2036 (Numeronym: Y2K36). Am 7. Februar 2036 um 06:28:16 Uhr UTC läuft der Zähler des in Unix-Kreisen weit verbreiten Zeitsynchronisations-Protokolls NTP (Network Time Protocol) über. In modernen Implementierungen ist dieses Problem zwar behoben (siehe RFC 5905), doch sehr viele Geräte – besonders eingebettete Systeme – arbeiten noch nach dem alten Standard RFC 868. Auch hier ist der Hintergrund, dass die Zeitübermittlung als 32-Bit-Zahl in Sekunden stattfindet, jedoch nicht vorzeichenbehaftet und mit der Startzeit 1. Januar 1900, 00:00:00 UTC. Bei sehr ordentlicher Implementierung der Systeme kommt es sogar hier zu keinem (größeren) Problem während der Berechnung, da die Zeitsynchronisation nach einer Differenz-Methode arbeiten sollte. [6][7] Falls ein Client die bisherige Zeit nicht kennt (Kaltstart auf Systemen ohne Hardware-Uhr) und auch keine Prüfungen auf ein Mindest-Datum (z. B. das Datum seiner Kompilierung, oder Datum der NTP-Software) macht, könnte er versuchen, das Datum 1900-01-01 UTC zu übernehmen, welches nicht in Unix time dargestellt werden kann; dann kann die interne Uhr des betroffenen Systems auf „absurde“ Werte springen, was zu einem Totalausfall führen kann.

Hallo,

das erklärt zumindest mal das seltsame Datum 7.2.2036. mal abgesehen davon das ich am 7.2 Geburtstag habe.

also ein Überlauf

dann könnte ja ein Probelm der Berechnung durch fehlende UL spez. die Ursache gewsen sein . Mal abwarten

vielen Dank Heinz