Zitat von saft6luck
Beitrag anzeigen
Ankündigung
Einklappen
Keine Ankündigung bisher.
In der Tiefe: Validierungskonzept
Einklappen
X
-
Das Problem im Code ist ein (sicher unschönes) Verhalten der Verschachtelten if-Abfrage beim Initialisieren (siehe die vorigen mails): Einfach gesprochen: Jede if-Abfrage wird beim Initalisierungsvorgang auf einmal ausgewertet, egal ob verschachtelt oder nicht. Wir haben das auf dem Radar fürs nächste Relase.
-
Mal wieder eine Frage an Michael (und alle anderen, die das Validierungsschema verstanden haben
) zum Validierungsschema und Systemstart:
Sonnenaufgang z.B. 06:57.
Warum kommt hier für Rollo_Sonnenaufgang_h und Rollo_Sonnenaufgang_m 7:50 heraus und nicht 7:00? Nach der ersten Änderung geht es dann aber ...
Sollte Copy&Paste prüfbar sein (Code ist zu Debugzwecken schon sehr umgebaut):
[highlight=epc]
// Rollo - Sonnenaufgang
Rollo_Sonnenaufgang_vorziehen = 7s08
Rollo_Sonnenaufgang_min_h = 07u08
Rollo_Sonnenaufgang_min_m = 00u08
Rollo_Sonnenaufgang_m = 60u08
Rollo_Sonnenaufgang_h = sunrisehour()
Rollo_Sonnenaufgang_m_s = convert( sunriseminute(), 0s08) - Rollo_Sonnenaufgang_vorziehen; /* -> Minuten: -15 <= m <= 44 */
if change( Rollo_Sonnenaufgang_m_s ) or systemstart() then {
if ( Rollo_Sonnenaufgang_m_s < 0s08 ) then {
Rollo_Sonnenaufgang_m_s = Rollo_Sonnenaufgang_m_s + 60s08;
Rollo_Sonnenaufgang_h = sunrisehour() - 1u08
} endif;
Rollo_Sonnenaufgang_m = convert( Rollo_Sonnenaufgang_m_s, 0u08 );
if ( ( Rollo_Sonnenaufgang_h == Rollo_Sonnenaufgang_min_h ) and ( Rollo_Sonnenaufgang_m < Rollo_Sonnenaufgang_min_m ) ) then {
Rollo_Sonnenaufgang_m = Rollo_Sonnenaufgang_min_m
} endif;
if ( Rollo_Sonnenaufgang_h < Rollo_Sonnenaufgang_min_h ) then {
Rollo_Sonnenaufgang_m = Rollo_Sonnenaufgang_min_m;
Rollo_Sonnenaufgang_h = Rollo_Sonnenaufgang_min_h
} endif;
} endif
[/highlight]
Einen Kommentar schreiben:
-
So, jetzt habe ich auch noch die vollständige Fassung lesen können.
Die Sache mit dem Makro bekräftigt noch mal meine schon vorher aufgekommene Frage:
Warum unterliegen Ausgabefunktionen nicht dem VK, so wie alle anderen auch? Rekursionen können auch anders entstehen und müssen sowiso irgendwie abgefangen werden, das zeigt ein dem Makro folgendes Beispiel. Dafür würde mit VK das Makro eher das machen, was ohne die Warnung sonst wohl die meisten von uns erwartet hätten: Es hätte zumindest bei Änderungen gesendet, auch wenn die Anweisungen dazu nicht im return-Zweig sondern im "globalen" Rumpf stehen.
OK, es ist jetzt, wie es ist, und wenn man das jetzt verstanden hat, kommt man auch so ans Ziel, aber ich sehe jetzt immer noch keinen Vorteil darin, die Ausgabefunktionen aus dem VK herauszunehmen.
Aber habe ich das den Beispielen jetzt richtig entnommen:
1. Nur das, was im return-Zweig eines Makros steht, wird an den Stellen eingefügt, an der es aufgerufen wird? Der Rest steht funktional gesehen einmalig im globalen Code? Oder so oft, wie das Makro aufgerufen wird?
2. Wenn ich ein Makro unbedingt aufrufe, steht dann der Code im Returnzweig genauso im globalen Kontext wie der restliche Makrocode und es greift auch hier das VK?
3. Was bildet den Rückgabewert des Makroaufrufes, wenn im Returnzweig so viel Code stehen darf? Generell das letzte Statement? Was wäre dann, wenn dieses keinen Wert liefert? Oder das letzte Statement das einen Wert liefert? Was, wenn mehrere Statements einen Wert liefern? Werden dann alle Werte bis auf den letzten verworfen? Oder ist das nicht zulässig? Was ist, wenn kein Statement einen Wert liefert? Was ist, wenn an der Stelle des Aufrufes ein Wert erwartet wird? Fängt so etwas schon der Parser ab?
Rekursion:
Wie wird sie erkannt? Wann wird das Event PROC_REPITIONS generiert? Was passiert danach?
Einen Kommentar schreiben:
-
Gut, bleibt für mich nur die Frage:
[highlight=epc][EibPC]
write("Schalter-1/2/10",!"Schalter-1/2/10")
write("Schalter-1/2/10",blub)
a=a+1u08
a=b+1u08[/highlight]Zeile 2 und 3 sind erlaubt, aber führen zu nichts da die Argumente die Funktionen nicht triggern können.
Zeile 4 würde sich gemäß VK selbst triggern und wird daher vom Parser an dieser Stelle nicht zugelassen.
Zeile 5 würde gemäß VK getriggert werden und ist OK.
Warum wird Zeile 2 nicht wie Zeile 4 und Zeile 3 wie Zeile 5 behandelt?
Zeile 2 ist ein Risiko, aber Zeile 4 genauso.
Wenn der Parser den Zirkelbezug in Zeile 4 erkennen und ablehnen kann, hätte man das doch genauso für Zeile 2 implementieren können. Ich fände es logischer, wenn Zeile 3 sich bei Änderungen der Argumente genau so erneut auswerten würde, wie dies Zeile 5 tut.
Warum also diese unterschiedliche Behandlung?
Einen Kommentar schreiben:
-
Ups, das habe ich versehentlich gemacht. => neu hochgeladen.Zitat von Tessi Beitrag anzeigenHabe ich jetzt mal endlich geschafft!
Schade, das es nach der 5. Seite zu Ende ist. Ich hätte doch gerne gewusst, was der Parser aus dem Makro am Ende macht.
Ja, das ist richtig.Ich lese auf Seite 118: Ausgabefunktionen werden nie von ihren Argumenten invalidiert.
Demnach funktionieren sie nur als Teil eines Ausdrucks, der von außen invalidiert wird, also in then- oder else-Zweigen.
Das ist der Hintergrund für diesen Verhalten.Mir ist jetzt nicht klar, warum das wirklich ein Problem werden kann. OK, der Toggle-Befehl in Zeile 2 würde sich immer wieder selbst triggern, aber wenn ich das statt dessen so schreiben würde:
richtig, aber das setzt schon einiges voraus an gezieltem Handeln. Einfach nur ein write und dieses Verhalten, da erschien uns die Lernkurve zu krumm...hätte ich das gleiche Problem.
Eben!Nicht ohne Grund mag der Parser so etwas ja nicht:
Das Argument ist gut. Hintergrund ist wohl (ich bin nicht der FW-Spezi) die Sache mit den unterschiedlichen Argumenten (Sequenz). Dass es bei Variablen so funktioniert ist wohl ein "Seiteneffekt", über den man nachdenken könnte.Das macht für mich keinen Sinn! Entweder sende ich auch die Folge von Werten, die die verschiedenen write-Befehle hatten (weil die Sequenz für den Empfänger wichtig sein könnte), oder es geht tatsächlich nur um die letzte Änderung, aber dann sollte auch nur einmal pro Zyklus und GA ein Telegramm im Puffer landen.
Welchen Sinn hat das derzeitige Verhalten?
Einen Kommentar schreiben:
-
Habe ich jetzt mal endlich geschafft!Zitat von enertegus Beitrag anzeigenSchau doch noch mal in Ruhe das PDF dieses Threads durch. Da ist das genau mit Beispielen erläutertet.
Schade, das es nach der 5. Seite zu Ende ist. Ich hätte doch gerne gewusst, was der Parser aus dem Makro am Ende macht.
Ich lese auf Seite 118: Ausgabefunktionen werden nie von ihren Argumenten invalidiert.
Demnach funktionieren sie nur als Teil eines Ausdrucks, der von außen invalidiert wird, also in then- oder else-Zweigen. Welche Katastrophe würde denn eintreten, wenn auch hier das VK gelten würde?
[highlight=epc][EibPC]
write("Temperatur-1/2/1",22.3)
write("Schalter-1/2/10",!"Schalter-1/2/10")
write("Temperatur-1/2/1",Temp)
write("Schalter-1/2/10",Status)[/highlight]Zeile:- -
- Kein Problem, die Konstante invalidiert ja sowiso nie.
- Hm, könnte ein ernstes Problem werden, aber so etwas sollte man an dieser Stelle dann auch nicht schreiben, bzw. der Parser könnte es ablehnen (wie er es an selbiger Stelle ja auch mit a=a+1u08 tun würde)
- Jede Änderung von Temp - egal wo im Code erfolgt - wird auch geschrieben, und hier maximal nur einmal pro Zklus. Problem?
- Wie zuvor
[highlight=epc][EibPC]
if ("Schalter-1/2/10") then {
write("Schalter-1/2/10",!"Schalter-1/2/10")
} else {
write("Schalter-1/2/10",!"Schalter-1/2/10")
} endif[/highlight]hätte ich das gleiche Problem. Nicht ohne Grund mag der Parser so etwas ja nicht:
[highlight=epc][EibPC]
a=a+1u08[/highlight]Statt dessen muß ich derzeit Zeile 3 und 4 (erstes Beispiel), damit eine Änderung auch auf den Bus kommt, so schreiben:
[highlight=epc][EibPC]
if change(Temp) write("Temperatur-1/2/1",Temp)
if change(Status) write("Schalter-1/2/10",Status)[/highlight]Hier muß ich also explizit das schreiben, was das VK sonst implizit macht.
OK, ich kann damit leben, aber dennoch interessiert mich der Grund für diese Art "Sonderbehandlung".
Nächster Punkt:
Ein Telegramm wird aus einem Zyklus heraus so oft in den Sendepuffer gestellt, wie in diesem Zyklus write-Befehle auf die GA invalidiert wurden. Klingt zunächst vernünftig, auch wenn das ggf. den Bus überlastet (ist aber dann ein Fehler des Programmierers). Gesendet wird dabei aber jedesmal der Wert den der zuletzt bearbeitete write-Befehl auf diese GA hatte. Das macht für mich keinen Sinn! Entweder sende ich auch die Folge von Werten, die die verschiedenen write-Befehle hatten (weil die Sequenz für den Empfänger wichtig sein könnte), oder es geht tatsächlich nur um die letzte Änderung, aber dann sollte auch nur einmal pro Zyklus und GA ein Telegramm im Puffer landen.
Welchen Sinn hat das derzeitige Verhalten?
Einen Kommentar schreiben:
-
Ich hab mal das Pdf aus dem internen Stand des Handbuch hochgeladen.
Sind sicher noch jede Menge Tippfehler drinne.
Einen Kommentar schreiben:
-
Zum Thema: Objektabhängigkeit und Validierung ein paar Bilder. Ich werde dies ins Handbuch einarbeiten.
Dazu noch zum Thema if:
Die if-Anweisung invaldiert alles im then-Zweig. Daher wird dort alles abhängig von der if-Anweisung ausgeführt. Wenn nun hier auch eine if-Anweisung steht, gilt für diese die Valdierung nicht vom Argument sondern direkt von der übergeordneten Anweisung.
Nochmal zu Valdierung:
- Eine Variablenausdruck ist invalid bedeutet: Berechne ihn und neu und invaldiere von ihm abhängige Variablen.
- Eine Funktion ist invalid bedeutet: Führe die Funktion aus
- Funktionen, die etwas auf den Bus schreiben, tun dies
- Eine if-Anweisung ist invalid: Wenn die Bedingung wahr ist, dann führe den then Zweig aus.
- Ein nicht von einer anderen if-Anweisung abhängige if-Anweisung (="Toplevel If") wird von ihrer Abfragebedingung abhängig invaldiert.
- Ein von einer anderen if-Anweisung abhängige if-Anweisung (="verschachteltes If") wird NICHT von ihrer Abfragebedingung abhängig invaldiert
Ich mach da noch ein paar Bilder, aber wahrscheinlich nicht vor Mitte nächster Woche.
Vielleicht klärt sich das noch auf. Der pio hat es schön mit seiner Tabelle gezeigt und exakt richtig formuliert.Angehängte Dateien
Einen Kommentar schreiben:
-
Ehrlich gesagt frage ich mich schon, wieso die Programmierung des eibPCs eine solch Komplexe Angelegenheit sein muss. Mir wäre mehr daran gelegen, dass die Anleitung (und damit die Interpretation der Programmierung) so einfach wie möglich wird. Daraus folgt, dass die Programmierung robust wird.
Und robust ist für mich eine Sprache, wenn sie eindeutig und deterministisch ist und das nicht erst nach mehreren Iterationen. Ich bin zwar ein Schachspieler, will aber trotzdem nicht jede Zeile Code "5 Ausführungszyklen weit" voraus betrachten müssen, schon gar nicht, um triviale Prüfungen zu implementieren.
Leider erfüllt der eibPC mit seiner Programmiersprache meine Anforderungen nicht. Robustheit und Determinismus sind für mich wesentliche Aspekte der Automatisierung und da hatte ich evtl. zu viel erwartet.
Einen Kommentar schreiben:
-
Um das noch weiter zu erklären:Zitat von enertegus Beitrag anzeigend=a+b+c+1u08
if (d>=0) then write('2/3/4'u08, d)[/highlight]
richtig
Nein, die werden sofort im Zyklus sich ändern, nur change() reagiert darauf erst im folgenden.
gar nix, weil ja d=>0 schon zum Systemstart gültig ist.
Es hat absolut nichts mit Geheimniskrämerei zu tun. Ich bin drüber, da wa zu malen.
nach dem Neustart ist d=0, d.h. die Bedingung d>=0 ist erfüllt.
Nach meinem Verständniss wird dann auch beim Neustart, d.h. beim allerersten Zyklus NICHTS gesendet, da die Bedingung zwar erfüllt ist, aber sich "nichts geändert" hat.
Das gilt dann für den zweiten Verarbeitungszyklus und alle weiteren: obwohl auf der GA ein neuer Wert (=1) ankommt, ist die Bedingung >= 0 immer noch erfüllt, hat sich also gegenüber dem vorigen Zyklus nicht verändert, ergo wird der Then-Zweig auch nicht ausgeführt.
Mein Vorschlag an Enertex zur Doku:
Macht eine Tabelle, mit einer Zeile pro Verarbeitungszyklus, und listet in jeder Spalte die Zustände der einzelnen "Elemente" auf.
Beispiel siehe Bild.Angehängte Dateien
Einen Kommentar schreiben:
-
Naja, die "Sprache" des EibPC ist glaube ich für jemanden der schonmal programmiert hat (nicht verwechseln mit dem parametrieren in der ETS oder dem beklicken einer SPS bitte!) - zumindest gewöhnungsbedürftig.
Dann gehts recht gut..
Aber ich finds garnicht so schlecht, jeder der <=2007 mit dem HS angefangen hat und es nun gewohnt ist 15 Minuten (in Worten -> bis heute: eine Viertelstunde!) ohne jeglichen Support/gescheite Doku vom Hersteller (Anwesende im Forum ausgenommen) sich mal überraschen zu lassen, was nach dem Neustart passiert
Der liebt das bestimmt, nach 10sek ggfs. sogar einen Bug zu finden
(der nicht in 2 J sondern in 2 Tagen gefixed wird..)
Man betrachtet das dann vielleicht auch anders
Makki
Einen Kommentar schreiben:
-
Ich werde da heute abend noch etwas malen und verdeutlichen (soweit es mir gelingt
)
Aber schon mal hierzu:
[QUOTE=Tessi;141323]
[highlight=epc]
a=0u08
b=0u08
c=0u08
d=0u08
a='1/2/3'u08
b=a+1u08
c=a+b+1u08
d=a+b+c+1u08
if (d>=0) then write('2/3/4'u08, d)[/highlight]
richtigKommt über '1/2/3' eine 0 passiert nichts - a ist ja schon 0.
Nein, die werden sofort im Zyklus sich ändern, nur change() reagiert darauf erst im folgenden.Kommt über '1/2/3' eine 1 wird dann im selben Zyklus nur a=1 und b,c und d bekommen die Änderung von a erst im folgenden Zyklus mit?
gar nix, weil ja d=>0 schon zum Systemstart gültig ist.Was wird dabei wann über '2/3/4' gesendet?
Es hat absolut nichts mit Geheimniskrämerei zu tun. Ich bin drüber, da wa zu malen.Wie gesagt, solche Fragen könnte ich mir selbst beantworten, wenn ich mehr über die internen Vorgänge im EPC wüßte...
Einen Kommentar schreiben:
-
Es muß da aber doch noch einen besseren Weg geben das VS eindeutig und vollständig zu beschreiben, als seitenlange Prosa, die offenbar immer irgendwie Interpretationsspielraum für Missverständnisse läßt, und Beispiele, die ohnehin nicht alles abdecken können und teilweise gleich neue Fragen aufwerfen.
Oben wurde erwähnt, das der Parser/Compiler den Code in Objekte und eine Abhängigkeitsstruktur umsetzt. Ich finde, für komplexere Logiken ist es hilfreich zu wissen, wie in etwa so ein Objekt und die Abhängigkeitsstruktur aussieht und was die Laufzeitumgebung im EPC damit macht, also wie der Ablauf beim Auftreten eines Events denn ist. Das schließt auch vorhandene Queues, Buffer und deren Verwaltung ein.
Bis dahin habe ich aber noch eine konkrete Frage:
[highlight=epc]
a=0u08
b=0u08
c=0u08
d=0u08
a='1/2/3'u08
b=a+1u08
c=a+b+1u08
d=a+b+c+1u08
if (d>=0) then write('2/3/4'u08, d)[/highlight]
Kommt über '1/2/3' eine 0 passiert nichts - a ist ja schon 0.
Kommt über '1/2/3' eine 1 wird dann im selben Zyklus nur a=1 und b,c und d bekommen die Änderung von a erst im folgenden Zyklus mit?
Wenn dem so ist, ändert sich c dann zweimal einmal wegen a und dann im folgenden Zyklus wegen b und ändert sich d dann analog dazu dreimal in drei aufeinanderfolgenden Zyken?
Was wird dabei wann über '2/3/4' gesendet?
Bei "reiner" Programmierlogik sollte nur einmal 8 gesendet werden.
Wenn aber Änderungen der Variablen immer erst im Folgezyklus bearbeitet werden, dann würde ich 2,4 und 8 in dichter Folge erwarten - unter der Annahme, das es einen FIFO für zu sendende Botschaften gibt.
Oder wird dennoch nur 8 gesendet, weil während des Sendens der dann aktuelle Wert verwendet wird und der bis dahin auf jeden Fall schon 8 ist?
Wird dann drei mal 8 gesendet? Oder wird das zu einem Telegramm zusammengefasst? Falls ja, woher will die Ablaufsteuerung denn wissen, das ich nicht doch drei Botschaften wollte?
Wie gesagt, solche Fragen könnte ich mir selbst beantworten, wenn ich mehr über die internen Vorgänge im EPC wüßte...
Einen Kommentar schreiben:
-
Wer im Glashaus sitzt...ich sage nur FSF und nicht vorhandene Flash-Kompetenz.Zitat von enertegus Beitrag anzeigenDa zieh ich mal den Stecker, PLONK.
DOPPELPLONK & Mail an die entsprechenden Stellen ist raus.
Einen Kommentar schreiben:
-
Ich glaube, Du solltest hier nicht einfach was in die Runde schmeißen, so quasi auf Verdacht mal was gesagt.Zitat von no sleep Beitrag anzeigenGut, dass ich das auch nicht verstehen muss, weil ich mir "sowas" nie antun würde.
Da zieh ich mal den Stecker, PLONK.
Einen Kommentar schreiben:

Einen Kommentar schreiben: