Vorschlag zu TIMECHECK

Begonnen von EMV-Fuzzi, 31. Januar 2011, 00:28:40

Vorheriges Thema - Nächstes Thema

0 Mitglieder und 1 Gast betrachten dieses Thema.

EMV-Fuzzi

Hallo Entwickler!

Bei Zeit-Berechnungen mit TOD-Variablen kann es vorkommen,
daß ein Ergebnis größer 24 Stunden herauskommt. Wenn ich nun
diese Variable für die STOP-Zeit benutze, schaltet TIMECHECK
den Ausgang um 00:00:00 Uhr ab, was nicht richtig ist.

Vorschlag:
IF (STOP >= HOUR_TO_TOD(24)) THEN
STOP := STOP - t#24h;
END_IF


Wenn wir das allgemeingültig machen wollen, sollte eine WHILE-
Schleife das Problem lösen:
WHILE (STOP >= HOUR_TO_TOD(24)) DO
STOP := STOP - t#24h;
END_WHILE


Gruß
  EMV-Fuzzi

hugo

das werden wir uns fürs nächste release ansehen

hugo

tod ist nur für 00:00 - 23:59:59.999 definiert.
der überlauf dürfte nicht auf allen systemen vorhersehbare ergebnisse liefern.

so wie beim teilen durch null muss der anwender sicherstellen das die eingangswerte der funktion dem wertebereich entsprechen.

EMV-Fuzzi

Nochmal ein paar Gedanken zu dem Thema:
Daß ich einer TOD-Variablen keine Zeiten größer 24h zuweisen kann,
ist klar und richtig!

todAbschaltZeit := tod#24:02:00;

erzeugt die Fehlermeldung:
Fehler 3906: Testprogramm (23) Ungültige Tageszeitkonstante

Mir ging es aber um Berechnungen mit TOD-Variablen, die, im Gegensatz zu
anderen Zahlentypen (INT, WORD, etc.), offensichtlich keinen automatischen
Übertrag generieren, wenn der Wertebereich überschritten wird.

todAbschaltZeit :=  tod#23:59:00 + MINUTE_TO_TIME(3);

compiliert fehlerfrei und zeigt auf zwei komplett verschiedenen Hardware-
Plattformen UND bei Simulation im Online-Modus dies an:

todAbschaltZeit := TOD#24:02:00;

Daher meine Idee, die überzähligen 24 Stunden dort zu eliminieren,
wo sie auf jeden Fall zu falschen Ergebnissen führen...


Gruß
  EMV-Fuzzi


PS: "CoDeSys 2.3.9.22 Build Jun 10 2010"

hugo

was du so einfach testest ist sehr diffizil.

1. codesys ist nicht gleich codesys.
wenn du ein projekt compilierst linkt der compiler je nach zielhardware und cpu ganz unterschiedliche interne libraries. andere cpu's brauchen eben anderen code.
deshalb wird sich dein code unter umständen auf verschiedenen cpu's unterschiedlich verhalten.
nur weil du ein oder 2 systeme testest ist das noch keine plausible aussage.

sicherer code wird es nur dann wenn man keine derartigen experimente macht.
codesys 9.3.22 verhält sich eben ja nach zielhardware und cpu ganz anders.

mur ein beispiel selbst diue TRUNC funktion für negative zahlen liefert auf einer wago842 cpu andere ergebnisse als auf einer wago841 usw usw
wir schlagen uns bei oscat seit jahren mit diesem thema rum und haben gelernt keine solchen experimente zu machen weil das keinen sichere3n portierbaren code ergibt.

oscat benutzt derzeit gleichen  code auf pcworx, twincat, codesys und eben auf unterschiedlichster hardware.

wir haben schon hundertemale feststellen müssen das code mit ein und dem selben codesys für unterschiedliche zielhardware compiliert andere ergebnisse lieferet.

hugo

was du möchtest ist eine neue funktion für den datentyp time oder gar dt !
hierfür aber die tod funktion zu vergewaltigen möchten wir dringend abraten

