Betriebsstundenzähler - Zeit läuft beim Start kurz rückwärts

Programmierung der FHZ-Zentralen mit contronics homeputer Standard / homeputer Studio & WEB-Server

Moderator: Co-Administratoren

Antworten
SpiRu
Beiträge: 74
Registriert: 18.09.2012, 23:05
Wohnort: Deutschland.Freiburg

Betriebsstundenzähler - Zeit läuft beim Start kurz rückwärts

Beitrag von SpiRu » 03.10.2012, 19:51

Nachtrag: hat geschrieben: Das Phänomen ist nun abschließend geklärt.
Siehe dazu Beitrag Nr. 7.
Hallo zusammen,

ich habe hier so etwas wie einen Betriebsstundenzähler für mein Steuerungs-Programm programmiert, der als schönes Programmierbeispiel dienen könnte, wenn er denn richtig funktionieren würde. Das System bringt mich aber schier zur Verzweiflung, weil die Zeit hier anscheinend kurzzeitig mal rückwärts läuft. Hat vielleicht jemand eine Ahnung, wieso das so ist?

Code: Alles auswählen

***********************************************************************************************
** Objekt BetriebsZeit: [Zeichen]
**   Variablen:
**   Name           Typ      Startwert
**   letzterStart  [Zeit]    DATUM+UHRZEIT
**   Laufzeit      [Zeit]
**   gesamt        [Zeit]
**   jetzt         [Zeit]    [00:00:00]
**   u             [Uhr ]
**   i             [Zahl]
**   r             [Zahl]    0,00
**   VZ            [Zeichen]
**
** Erstaunlicherweise kann man als Startwert von Variablen auch Funktionen verwenden, was in
** der Hilfe nirgends dokumentiert ist! Funktioniert aber anscheinend, wie man via Ablauf-
** verfolgung nachprüfen kann: "letzterStart" enthält tatsächlich die Startzeit des Programms.
**     Oder auch die Zeit 8 Sekunden vor dem Start? Siehe "Debug"-Anweisungen im Code!
**     Uneklärliche Phänomene!
**
** BetriebsZeit.gesamt ist quasi der Betriebsstundenzähler dieses Programms und muss als
** persistenter Wert in *END gespeichert und in *INIT geladen werden.
**
** BetriebsZeit kann dann auch während des späteren Programmablaufs aufgerufen werden,
** um den visuellen Teil des Objekts zu aktualisieren.
**
** Da keine Objekte vom Typ [Zeit] bzw. [Uhr] vereinbart werden können, benötigt man - wie so
** häufig in diesem "System" - ein Würg-around, wenn man die "Betriebsstunden" in einer
** Visualisierungsansicht sichtbar machen will: Die Makro-interne Betriebszeit "gesamt" wird
** in den sichtbaren [Zeichen]-Teil des Objekts gespiegelt, wobei diese Zeit aus der
** ganzzahligen Komponente (Tage) und den Stunden im üblichen Zeitformat zusammengebaut werden
** muss, da es für Zeitdifferenzen >= 24 Stunden keine brauchbare Standard-Ausgabemethode gibt.
**
** *INIT muss
**     BetriebsZeit.gesamt laden und dann
**     BetriebsZeit aufrufen!
**
** *END muss ebenfalls
**     BetriebsZeit aufrufen und dann
**     BetriebsZeit.gesamt speichern!
***********************************************************************************************

jetzt:= DATUM + UHRZEIT
    ******* Debug ****************
    wenn jetzt < letzterStart dann
         Ticker:= "Fehler: 'jetzt' liegt zeitlich vor 'letzterStart'<<" +
                  letzterStart + "  letzterStart" + "<<" +
                  jetzt        + "  jetzt       " + "<<" + Ticker
         ******** einmalig ca. 8 Sekunden beim Programmstart!
    endewenn
    ******* Debug ****************

    ** Falls man erlauben will, dass die Betriebszeit zurückgesetzt werden kann:
    ****************************************************************************
    wenn BetriebsZeit = "*" dann
         gesamt      := 0
         letzterStart:= jetzt
    endewenn
    ****************************************************************************
Laufzeit    := jetzt  - letzterStart
gesamt      := gesamt + Laufzeit
letzterStart:= jetzt

    ******* Debug only *************
    Ticker:= Laufzeit + "  Laufzeit" + "<<" +
             gesamt   + "  gesamt"   + "<<" + Ticker
    ******* Debug only *************

