Ankündigung

Einklappen
Keine Ankündigung bisher.

Quantenphysik im EibPC: then und else "gleichzeitig"

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

    Quantenphysik im EibPC: then und else "gleichzeitig"

    Ich weiß nicht, ob das Thema in diesem Unterforum schon mal behandelt wurde.

    Das nun folgende Problem hat mich Stunden gekostet und lässt mich immer noch kopfschüttelnd zurück.

    Bei der Programmierung eines Automaten für unser Garagentor, das sowohl über einen Auf/Ab/Stop-Taster als auch über die Fernbededienung und das EibPC-UI gesteuert werden kann, bin ich auf ein Problem gestoßen, das im folgende Code-Beispiel zum Ausdruck kommt:

    Code:
    letzter = 0b01
    aktuell = 0b01
    
    if aktuell != letzter then letzter = aktuell; endif;
    
    if cycle(0u08, 3u08) then {
            if letzter == 0b01 then {
                    ​aktuell = 1b01;
            } else {
                    aktuell = 0b01;
            } endif;
    } endif;
    (ja, der Code ist zu vereinfachen, er stellt lediglich den Kern des Problems dar)

    In letzter wird unter bestimmten Umständen der aktuelle Wert gespeichert (hier vereinfacht, wenn aktuell != letzter). Dieser archivierte Wert beeinflusst unter bestimmten Umständen den aktuellen Wert (hier vereinfacht bei jedem cycle()).

    Dieser Code sollte in allen Programmierwelten, die ich kenne, alle 3 Sekunden den Wert von aktuell toggeln. Das tut er aber nicht. Nach jedem cycle() ist aktuell immer noch bzw. wieder 0.

    Tatsächlich geschieht das Kuriosum, dass aktuell im then-Zweig zunächst auf 1b01 gesetzt wird, letzter daraufhin auf Grund der if-Bedindung aktuell != letzter davor ebenso auf 1b01, was dann dazu führt, dass nun wegen letzter != 0b01 der else-Zweig durchlaufen wird, der aktuell wieder auf 0b01 setzt.

    Das heißt, obwohl cycle() lt. Dokumentation "für einen Verarbeitungszyklus" den Rückgabewert 1b01 setzt, wird innerhalb dieses einen(!) Verarbeitungszyklusses
    • unten letzter == 0b01 geprüft
    • aktuell = 1b01 im then-Zweig gesetzt
    • oben aktuell != letzter geprüft
    • letzter = aktuell im dessen then-Zweig gesetzt
    • unten letzter == 0b01 nun negativ geprüft
    • aktuell = 0b01 im else-Zweig gesetzt

    Das widerspricht meiner Anschauung von "ein Verarbeitungszyklus". Im Ergebnis widerspricht das dem entweder-oder des then...else. Wenn der Code des then-Zweiges ausgeführt wird, dann niemals der Code des else-Zweiges - und umgekehrt, zumindest nicht in einem Zyklus.

    Meines Erachtens ist das Verhalten des EibPC an dieser Stelle möglicherweise erklärbar, aber falsch.
    KNX, openHAB 4.3, EibPC²

    #2
    Du solltest dir mal das Handbuch schnappen und ab Seite 53 lesen.

    Kommentar


      #3
      Das habe ich gelesen, erneut, bevor ich das obige postete.

      Im Validierungsschema wird von Zyklen gesprochen, in dem alles quasi-parallel läuft. Zu Beginn ist alles valide. Dann schlägt cycle() zu und macht seinen then-Zweig invalide. Zu diesem Zeitpunkt ist aber das if aktuell != letzter​ nach wie vor valide. Das heißt, nach meinem Verständnis laufen innerhalb dieses Zyklus' nur die Schritte im Then-Zweig.
      Die machen zwar die if aktuell != letzter​ invalide, aber da hat der cycle()-Zyklus doch schon begonnen. Das heißt, dieses Ereignis sollte erst im nächsten Zyklus abgearbeitet werden.
      Und wenn dann das if aktuell != letzter im nächsten Zyklus abgearbeitet wird, sollte cycle() bereits wieder 0b01 sein, da durch cycle() der Wert 1b01 nur für einen Verarbeitungszyklus gesetzt wird. Und damit wäre der then-Zweig von cycle() nicht erneut invalide und würde auch nicht abgearbeitet werden, so dass die Änderung von letzter​ nicht mehr wirken kann.

      Das alles wäre nur erklärbar, wenn der Zyklus des Validierungsschemas ein anderer Zyklus und deuchtlich schneller ist als der Verarbeitungszyklus, für den cycle() den Wert 1b01 zurückgibt.

      Und das hieße für mich, dass ich nicht deterministisch dafür sorgen kann, dass ein Ereignis wie cycle() genau ein Mal wirkt. Mir muss es doch möglich sein, Ereignisse, die nacheinander auftreten, auch nacheinander abzuarbeiten.
      KNX, openHAB 4.3, EibPC²

      Kommentar


        #4
        Ja, deine Schlussfolgerung ist im Kern richtig. Ich kenne den EibPC nicht, aber nach überfliegen des Handbuchs habe ich rerausgelesen, dass der EibPC innerhalb eines Verarbeitungsdurchlaufs die durch Änderungen invalid gewordenen abhängigen Objekte abarbeitet, bis der Zustand wieder konsistent ist.

        Bei cycle() steht wiederum sinngemäß: Es ist ein Zyklustimer für wiederkehrende Aufgaben. Die Funktion liefert einen kurzen Impuls. Der entscheidende Punkt ist: Dieser Impuls bleibt während der Validierung offenbar lange genug EIN, dass durch deine eigenen Zuweisungen erneut invalid gewordene abhängige Ausdrücke noch unter demselben cycle()-Impuls laufen.​

        Für „ein Ereignis soll genau einmal wirken“ brauchst du daher eine Struktur ohne unmittelbare Rückkopplung in dieselbe Bedingung. Also nicht:
        cycle() -> aktuell ändern -> letzter ändern -> aktuell wieder ändern

        Solltest du den Zustand von letzter nicht brauchen, dann schreibe es so
        HTML-Code:
        if cycle(0u08, 3u08) then {
        aktuell = !aktuell
        } endif​
        oder wenn du letzter brauchst, dann so:
        HTML-Code:
        if cycle(0u08, 3u08) then {
        letzter = aktuell;
        aktuell = !aktuell;
        } endif;​
        Bin mir auf die schnelle aber nicht 100% sicher ob das dein Problem erschlägt. Du kannst das halt nicht mit einer zyklischen SPS o.ä. vergleichen.

        Kommentar


          #5
          Das (eine) Problem habe ich schon gelöst, nachdem ich die Ursache erkannt hatte, warum mein Automat nicht funktionierte. Allerdings bin ich nicht davor gefeit, dass es früher oder später andere Seiteneffekte gibt, und zwar an Stellen, die durch Tests nicht unmittelbar auffallen.

          Wenn startt cycle() dort ready() stehen würde, könnte ich das alles nachvollziehen. Was mich stört, ist, dass ein Ereignis (Wechsel von 0 auf 1 auf 0) offensichtlich länger dauert als ein Validierungszyklus, so dass man über nachträgliche(!) Invalidierungen außerhalb(!) wieder in den gleichen Zweig reinkommt, nun aber mit einem anderen Ergebnis.

          Das ist in meinen Augen falsch. Invalidierungen auf einer Ebene höher sollten auch erst in nächsten Zyklus abgearbeitet werden. Wenn das Ereignis - hier cycle() - tatsächlich nur und genau einen Zyklus triggern würde, sollte das Problem nicht auftreten.
          Zuletzt geändert von Tokamak; Gestern, 12:52.
          KNX, openHAB 4.3, EibPC²

          Kommentar


            #6
            Ja aber erschlägst du das Problem nicht, wenn du die Zustandsänderung in den Ereigniszweig ziehst, wie in in #4 schrieb?
            Was passiert wenn du mit eval() arbeitest?

            Kommentar


              #7
              Wie ich eingangs schrieb, ist das nur der Kern des Problems. Der Code ist ein Auszug. Eigentlich ist "aktuell" einer von 7 Status eines Automaten, und "letzter" merkt sich im Original zwei dieser Status, damit diese gemerkten Status (eigentlich erst) beim nächsten (echten) Ereignis zur Bestimmung des Folgestatus herangezogen werden können.
              Da der Status (hier: aktuell) und "letzter" im Original Strings sind, konnte ich nicht mit !/not arbeiten.
              Und, wie gesagt, gelöst ist es schon, letztlich nach Code-Umstellung nun mit zwei Status-Variablen statt einer.

              Und nein, eval() würde da meines Erachtens nicht helfen, da eval() künstlich invalidiert, um die Auswertung zu erzwingen, genau das, was ich nicht möchte.

              Was ich suche, ist ein deterministisches Vorgehen, wie ich diese Situation eingängig und unter allen Umständen verlässlich programmieren kann, um in solche Probleme sicher nie mehr reinzulaufen.

              Natürlich könnte ich etwa das erste if künstlich verzögern. Ein

              Code:
              if delay(aktuell != letzter, 10u64) then letzter = aktuell; endif
              würde das vermutlich schon beheben. Aber dieses delay() ist weder intuitiv, noch ist sinnvoll, zu warten, wenn man eigentlich nicht warten muss.
              KNX, openHAB 4.3, EibPC²

              Kommentar


                #8
                Schau mal hier

                https://knx-user-forum.de/forum/supp...de-durchlaufen

                da ist das schon mal schön erklärt.

                ....und versuchen Sie nicht erst anhand der Farbe der Stichflamme zu erkennen, was Sie falsch gemacht haben!

                Kommentar


                  #9
                  Verstanden habe ich das schon. Allerdings wird die negierte Bedingung des Else-Zweiges dort während der Bearbeitung des then-Zweiges unmittelbar erzeugt, indem dort save = 4u08 gesetzt wiird, um dann auf !save == 0u08 zu treffen.

                  In meinem Fall ist es eine Spur komplexer. Denn die Bearbeitung des Ereignisses if aktuell != letzter​, das dazu führt, dass der else- als zweiter Zweig durchlaufen wird, liegt anders als im verlinkten Beispiel außerhalb der eigentlichen Ereignis-Bearbeitung. Die Bedingung aktuell != letzter​ war zum Zeitpunkt des Eintritts in den then-Zweig von cycle() nicht invalide.

                  Das heißt, es werden in einem Zyklus noch außerhalb der eigentlichen Bearbeitung Bedingungen invalidiert, die es zu Beginn des Zyklus nicht waren.

                  Wenn ich das weiterspinne, läuft man Gefahr, dass über noch längere Ketten - die erste Bedingung wird erst innerhalb des Zyklus invalidiert, dadurch eine zweite Bedingung, dann eine dritte usw. - plötzlich Dinge passieren, die man nicht auf dem Schirm hatte und auf keinen Fall wollte.

                  Und vermutlich wird, da die Zykluszeit begrenzt ist, irgendwann, vielleicht nach der zweiten oder in Folge der dritten zusätzlich invalidierten Bedingung, vielleicht auch bereits nach der ersten, der Zyklus beendet. Und diese Kette ist mal länger oder kürzer, je nachdem, wieviel der EibPC gerade zu tun hat.
                  Wenn das so passiert, wird aus dem EibPC eine nichtdeterministischer Automat, an derm vielleicht theoretische Informatiker, aber sicher keine Hausautomatisierer ihre Freude haben.
                  KNX, openHAB 4.3, EibPC²

                  Kommentar


                    #10
                    Jetzt bin ich raus, da kann nur enertegus und foobar0815 helfen

                    Kommentar

                    Lädt...
                    X