peewit

hallo

das mit den verschiedenen verhalten ist leider wirklich so grass !
ein praktisches beispiel bei PCWORX (Phoenix Contact)

REAL_TO_DINT

liefert bei ILC 1xx und ILC 3xx komplett verschiedene ergebnisse
einmal wird auf und einmal wird abgerundet !

damit wir einen kompatiblen code schaffen, habe ich für PCWORX folgendes erfunden

anstatt der original IEC-Function REAL_TO_DINT wurde in allen bausteinen _REAL_TO_DINT verwendet

diese function erkennt selber ob falsch gerundet wird, und nutzt einen ersatzcode


IF REAL_TO_DINT(0.5) = DINT#1 THEN
  _REAL_TO_DINT := REAL_TO_DINT(x);
  RETURN;
END_IF;

IF X > 0.0 THEN
  _REAL_TO_DINT := REAL_TO_DINT(x+0.5);
ELSIF X < 0.0 THEN
  _REAL_TO_DINT := REAL_TO_DINT(x-0.5);
ELSE
  _REAL_TO_DINT := DINT#0;
END_IF;



EMV-Fuzzi

Eine letzte Anmerkung von mir:
Ich akzeptiere Eure Argumentationen, sehe aber das Rechnen mit TOD-Variablen (zumindest für
Codesys und meine Ziel-Hardware) über die 24-Stunden-Marke hinaus als zulässig an!

Zitat aus der Codesys-Hilfe:
Die Datentypen TIME, TIME_OF_DAY (kurz TOD), DATE und DATE_AND_TIME (kurz DT)
werden intern wie DWORD behandelt.
Bei TIME und TOD wird die Zeit in Millisekunden angegeben, wobei bei TOD ab
00:00 Uhr gerechnet wird.


Hieraus ergibt sich für den Datentyp TOD ein interner Umfang von über 49 Tagen (in
Millisekunden), von dem ich m.E. durchaus mehrfach 24 Stunden subtrahieren kann,
solange ich mich im positiven Bereich bewege.

peewit

#8
hallo

natürlich kannst du es auf deiner plattform so machen

die codesys-doku ist halt keine referenz für die anderen hersteller


das steht auch in der codesys doku

Zitat
TIME_OF_DAY-Konstanten, zum Speichern von Uhrzeiten:

Eine TIME_OF_DAY-Deklaration beginnt mit "tod#", "TOD#", "TIME_OF_DAY#" oder "time_of_day#", anschließend können Sie eine Uhrzeit angeben in der Schreibweise: Stunde:Minute:Sekunde. Sekunden können dabei als reelle Zahlen angegeben werden, es können also auch Sekundenbruchteile angegeben werden. Mögliche Werte: 00:00:00 bis 23:59:59.999.



hugo

wenn du über einen tag hinaus rechnen willst warum nimmst du dann nicht einfach time
time geht eben genau bis 49 tagen das ist der unterschied zu tod

EMV-Fuzzi

@peewit:
Stimmt, andere Hersteller können ihre Datentypen anders definieren.

@hugo:
Ich habe TOD genommen, weil ich es mir einfach machen wollte, da die von
mir genutzten Bausteine (z.B. SUN_TIME, TIMECHECK, ...) dies als Eingangs-/
Ausgangs-Typen benutzen!
In diesem Zusammenhang ist mir dann aufgefallen, daß ich beim Berechnen
der STOP-Zeit über die 24h-Marke kommen KÖNNTE! Das würde mir auch bei
Benutzen von TIME passieren, wobei ich dann für TIMECHECK wiederum
in TOD konvertieren müßte...
Dann hätte ich die gleiche Aufgabe mit einem anderen Datentypen...

hugo

du kannst und solltest funktionen wie tod_to_time und umgekehrt nutzen.

eine einfache möglichkeit auf 24h zu begrenzen wäre

udint_to_tod(tod_to_udint(xxx) mod 86400000)