Ankündigung

Einklappen
Keine Ankündigung bisher.

In der Tiefe: Validierungskonzept

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • saft6luck
    antwortet
    @Tessi:
    Ich habe noch keinen Hinweis im Handbuch gefunden, dass die Reihenfolge im Code nicht der Ausführungsreihenfolge entspricht. Die angesprochene parallele Ausführung enthält auch hierzu keinen Anhaltspunkt (trägt eher zur Verwirrung bei). Wenn tatsächlich umsortiert wird, muss das entsprechend beschrieben werden oder soll die von Michael gerne zitierte Blondine sich da einen Reim drauf machen müssen???

    Verschachtelungen sind beim eibPC leider notwendig, den nur auf der obersten Ebene gilt der vereinfachte Syntax (das Validierungsschema = Event-getrieben). Die nächsten Ebenen sind eigentlich normale Logik, auch wenn das im Handbuch stark verkompliziert ist. (Wo findest du denn den Hinweis, dass man Verschachtelungen vermeiden soll? Ich hab da nur else in Erinnerung?).

    Ansonsten gebe ich dir Recht, ob ein Kommando ausgeführt wird, oder nicht definiert sich laufend neu

    Einen Kommentar schreiben:


  • Tessi
    antwortet
    Irgendwo im Handbuch steht (oder stand zumindest in älteren Versionen), das man verschachtelte Strukturen vermeiden solle, weil sie überwiegend eben nicht zu dem Ergebnis führen, das ein "normaler" Programmierer entsprechend seinen Erfahrungen mit üblichen Sprachen erwarten wird. Hält man sich daran, ist es nicht mehr wichtig, ob eine Veränderung des Wertes einer Variable noch im selben oder erst im nächsten Zyklus im restlichen Code sichtbar wird.
    Und ganz offensichtlich sind Statements wie
    a=a+1
    ausgesprochen problematisch, da sie je nach Situation/Abhängigkeit nur ein einziges Mal oder aber "endlos" in jedem Zyklus ausgeführt werden.
    Entzerren läßt sich das, indem man für jeden Schritt eine neue Variable verwendet, wodurch der Output eben nicht den Input verändert und diesen so ständig wieder invalidiert. Das ist zunächst ungewohnt, aber der EPC folgt nun mal nicht den Regeln gewohnter Sprachen, also sind auch andere Lösungen angesagt.

    Die Frage, was denn tatsächlich gesendet wird, wenn innerhalb eines Zyklus mehrfach und mit verschiedenen Werten auf eine GA geschrieben wird dürfte nur in absoluten Ausnahmefällen interessant sein, denn normalerweise sollten zwischen zwei "Zugriffen" auf die selbe GA mehr als nur ein Zyklus liegen - allein schon deshalb, weil der EPC während der Übertragung eines einzigen Telegramms normalerweise mehrere Zyklen schafft und mehrfaches Schreiben in einem Zyklus ziemlich schnell den Bus überfordert.

    Im konkreten Fall würde ich den Zeitversatz rein mathematisch ohne if abhandeln - Uhrzeit erst in Minuten umrechnen, Versatz hinzurechnen, das Ergebnis wieder in Stunden und Minuten zerlegen. Wann welche Operation ausgeführt wird, entscheidet dann das Validierungsschema und solange dabei kein Ergebnis Werte beeinflußt, von denen es direkt oder indirekt abhängt, ist auch egal, ob die einzelnen Statements im selben oder in aufeinanderfolgenden Zyklen abgearbeitet werden.

    So wie ich das bislang verstanden habe, gibt es ja nicht einmal eine Garantie dafür, das die Statements während eines Durchlaufs auch in der Reihenfolge bearbeitet werden, in der sie im Code stehen.
    So wie ich das verstanden habe, muß man davon ausgehen, das alle Statements quasi parallel ausgeführt werden, so das die dabei in einem bestimmten Statement erfolgenden Änderungen erst im nächsten Zyklus für alle anderen Statements sichtbar werden. Wobei man sich darauf aber wiederum auch nicht verlassen sollte...

    Mein ganz persönliches Problem ist, das ich trotzt aller bislang gelesenen Erklärungen in vielen Fällen immer noch nicht sicher vorhersagen kann, was ein gegebener Code tatsächlich tun wird, da ich nicht weiß, was der Compiler tatsächlich daraus macht und was da zur Laufzeit dann passiert.

    Für die meisten Funktionen ist recht genau erklärt, was sie tun. Aber wann sie es tun, dafür wir immer auf das Validierungsschema verwiesen und genau dieses hat sich mir immer noch nicht lückenlos erschlossen.
    Ich glaube vorhersagen zu können, was ein Statement machen wird, wenn es abgearbeitet wird, aber ich kann einfach immer noch nicht sicher sagen, wann ein Statement abgearbeitet wird, und wann nicht. Geht mir das jetzt allein so oder habe ich da noch Leidensgenossen?

    Einen Kommentar schreiben:


  • saft6luck
    antwortet
    Zitat von pio Beitrag anzeigen
    Ich hatte geschrieben, dass "trigger" durch einen pbutton gesetzt, und somit auch automatisch wieder rückgesetzt würde. Die dazu notwendige Logik zeigt mein Beispiel nicht. Ich will auch nicht auf change(trigger) was machen, sondern nur wenn trigger==1. Aber das nur zur Erläuterung ....
    [+]
    So hatte ich das auch mal verstanden. Mich hatte jetzt nur dein Statement aus deinem Post 223 irritiert.
    Darher bin ich auf trigger eingegangen, da meine Aussage (und die kommt ja von Michael) sich nur auf change() bezieht (was natürlich in dem if irgendwie enhalten ist), aber eben keine Auswirkung hat, wenn da unterschiedliche Variablen im Spiel sind.

    Das würde der reinen SPS-Lehre entsprechen (Eingangsabbild aktualisieren --> komplett verarbeiten --> Ausgangsabbild auf die Ausgänge schreiben).
    Das hatte ich ja auch schon festgestellt, nur sind da ein paar Leute explodiert. Es wagt jemand die Verarbeitung des eibPCs mit der einer SPS zu vergleichen, ts, ts, Steine, schöne frische Steine ...

    Einen Kommentar schreiben:


  • pio
    antwortet
    Zitat von saft6luck Beitrag anzeigen
    1. mit der Änderung von trigger hast du recht, der Wert ändert sich aber in deinem Beispiel nicht mehr
    Ich hatte geschrieben, dass "trigger" durch einen pbutton gesetzt, und somit auch automatisch wieder rückgesetzt würde. Die dazu notwendige Logik zeigt mein Beispiel nicht. Ich will auch nicht auf change(trigger) was machen, sondern nur wenn trigger==1. Aber das nur zur Erläuterung ....

    2. Die Zuweisung von a=0 wird sofort gültig, d.h. die nächste Abfrage wird auch wahr und somit wird a wieder 1.
    So hatte ich das auch mal verstanden. Mich hatte jetzt nur dein Statement aus deinem Post 223 irritiert.

    (Unverständlich finde ich, dass alle eingefügten writes(GA, a) nur den Endwert von a ausgeben würden, unabhängig von der Position im Code, aber das ist schon wieder ein anderes Thema).
    Das würde der reinen SPS-Lehre entsprechen (Eingangsabbild aktualisieren --> komplett verarbeiten --> Ausgangsabbild auf die Ausgänge schreiben). Damit vermeidet man z.B., dass erst das Licht ein und dann gleich wieder ausgeschaltet wird (auf ein Beispiel des Eib übertragen und unter Vernachlässigung der Tatsache, dass die Zykluszeit des EibPC wesentlich schneller ist als die Zeit, 2 Telegramme direkt hintereinander auf den Bus zu schreiben).
    Andererseits kann ich mir auch Situationen vorstellen, in denen ich das Verhalten explizit möchte: ich mache eine Berechnung, als Ergebnis sende ich dann einen Trigger auf den Bus, der irgendwo überwacht wird. Wenn der Trigger länger ansteht als z.B. 500ms, dann löst das überwachende Device ne Aktion aus.
    Wenn ich jetzt im selben Zyklus des EibPCs noch ein invertierendes Telegramm in die Warteschleife setzten kann, noch bevor ich im selben Verarbeitungszyklus schon 10 weitere Telegramme in der Schlange platziert habe, und die Gesamtsendedauer aller 11 Folge-Telegramme die 500ms überschreitet, dann wird mein Eib-Device doch nichts machen.

    Oder landen die Telegramme etwa in zufälliger Reihenfolge im Sendepuffer?

    Einen Kommentar schreiben:


  • saft6luck
    antwortet
    Zitat von pio Beitrag anzeigen
    Das bedeutet, dass folgender Code so funktionieren würde:
    (trigger geht immer nur für einen Verarbeitungszyklus auf 1, z.B. bei Druck auf einen Webbutton)

    [highlight=epc]
    a = 1b01
    trigger = 0b01

    if trigger then {
    if a==1 then a=0; "mache noch irgendwas" endif;
    if a==0 then a=1; "mache noch irgendwas anderes" endif
    } endif
    [/highlight]Wird trigger jetzt 1, dann wird das erste innere if aufgerufen und a=0 gesetzt, aber NICHT mehr das zweite innere if, da das Nullsetzen von a erst im folgenden Verarbeitungszyklus "aktiv" wird.
    Michael möge mir verzeihen, aber ich versuche mich mal in der Antwort:
    1. mit der Änderung von trigger hast du recht, der Wert ändert sich aber in deinem Beispiel nicht mehr -> man wird so nicht erkennen, ob es im nächsten Zyklus einen change() gibt.

    2. Die Zuweisung von a=0 wird sofort gültig, d.h. die nächste Abfrage wird auch wahr und somit wird a wieder 1. (Unverständlich finde ich, dass alle eingefügten writes(GA, a) nur den Endwert von a ausgeben würden, unabhängig von der Position im Code, aber das ist schon wieder ein anderes Thema).

    Das Verhalten (ich empfinde es als Problem) zeigt sich bei folgendem Konstrukt:

    [highlight=epc]
    a=sunriseminute()
    /* 5 Minuten addieren und Überlauf beachten */
    if change(a) then {
    if a>54 then a=a-55 else a=a+5 endif
    } endif
    [/highlight]

    Hier würde ich normalerweise erwarten, dass a um 5 erhöht wird und der Wert auf 59 begrenzt wird. Leider wird der change() aber im nächsten Zyklus erneut auftreten und somit a ständig hochzählen. (Abgesehen davon, dass das else noch im gleichen Zyklus ausgeführt wird ...).

    Oder anderes Beispiel:
    [highlight=epc]
    a = "Taster-GA"
    if change( a ) then {
    a = !a;
    write (a);
    } endif
    [/highlight]

    Hier wird a endlos toggeln.

    Beispiele sind leider ungetestet, da mein eibPC momentan loggen soll.

    Einen Kommentar schreiben:


  • pio
    antwortet
    Zitat von saft6luck Beitrag anzeigen
    Immerhin weiß ich jetzt auch, dass Änderungen von Variablen im nächsten Zyklus erscheinen.
    Das bedeutet, dass folgender Code so funktionieren würde:
    (trigger geht immer nur für einen Verarbeitungszyklus auf 1, z.B. bei Druck auf einen Webbutton)

    Code:
    a = 1b01
    trigger = 0b01
    
    if trigger then {
         if a==1 then a=0; "mache noch irgendwas" endif;
         if a==0 then a=1; "mache noch irgendwas anderes" endif
    } endif
    Wird trigger jetzt 1, dann wird das erste innere if aufgerufen und a=0 gesetzt, aber NICHT mehr das zweite innere if, da das Nullsetzen von a erst im folgenden Verarbeitungszyklus "aktiv" wird.

    Für den "Nicht-EibPC"-Programmierer ist das natürlich so nicht zu erahnen. Oder hab ich da etwas im Handbuch (ok, ich hab noch v15) überlesen? Sollte ansonsten vielleicht klar beschrieben werden.

    Einen Kommentar schreiben:


  • enertegus
    antwortet
    Zitat von saft6luck Beitrag anzeigen
    Aber welchen Überlauf meinst du hier? Die innere Abfrage triggert fälschlicherweise?
    Sorry, ich bin da wohl etwas undeutlich und selbst nicht ganz geordnet: Irgendwie triggert die innere Abfrage (>59) das change() beim Initialsieren.

    Einen Kommentar schreiben:


  • saft6luck
    antwortet
    Zitat von enertegus Beitrag anzeigen
    Ich hab das nochmals getestet:
    Rollo_Sonnenuntergang_verzoegerung = 59u08
    => change wird (fälschlicherweise) getriggert
    Rollo_Sonnenuntergang_verzoegerung = 9u08
    => change wird erwartungsgemäß nicht getriggert
    (sunsetminute() steht auf 50)
    Aber welchen Überlauf meinst du hier? Die innere Abfrage triggert fälschlicherweise?

    Einen Kommentar schreiben:


  • enertegus
    antwortet
    Zitat von saft6luck Beitrag anzeigen
    Klar. Dann hast du natürlich eine Menge Arbeit!
    Wir entwicklen ja fleissig an weiteren Produkten,..

    dass die Addition von Rollo_Sonnenuntergang_verzoegerung triggert ...
    Ich hab das nochmals getestet:
    Rollo_Sonnenuntergang_verzoegerung = 59u08
    => change wird (fälschlicherweise) getriggert
    Rollo_Sonnenuntergang_verzoegerung = 9u08
    => change wird erwartungsgemäß nicht getriggert
    (sunsetminute() steht auf 50)

    Einen Kommentar schreiben:


  • saft6luck
    antwortet
    Zitat von enertegus Beitrag anzeigen
    Meine Vermutung: Zunächst wird initialisiert und change triggert nicht. Beim Überlauf (intern ist das sicher 32 Bit) wird ggf. versehentlich change getriggert. Ich hoffe mal nix großes - wir wollen ja bald nun eine neue Version freigeben.
    Klar. Dann hast du natürlich eine Menge Arbeit!

    Evtl. hast du dir ja mein Posting #194 noch nicht angeschaut. Hier einfach noch einmal die dortige Version, die das Problem auch zeigt und keinen Überlauf haben kann, oder? Ich vermute also eher, dass die Addition von Rollo_Sonnenuntergang_verzoegerung triggert ...

    [highlight=epc]
    // Sonnenuntergang
    Rollo_Sonnenuntergang_verzoegerung = 59u08

    Rollo_Sonnenuntergang_h = sunsethour()
    Rollo_Sonnenuntergang_m = sunsetminute() + Rollo_Sonnenuntergang_verzoegerung

    if change( Rollo_Sonnenuntergang_m ) then {
    if ( Rollo_Sonnenuntergang_m > 59u08 ) then {
    Rollo_Sonnenuntergang_m = Rollo_Sonnenuntergang_m - 60u08;
    Rollo_Sonnenuntergang_h = sunsethour() + 1u08;
    } endif
    } endif
    [/highlight]

    Einen Kommentar schreiben:


  • enertegus
    antwortet
    Zitat von saft6luck Beitrag anzeigen
    Habt ihr den Fehler denn schon eingrenzen können?
    Ich hab das nur reportet- wir arbeiten ja noch an anderen Dingen.
    Meine Vermutung: Zunächst wird initialisiert und change triggert nicht. Beim Überlauf (intern ist das sicher 32 Bit) wird ggf. versehentlich change getriggert. Ich hoffe mal nix großes - wir wollen ja bald nun eine neue Version freigeben.

    Einen Kommentar schreiben:


  • saft6luck
    antwortet
    Habt ihr den Fehler denn schon eingrenzen können?

    Einen Kommentar schreiben:


  • saft6luck
    antwortet
    Zitat von enertegus Beitrag anzeigen
    Nun habe ich aber die Startvariable geändert, so dass ein Überlauf autritt (also z.B. 55). Das sollte eigentlich wie zuvor sein, also change() beim Initialisieren nicht triggern.

    Tut es aber doch, also hier ist er, der BUG, wenngleich hier das Ergebnis eigentlich sogar gewünscht wäre.

    Naja, schwere Geburt, aber immerhin habe ich nun vielleicht verstanden, was Dir nicht klar war (und auch es nicht sein konnte). . Ich vermute dass der Überlauf die change-Variable irgendwie triggert. Werde das morgen in den Bugreport einreihen...
    Ja, das hatte ich gemeint
    Zur Info: Schau dir das Beispiel in #194 an, da gibt es keinen Überlauf (meinst du überhaupt einen Überlauf oder sprichst du von der Überlauf-Abfrage) und es wird trotzdem getriggert.

    Und wirklich, ich dachte inzwischen, dass der change richtig sei und der 2. Fall einen Fehler hat. Gut, dass es nicht so ist. Dann mache ich noch den Systemstart() rein und es passt wieder.

    Immerhin weiß ich jetzt auch, dass Änderungen von Variablen im nächsten Zyklus erscheinen.

    Einen Kommentar schreiben:


  • enertegus
    antwortet
    Zitat von saft6luck Beitrag anzeigen
    Ja, da ist eine Abfrage drinnen und wenn du die Konstante nicht größer als die Minuten des Sonnenaufganges wählst, wird es auch keine Änderung geben.
    Also nochmal: Beim Initialisieren wird die Konstante gesetzt, das sollte da keine change()-Funktion triggern, so war das vorausgesagt und das stimmt. Darum gings mir. Wenn der Sonnenstand sich später ändert, wird dann aber change() getriggert.
    [highlight=epc]
    if change( Rollo_Sonnenaufgang_m_s ) then {
    if ( Rollo_Sonnenaufgang_m_s < 0s08 ) then {
    Rollo_Sonnenaufgang_m_s = Rollo_Sonnenaufgang_m_s + 60s08;
    Rollo_Sonnenaufgang_h = sunrisehour() - 1u08;
    } endif;
    write('0/0/1'u08,10);
    } endif
    [/highlight]
    Hier sieht man, dass dem auch so ist: In meinem Beispiel wird change() beim Systemstart nicht getriggert. So soll es sein.
    Nun habe ich aber die Startvariable geändert, so dass ein Überlauf autritt (also z.B. 55). Das sollte eigentlich wie zuvor sein, also change() beim Initialisieren nicht triggern. Tut es aber doch, also hier ist er, der BUG, wenngleich hier das Ergebnis eigentlich sogar gewünscht wäre.

    Naja, schwere Geburt, aber immerhin habe ich nun vielleicht verstanden, was Dir nicht klar war (und auch es nicht sein konnte). . Ich vermute dass der Überlauf die change-Variable irgendwie triggert. Werde das morgen in den Bugreport einreihen...

    Einen Kommentar schreiben:


  • saft6luck
    antwortet
    Zitat von Tessi Beitrag anzeigen
    Irgendwie verstehe ich nicht, was mir das sagen soll.
    Du hast recht damit, dass man die Helligkeit auch mit dem Sonnenstand direkt abschätzen kann.

    Klar, aber Code soll doch in erster Linie möglichst optimal das Problem lösen. Und wenn Du einfach elevation() nutzt, dann mußt Du gar nicht debuggen, denn wenn die nicht tut was sie soll kann das eh nur Enertex ändern...
    Das Problem habe ich ja nicht beschrieben.

    Bei mir sollen die Rollos automatisch auf und zu gehen. Möglichst nicht vor 7:00 im Schlafzimmer, im restlichen Haus nicht vor 6:00, schließen sollen sie helligkeitsabhängig, die Terrassen- und Balkontür wird ausgeschlossen, wenn die Tür offen ist und insgesamt nicht später als 22:00.

    In der Visu soll die entsprechende Zeit angezeigt werden (möglichst schon für die ganze Woche, aber das ist eher ein Wunsch).

    Der Code-Schnipsel ist reduziert auf das Problem, auf das ich gestoßen bin.

    Einen Kommentar schreiben:

Lädt...
X