************************************************************************
** allgem. Lösung für formatierte Ausgabe einer Zeitdifferenz (auch < 0)
************************************************************************
r:=  gesamt
wenn r < 0 dann
     VZ:= "-"
**** r := -r      <-- Bug, geht net!
     r := 0-r
sonst
     VZ:= "+"
endewenn
u:= gesamt
i:= r - 0,5
Betriebszeit:= VZ + i + " Tage " + u
"LetzterStart" im Objekt *INIT mit DATUM+UHRZEIT zu initialisieren, anstatt im Objekt selbst per Startwert, macht übrigens keinen Unterschied. An dem undokumentierten Feature, als Startwert keine Konstante, sondern Funktionen zu verwenden, kann's also kaum liegen!

Ich hoffe, dass man dieses Objekt mit einem Würg-around doch noch retten kann und mir hier keine prinzipiellen Denkfehler unterlaufen sind.

Mit der vordefinierten Variablen CT könnte man das Programm vielleicht noch etwas vereinfachen:
Hilfe.Variablen.CT hat geschrieben:Es gibt eine vordefinierte Variable des Typs Uhrzeit für jedes Objekt. Der Name der Variablen ist CT (für ChangeTime). In dieser Variablen wird die jeweils letzte Änderungszeit eines Objekts gespeichert. Mit der Funktion STOPPZEIT(Objektname.CT) kann ermittelt werden wie lange ein Objekt sich in seinem aktuellen Zustand befindet.
Mir ist aber noch nicht klar, bei welchen Ereignissen CT geändert wird (Zuweisung an BetriebsZeit?) und ob CT nur die Uhrzeit liefert oder auch das Datum, weil STOPPZEIT(CT) laut Hilfe ja nur eine Zeit zwischen 00:00:00 und 23:59:59 liefert. Vielleicht kann mich/uns da mal jemand aufklären! Bzw. der Hersteller die Hilfe diesbezüglich mal überarbeiten!
Hilfe.STOPPZEIT hat geschrieben:STOPPZEIT(Zeitvariable)
Diese Funktion gibt die Zeitdauerdifferenz zwischen der aktuellen Uhrzeit und der in der Zeitvariablen hinterlegten Zeit zurück. Es wird die reine Uhrzeitdifferenz ermittelt, Tage werden nicht berücksichtigt, d.h. als Ergebnis kann es keinen Wert grösser als 23:59:59 geben.
Zuletzt geändert von SpiRu am 06.10.2012, 10:54, insgesamt 3-mal geändert.
FHZ 1000 PC, Homeputer Studio V2.0 Rel. 120301
FHT80b-Raumregler, Windows XP (SP3)

Bugs? - Das sind keine Bugs! Das sind Features!

buempi
Ehrenmitglied
Beiträge: 12194
Registriert: 29.07.2006, 15:58
Wohnort: Schweiz
Danksagung erhalten: 5 Mal

Re: Betriebsstundenzähler - Zeit läuft beim Start kurz rückw

Beitrag von buempi » 03.10.2012, 20:44

Hallo SpiRu

Du hast eine sehr mühsame Art zu programmieren! Einerseits sparst du bei den Variablen-Bezeichnungen Tastenanschläge wo's nur geht; andererseits verschwendest du sie dann wieder anderswo...

Schon mal die erste Programmzeile: Wie kommst du dazu, der Zeitvariablen "jetzt" Datum+Uhrzeit zuzuweisen? - Falls das funktioniert: Tolles Feature von Homeputer! - Es gibt hier im Forum mindestens 1000 Beispiele mit

Code: Alles auswählen

jetzt := Zeit
Die Variable "Laufzeit" dürfte ja für die Aufnahme eines Zeitraumes (=Zeitdauer) vorgesehen sein. Dafür kann man nicht eine Variable vom Typ Zeit verwenden. Die ist für die Aufnahme eines Zeitpunktes wie z.B.

Code: Alles auswählen

03.10.12 17:40:21
bestimmt.

Dann schreibst du was, dass "die Zeit hier anscheinend kurzzeitig mal rückwärts läuft". Wo und wann? Beim Start, zu jeder vollen Stunde oder immer am 29. Februar?

Wenn du so hohe Anforderungen an die von dir verwendete Software richtest, solltest du bei einer eigenen Arbeit ähnliche Massstäbe anlegen.

Ich habe mir dein Makro nicht weiter im Detail angeschaut, denn ein Betriebsstundenzähler programmiert sich ganz einfach so:

Code: Alles auswählen

** Makro im Aktor - Ausführung bei Änderung
** EinschaltZeit ist eine Variable vom Typ Zeit
** AktuelleLaufzeit und TotalLaufzeit sind Variablen vom Typ Zahl, Startwert 0,0

wenn Aktor eingeschaltet dann
   EinschaltZeit    := Zeit
sonst
   AktuelleLaufzeit := Zeit - EinschaltZeit
   TotalLaufzeit    := TotalLaufzeit + AktuelleLaufzeit
endewenn
Viele Grüsse
Bümpi

SpiRu
Beiträge: 74
Registriert: 18.09.2012, 23:05
Wohnort: Deutschland.Freiburg

Re: Betriebsstundenzähler - Zeit läuft beim Start kurz rückw

Beitrag von SpiRu » 03.10.2012, 22:47

Hi buempi,
bei der Funktion ZEIT hatte ich doch glatt wieder mal Tomaten auf den Augen:
Hilfe.ZEIT hat geschrieben:ZEIT
Diese Funktion ergibt die Zeit in einem internen Format.
...
Weiterhin ist der Typ Zeit nützlich um die komplette Zeit (also Datum und Uhrzeit zu merken und auszugeben. Wenn eine Variable dieses Typs einem Zeichen-Objekt zugewiesen wird, werden Datum und Uhrzeit als Text ausgegeben.
buempi hat geschrieben:Es gibt hier im Forum mindestens 1000 Beispiele mit

Code: Alles auswählen

jetzt := Zeit
Nachdem ich statt DATUM+UHRZEIT jetzt überall den Funktionsaufruf ZEIT eingesetzt habe, läuft's wie es sollte. Zwei unmittelbar aufeinanderfolgende Aufrufe von ZEIT ergeben keine negative Differenz, im Gegensatz zu den vorherigen 2 aufeinanderfolgenden Aufrufen von DATUM+UHRZEIT. Das ist ein eindeutiger und stets reproduzierbarer Systemfehler!
buempi hat geschrieben: Die Variable "Laufzeit" dürfte ja für die Aufnahme eines Zeitraumes (=Zeitdauer) vorgesehen sein. Dafür kann man nicht eine Variable vom Typ Zeit verwenden. Die ist für die Aufnahme eines Zeitpunktes wie z.B.

Code: Alles auswählen

03.10.12 17:40:21
bestimmt.
Da muss ich Dir entschieden widersprechen! Eine Zeitvariable speichert die Zeit als Gleitkomma-Zahl (Real), wobei der Wert 1 einem Tag entspricht. Tage, Stunden etc. werden durch Bruchteile von 1 dargestellt: 1 Tag = 1/24, 1 Stunde = 1/24/60 etc. Es ist reine Interpretations-Sache, ob man diesen Wert nun als Zeitdauer (relativ zu 0) interpretiert oder als Abstand von einem Bezugszeitpunkt (1899-12-30 00:00:00). Einen eigenen Typ [Zeit](Dauer), mit dem man eine passende Ausgabe-Formatierung steuern könnte, gibt es im System leider nicht (möchte ich aber hier als Verbesserungsvorschlag einbringen)!

Mangels komfortabler Formatierungs-Funktionen oder explizitem Type-Casting wie beispielsweise in "C" kann man hier die Ausgabeformatierung praktisch nur durch die Verwendung des passenden Variablentyps steuern. Dann wird entweder nur die Uhrzeit-Komponente ausgegeben (Typ [Uhr]), nur das Datum (Typ [Datum]) oder alles (Typ [Zeit]). Für die interne Repräsentation macht es aber keinen Unterschied, von welchem Zeit-(Unter-)Typ eine Variable ist. Sie ist eigentlich immer nur eine type-gecastete Real-Variable.
FHZ 1000 PC, Homeputer Studio V2.0 Rel. 120301
FHT80b-Raumregler, Windows XP (SP3)

Bugs? - Das sind keine Bugs! Das sind Features!

SpiRu
Beiträge: 74
Registriert: 18.09.2012, 23:05
Wohnort: Deutschland.Freiburg

Re: Betriebsstundenzähler - Zeit läuft beim Start kurz rückw

Beitrag von SpiRu » 04.10.2012, 00:28

buempi hat geschrieben:Dann schreibst du was, dass "die Zeit hier anscheinend kurzzeitig mal rückwärts läuft". Wo und wann? Beim Start, zu jeder vollen Stunde oder immer am 29. Februar?
Hier, beim 1. Aufruf! Aber nur genau 1 mal! Also nicht manchmal, sondern immer beim erstmaligen Aufruf.

Code: Alles auswählen

letzterStart:= ZEIT
muss unmittelbar vorher ausgeführt worden sein, denn woher sollte sonst der mit 8 Sekunden ziemlich konstant differierende Wert kommen?

Code: Alles auswählen

jetzt:= DATUM+UHRZEIT
    ******* Debug ****************
    wenn jetzt < letzterStart dann
         Ticker:= "Fehler: 'jetzt' liegt zeitlich vor 'letzterStart'<<" +
                  letzterStart + "  letzterStart" + "<<" +
                  jetzt        + "  jetzt       " + "<<" + Ticker
         ******** einmalig ca. 8 Sekunden Differenz beim Programmstart!
    endewenn
    ******* Debug ****************
Also klarer kann man's wohl nicht beschreiben! Aber wenn man sich den Code halt gar nicht erst anschaut... :roll:

Code: Alles auswählen

jetzt:= DATUM+UHRZEIT habe ich mittlerweile mit
jetzt:= ZEIT ersetzt
und jetzt geht's.
Zuletzt geändert von SpiRu am 06.10.2012, 10:51, insgesamt 1-mal geändert.
FHZ 1000 PC, Homeputer Studio V2.0 Rel. 120301
FHT80b-Raumregler, Windows XP (SP3)

Bugs? - Das sind keine Bugs! Das sind Features!

buempi
Ehrenmitglied
Beiträge: 12194
Registriert: 29.07.2006, 15:58
Wohnort: Schweiz
Danksagung erhalten: 5 Mal

Re: Betriebsstundenzähler - Zeit läuft beim Start kurz rückw

Beitrag von buempi » 04.10.2012, 00:50

SpiRu hat geschrieben:Da muss ich Dir entschieden widersprechen! Eine Zeitvariable speichert die Zeit als Gleitkomma-Zahl (Real), wobei der Wert 1 einem Tag entspricht.
.... es ist mir durchaus bewusst, dass eine Zeitvariable intern nicht als dd.mm.jjjj hh:mm:ss gespeichert wird. Wahrscheinlich sogar als Real in Sekunden (vor dem Komma) und Bruchteilen von Sekunden (nach dem Komma).

Entscheidend ist aber, was nachher weiter damit geschieht, abhängig vom Variablen-Typ. Und da muss man sich eben an die Konventionen halten, wenn man sich nicht ständig selbst Steine in den Weg legen will:

Code: Alles auswählen

ZeitA := "31.12.12 12:00:00"
ZeitB := "30.12.12 12:00:00"

MeineZeit   := ZeitA - ZeitB
MeineZahl   := ZeitA - ZeitB

Anzeige := MeineZeit
warte("00:00:03")
Anzeige := MeineZahl
SpiRu hat geschrieben:im Gegensatz zu den vorherigen 2 aufeinanderfolgenden Aufrufen von DATUM+UHRZEIT. Das ist ein eindeutiger und stets reproduzierbarer Systemfehler!
... es ist also ein Systemfehler, wenn man Steine auf den Weg legt indem man einer Variablen einen undefinierten Wert zuweist und dann darüber stolpert!

Viele Grüsse
Bümpi

SpiRu
Beiträge: 74
Registriert: 18.09.2012, 23:05
Wohnort: Deutschland.Freiburg

Re: Betriebsstundenzähler - Zeit läuft beim Start kurz rückw

Beitrag von SpiRu » 04.10.2012, 03:32

buempi hat geschrieben:.... es ist mir durchaus bewusst, dass eine Zeitvariable intern nicht als dd.mm.jjjj hh:mm:ss gespeichert wird. Wahrscheinlich sogar als Real in Sekunden (vor dem Komma) und Bruchteilen von Sekunden (nach dem Komma).
Nee, die Sekunden sind garantiert nicht vor dem Komma! Wenn Du 1,0 auf einen Datumswert addierst, erhöht sich der Tag um 1.

Eine den Wenigsten klare Eigenschaft der Zeit als Real-Zahl ist, dass man damit auch prähistorische Ereignisse vor Milliarden von Jahren (bzw. auch in der Zukunft) datieren kann. Zwar sinkt dann die absolute Auflösung, die relative bleibt aber immer gleich, da die Bitanzahl der Mantisse konstant ist. Bei kleinen Zeitdifferenzen kannst Du sogar Nanosekunden auflösen, bei galaktischen Zeiträumen größenordnungsmäßig nur noch Jahre oder Jahrtausende.

Allerdings wirst Du bei absolut unüblichen Zeitauflösungen Probleme mit Formatschablonen wie beispielsweise JJJJ-MM-TT HH:mm:ss bekommen. Da bräuchte man dann nach oben hin z.B. JJJJJJJJJJJJJJJ-MM-TT HH. Wie man Sekundenbruchteile anzeigen lassen kann, bin ich aber überfragt.
buempi hat geschrieben: Entscheidend ist aber, was nachher weiter damit geschieht, abhängig vom Variablen-Typ. Und da muss man sich eben an die Konventionen halten, wenn man sich nicht ständig selbst Steine in den Weg legen will:

Code: Alles auswählen

ZeitA := "31.12.12 12:00:00"
ZeitB := "30.12.12 12:00:00"

MeineZeit   := ZeitA - ZeitB
MeineZahl   := ZeitA - ZeitB

Anzeige := MeineZeit
warte("00:00:03")
Anzeige := MeineZahl
SpiRu hat geschrieben:im Gegensatz zu den vorherigen 2 aufeinanderfolgenden Aufrufen von DATUM+UHRZEIT. Das ist ein eindeutiger und stets reproduzierbarer Systemfehler!
... es ist also ein Systemfehler, wenn man Steine auf den Weg legt indem man einer Variablen einen undefinierten Wert zuweist und dann darüber stolpert!
So ein Schmarrn! Wieso sollte DATUM+UHRZEIT undefiniert sein? Ungeschickt bzw. unnötig umständlich ja, aber keinesfalls undefiniert! Wenn

Code: Alles auswählen

z1:= ZEIT
z2:= DATUM+UHRZEIT
wenn z1 > z2 dann
        Sprachausgabe("Systemfehler! Zukunft liegt zeitlich vor Vergangenheit!")
endewenn
ist das eindeutig ein Systemfehler! Allenfalls wenn Du Millisekunden-genau um Mitternacht DATUM+ZEIT abfrägst, kann es sein, dass der eine Part noch vom Vortag ist und der andere schon vom neuen. Auf Gleichheit darf man natürlich nicht prüfen, da die interne Zeitauflösung unbekannt ist und theoretisch durchaus im Nanosekunden-Bereich liegen könnte, die Zeit sich also zwischen 2 Funktionsaufrufen häufig schon wieder geändert haben könnte.

Und was den davor stehenden Code-Schnipsel betrifft: genau das ist doch auch meine Rede! Aber offensichtlich hast Du Probleme, meine Ausführungen zu verstehen. :roll:
FHZ 1000 PC, Homeputer Studio V2.0 Rel. 120301
FHT80b-Raumregler, Windows XP (SP3)

Bugs? - Das sind keine Bugs! Das sind Features!

SpiRu
Beiträge: 74
Registriert: 18.09.2012, 23:05
Wohnort: Deutschland.Freiburg

Re: Betriebsstundenzähler - Zeit läuft beim Start kurz rückw

Beitrag von SpiRu » 06.10.2012, 00:47

Das Phänomen ist nun abschließend geklärt.

Ursache Nr. 1: UHRZEIT liefert die auf glatte 5 Sekunden abgerundete Zeit, ZEIT hingegen die aktuelle Zeit sogar auf Sekundennbruchteile genau.
Ursache Nr. 2: Zeit-Variablen können aufgrund eines "sehr originellen" :roll: System-Konzepts nicht mit exakt 0 vorbelegt werden.
Ursache Nr. 3: Zeit-Differenzen können aufgrund einer undokumentierten System-Anomalie nicht negativ werden. In dem Fall wird der Absolut-Betrag Modulo 1 Tag zürückgeliefert, also zwischen "00:00:00" und "23:59:59,999...". (das entspricht dem Nachkomma-Anteil des intern als Real-Zahl dargestellten Wertes, bei dem 1,0 einem Tag entspricht.)

Details dazu in
FHZ 1000 PC, Homeputer Studio V2.0 Rel. 120301
FHT80b-Raumregler, Windows XP (SP3)

Bugs? - Das sind keine Bugs! Das sind Features!

Antworten

Zurück zu „homeputer Studio / Standard: Programmierbeispiele“