Countdown String zusammensetzen, fehlerhafte Ausgabe

Hallo,

ich habe einen Countdown, ein long welches eine Zahl enthält, die die Restsekunden beinhaltet.
Nun gibt es allerdings einen Fehler bei der Anzeige.

Die sieht so aus:

:59:41

Normalerweise müsste das 1 Tag, 59 Minuten, 41 Sekunden sein.

Woran könnte das denn liegen?

long delta = restsekunden;
long years = delta / 31557600; delta = delta - (years * 31557600);
long months = delta / 2629800; delta = delta - (months * 2629800);
long weeks = delta / 604800; delta = delta - (weeks * 604800);
long days = delta / 86400; delta = delta - (days * 86400);
long hours = delta / 3600; delta = delta - (hours * 3600);
long minutes = delta / 60; delta = delta - (minutes * 60);
long seconds = delta;
myOLED.print(String(days)+":"+ String(hours)+":"+String(minutes)+":"+String(seconds), LEFT, 17);

Hallo,

lasse dir mit Serial.println Zwischenwerte deiner Variablen ausgeben.
Der Vorgang nennt sich debuggen.

Hallo,

da bekomme ich diese Ausgabe:
1
23
59
56

bei diesem Code
Serial.println(String(days));
Serial.println(String(hours));
Serial.println(String(minutes));
Serial.println(String(seconds));

Hallo,

und stimmt das oder nicht?
Wobei ich hätte lieber das gemacht ...

  Serial.println(days);
  Serial.println(hours);
  Serial.println(minutes);
  Serial.println(seconds);

Wenn die Debugwerte stimmen, dann zeige mal den gesamten Code.

timtailors:
Hallo,

ich habe einen Countdown, ein long welches eine Zahl enthält, die die Restsekunden beinhaltet.
Nun gibt es allerdings einen Fehler bei der Anzeige.

Die sieht so aus:

:59:41

Normalerweise müsste das 1 Tag, 59 Minuten, 41 Sekunden sein.

Woran könnte das denn liegen?

Dubiose Formeln. Eventuell falsch gewählte Variablentypen .

Wenn hours beispielsweise als "int" deklariert wäre (was man nicht sehen kann, weil Du nur einen kleinen Codeschnipsel zeigst und kein vollständiges Programmnm, dann würde in der Zeile

hours * 3600
je nach Wert von hours bereits in integer-Überlauf stattfinden, weil das Produkt den maximal darstellbaren Wert 32767 eines int sprengen könnte.

Im übrigen baust Du hier bereits einen kleinen Fehler ein:
long years = delta / 31557600; delta = delta - (years * 31557600);

Du gehst dabei davon aus, jedes Jahr hätte 365.25 Tage.

Tatsächlich hat kein einziges(!) Jahr eine gebrochene Anzahl an Tagen, sondern immer entweder 365 oder 366 Tage.

Möchtest Du genaue Werte ausrechnen? Oder nur ungefähr über den Daumen peilen und am Ende kommt es auf ein paar Stunden mehr oder weniger im Ergebnis nicht an?

Was soll das insgesamt darstellen?
Ist das delta ein Unterschied zwischen zwei Unixtime-Zeitangaben?
Und Du möchtest herausbekommen, um wieviele Jahre, Monate,Tage,Stunden,Minuten,Sekunden der ältere Zeitstempel älter ist als der jüngere?
Wenn Du das genau haben möchtest, geht es nicht ganz so einfach, wie Du es Dir momentan vorstellst.

Unabhängig von der Richtigkeit der Formel, bekomme ich diese Ausgabe:

Anfang
1:23:59:56

Testsketch:

void setup()
{
  Serial.begin(9600);
  Serial.println("Anfang");
  
  long delta = 172796;
  long years =  delta / 31557600;   delta = delta - (years * 31557600);
  long months = delta / 2629800;  delta = delta - (months * 2629800);
  long weeks = delta / 604800;  delta = delta - (weeks * 604800);
  long days = delta / 86400;  delta = delta - (days * 86400);
  long hours = delta / 3600;  delta = delta - (hours * 3600);
  long minutes = delta / 60;  delta = delta - (minutes * 60);
  long seconds = delta;
  Serial.println(String(days) + ":" + String(hours) + ":" + String(minutes) + ":" + String(seconds));
}

void loop() {}

Der Fehler liegt also woanders, denke ich mal.

agmue:
Unabhängig von der Richtigkeit der Formel, bekomme ich diese Ausgabe:

Anfang

1:23:59:56

Das ist ja auch richtig, das hast Du programmiert:

Das Programm gibt aus Serial.println("Anfang");
Und danach rechnet es ein delta = 172796 Sekunden in Stunden, Minuten, Sekunden um.

Und das Ergebnis ist "vier Sekunden weniger als zwei Tage), was soweit vollkommen richtig ist.

Eine Minute hat 60 Sekunden, eine Stunde 3600, ein Tag 86400, das sind Konstanten.

Aber efür ein Anzahl der Sekunden in einem Monat oder in einem Jahr gibt es keine Konstante, die sind von Fall zu Fall unterschiedlich.

Und zwar hängt die Anzahl der Sekunden in einem Monat von der Anzahl der Tage in genau diesem(!) Monat ab, die zwischen 28 und 31 liegen kann. Und die Anzahl der Sekunden in einem bestimmten Jahr hängt davon ab, ob dieses Jahr ein Schaltjahr mit 366 Tagen oder ein normales Jahr mit 365 Tagen ist.

Hallo jurs,
ich stimme Dir vollständig zu.

Mein Fokus liegt auf den mit widersprüchlich erscheinenden Aussagen:

timtailors:
Die sieht so aus:

:59:41

Normalerweise müsste das 1 Tag, 59 Minuten, 41 Sekunden sein.

Wo bleiben da die Stunden?

timtailors:
da bekomme ich diese Ausgabe:
1
23
59
56

bei diesem Code
Serial.println(String(days));
Serial.println(String(hours));
Serial.println(String(minutes));
Serial.println(String(seconds));

Unabhängig von der astronomischen und kalendarischen Richtigkeit, die natürlich wichtig ist, sollte Subtrahieren und Dividieren zum selben, reproduzierbaren Ergebnis führen. Das sehe ich als Grundlage aller weiteren Überlegungen.

Doc_Arduino:
Wenn die Debugwerte stimmen, dann zeige mal den gesamten Code.

Ja, denn der Fehler liegt wahrscheinlich im für uns nicht sichtbaren Teil.

Ja, denn der Fehler liegt wahrscheinlich im für uns nicht sichtbaren Teil.
[/quote]

Ich finde, sein Fehler ist bereits in seinem einleitenden Beitrag ganz klar ersichtlich: Er rechnet sowohl Monate als auch Jahre mit einerkonstanten Anzahl von Sekunden.

Solange seine Zeitdifferenz delta sich rein in Tagen, Stunden, Minuten und Sekunden ausdrücken läßt, passt das auch, weil Tage, Stunden und Minuten eine konstante Anzahl an Sekunden haben.

Sobald die Zeitdifferenz über einen Monat hinaus geht, macht er einen Fehler von mindestens mehreren Stunden. Die Größenordnung des Fehlers kannn man auch abschätzen: Weil er ein Jahr stets mit 365,25 Tagen rechnet, ein Jahr tatsächlich aber entweder 365 oder 366 Tage hat, rechnet er ab der Ausrechnung der Jahre mit einem delta-Fehler von entweder 0,25 Tagen (6 Stunden) oder 0,75 Tagen (18 Stunden) weiter und schleppt den dort bei den Jahren entstandenen Fehler bis zum Ende seiner Rechnung mit durch. Wenn er den Fehler nur bei den Jahren machen würde, dann wäre der in seiner Rechnung auftretende Fehler gegenüber der tatsächlichen Zeitdifferenz immer entweder 6 Stunden oder 18 Stunden Unterschied, sobald das delta mehr als ein Jahr umfaßt. Da er einen vergleichbaren Fehler aber auch beim Ausrechnen der Monate macht, kann der tatsächlich entstehende Fehler sowohl kleiner als 6 Stunden alsauch größer als 18 Stunden werden, je nachdem, ob sich die verrschiedenen Rechenfehler in seinem Mehr-als-ein-Jahr-Countdown addieren oder teilweise ausgleichen. Das hängt von den konkreten Ausgangswerten ab.

BTW: Da wir zum selben Thema (mit exakt denselben Rechenfehlern des Themenstarters) erst Ende Dezember 1016 ein Thema hier im Forum laufen hatten, allerdings ohne dass der damalige Themenstarter für eine Lösung interessiert hätte, sondern auch seine Frage war nur, warum seine Rechnung ein um Stunden falsches Ergebnis liefert, aber seine Frage war nicht, wie es richtig gerechnet werden müßte, habe ich mir dazu zwar ein paar Gedanken gemacht, aber nichts gepostet. Aber wer weiß, vielleicht möchte diesmal der Themenstarter ja wissen, wie eine Zeitdifferenz richtig in Jahre,Monate,Tage,Stunden,Minuten und Sekunden umgerechnet werden kann, ohne dabei Fehler zu machen.Dann könnte ich ggf. was vorschlagen.
Allerdings müßte der Themenstarter es sich abschminken, dass das alleine aus der Zeitdifferenz delta in Sekunden errechnet werden kann. Das funktioniert nicht.
Vielmehr braucht er beide Zeiten (Anfangszeit, Endzeit) seines Countdown in Unixtime oder Datum/Zeit, nur dann kann er mit einer Funktion Jahre,Monate,, Tage,Stunden,Minuten,Sekunden bis auf die Sekunde genau ausrechnen. Wenn er nur die Zeitdifferenz delta hat, funktioniert es nur für Tage,Stunden,Minuten,Sekunden die Countdown-Anazeige zu bilden.
Für Monate und Jahre im Countdown braucht man die konkreten Werte. für Anfangszeit und Endzeit des Countdowns.

Im englischen Sprachraum sind zum Beispiel Partnerschaftsuhren beliebte Arduino-Basteltgeschenke, die beispielsweise zum Valentinstag oder zur Hochzeit bzw. zum Hochzeistag verschenkt werden. Die Uhren zählen dann entweder aufwärts:
Verheiratet seit ... Jahren,Monaten,Tagen,Stunden,Minuten,Sekunden
Oder rückwärts:

  • noch ... Monate,Tage,Stunden,Minuten,Sekunden bis zum zehnten Hochzeitstag.

Vom Prinzip her nicht schwierig, man darf nur nicht anfangen, Jahre mit der krummen Tageszahl von 365,25 Tagen und Monate mit der krummen Tageszahl von 30,4375 Tagen zu rechnen, sondern reale Werte für "Tage pro Jahr" bzw. "Tage pro Monat" beim Countup oder Countdown verwenden.

Wobei mir einfällt: Die NASA hat hat auf ihren Seiten im Internet immer noch lgorithmen/Code aus Zeiten der Apollo11-Mission (erste Mondlandung) stehen, mit dem man für Zeit-/Datumsberechnungen auch auf 8-Bit Mikrocontrollern noch etwas anfangen kann.

der 26.03.2017 wird hierzulande übrigens voraussichtlich nur 23 Stunden haben...

michael_x:
der 26.03.2017 wird hierzulande übrigens voraussichtlich nur 23 Stunden haben...

Das kommt auf die zugrunde gelegte Bezugszeit an.

In Unixtime (UTC) hat der Tag natürlich 24 Stunden/86400 Sekunden.
Genau so in Zonenzeit UTC+1 (Zeitzone Berlin/Amsterdam).
Aber bezogen auf "lokale Ortszeit" ist der Tag eine Stunde kürzer,
weil die lokale Zeitzone sich während des laufenden Tages von UTC+1 nach UTC+2 ändert.