Anwendungshilfen für Custom-Logiken (How-to's)
Inhalt dieser Seite
Einführung
Um das Eindenken in die an die Schaltungstechnik orientierte Codiersprache zu erleichtern, werden hier - im Sinne von “Snippets” und ohne Anspruch auf Vollständigkeit - Lösungsansätze für Teilprobleme vorgestellt.
Definition des LEVEL-Array
Die nachfolgenden Beispiele basieren auf folgenden LEVEL-Array:
"Level": [
// Boolean-Variablen
["$InI","integer",0],
["$OutI","integer",0],
["$VonB","bool",false],
["$NachB","bool",false],
["$Ergebnis","bool",false],
["$Ergebnis1","bool",false],
["$Ergebnis2","bool",false],
["$ErgebnisFehler","bool",false],
// Integer-Variablen
["$InI","integer",0],
["$OutI","integer",0],
["$VonI","integer",0],
["$NachI","integer",0],
["$Groesser","integer",0],
["$Kleiner","integer",0],
["$Bezug","integer",0],
// ab hier Definition von Konstanten
["$true","bool",true],
["$false","bool",false],
["$Z0", "integer",0],
["$Z1", "integer",1],
["$Z2", "integer",2],
["$Z3", "integer",3],
["$Z4", "integer",4],
["$Z5", "integer",5],
["$Z6", "integer",6],
["$Z7", "integer",7],
["$Z8", "integer",8],
["$Z9", "integer",9]
]
Aufgabenstellungen
Einer Variablen den Wert einer anderen Variablen zuweisen
Boolean-Typen
["And",["$VonB"],"$NachB"]
Alle Typen
["Latch","$VonI","$NachI","$true",0]
["Multiplexer",[0,"$true"],"$NachB","$VonB"]
Zwischen Variablen mit unterschiedlichen Datentypen
["Multiplexer",[0, 0, "$true", 0],"$NachB","$InI“]
(weist der Variablen$NachB"
den Wert TRUE zu, sofern der Wert der Variablen"$InI“
2
ist; in allen anderen Fällen wird0
zugewiesen.
Nur TRUE als Output senden
{
"Input": [
["Eingabe","Zu prüfender Wert","$InB","c" ]
],
"Output": [
["Ausgang","","$OutB","c"]
],
"Level": [
["$InB","bool",false],
["$OuBt","bool",false]
],
"Module": [
["Break",["-$InB"]], // nur wenn Input TRUE ist, ist die Logik nicht gesperrt und wird etwas gesendet
["And",["$InB"],"$OutB"]
]
}
Mit Bedingungen arbeiten
In prozeduralen Sprachen werden in der Regel Konstrukte wie “if … then”, if … then, else” oder “switch … case” genutzt. Die Codiersprache der TWS-Logikfunktion kennt zwar diese Konstrukte nicht, weil sie auf der Schaltungstechnik basiert. Trotzdem sind die gleichen Ergebnisse erzielbar (siehe auch die Diskussion unter: https://forum.timberwolf.io/viewtopic.php?f=24&t=1585
Durchführen von Vergleichen / Prüfen von Bedingungen
Wenn $Kleiner < $Groesser , dann TRUE an $Ergebnis
["Comparator" , "$Groesser" , "$Ergebnis" , "$Kleiner"]
Wenn $InI == $Bezug, dann TRUE an $Ergebnis
["Limiter","$InI",0,"$Ergebnis",["$Bezug", "$Bezug"]]
Bedingte Zuweisungen abhängig vom Ergebnis eines vorgängigen Vergleichs (→If-Then--else-Konstrukte)
["Latch","$VonI","$NachI","$Ergebnis",0]
→ Sofern das Ergebnis des vorgängigen Vergleichs TRUE ist, wird der Variablen"$NachI"
der Wert der Variablen"$VonI"
übergeben, ansonsten behält"$NachI"
ihren bisherigen Wert (If-then).["Multiplexer",["$VonI","$InI"],"$NachI","$Ergebnis"]
→ Sofern das Ergebnis des vorgängigen Vergleichs TRUE ist, wird der Variablen"$NachI"
der Wert der Variablen"$InI"
, ansonsten der Wert der Variablen"$VonI"
übergeben (If-then-else).
Bedingte Zuweisung abhängig von einem Integerwert (→Switch-Case-Default-Konstrukt)
Mit einem Multiplexer (nötigenfalls können mehrere Multiplexer-Zeilen in Serie geschaltet werden).
["Multiplexer",[0, 0, "$true", 0],"$NachB","$InI“]
--> Weist der Variablen$NachB"
den Wert TRUE zu, sofern der Wert der Variablen"$InI“
2
ist; in allen anderen Fällen wird0
zugewiesen.Als Kombination von Limiter-Anweisung; diese insbesondere dann bequemer, wenn beliebige Werte (d.h. nicht solche, die nahe bei 0 sind) ausgewertetet werden müssen:
["Limiter","$VonI",0,"$Ergebnis1",["$Z3","$Z3"]], ["Limiter","$VonI",0,"$Ergebnis2",["$Z5","$Z5"]], ["Limiter","$VonI",0,"$Ergebnis3",["$Z9","$Z9"]], ["Or",["$Ergebnis1","$Ergebnis2","$Ergebnis3"],"-$ErgebnisFehler"] // für Funktionalität nicht erforderlich ["And",["$Ergebnis1","$Ergebnis2","$Ergebnis3"],"$Ergebnis"]
→ Weist der Variablen
"$Ergebnis"
TRUE zu, wenn der Wert der Variablen ""$VonI"
entweder3
,5
oder7
ist; trifft dies nicht zu, erhält die Variable"$Ergebnis"
den Wert FALSE und die Variablen“$ErgebnisFehler”
den Wert TRUE zu.
Bedingte Zuweisung, abhängig von einer Kombination von Bedingungen
Aufgabenstellung: Ein Ausgang soll abhängig vom Zustand von drei möglichen Eingängen geschaltet werden.
Pseudo-If-then-else-Code:IF $Eingang1=true AND $Eingang2=true THEN $Ausgang = $Wert1 ELSE IF $Eingang1=false AND $Eingang2=true AND $Eingang3=true THEN $Ausgang= $Wert2 ELSE $Ausgang = $Wert3 END IF
Umsetzung in der Custom-Logik (Quelle: https://forum.timberwolf.io/viewtopic.php?f=24&t=1585&start=10#p16814):
// Zuerst kommt das ELSE (d.h. der Defaultwert): ["Latch","$Wert3","$Out","$true",0] => Schiebt grundsätzlich $Wert3 auf den Ausgang // Dann folgen die IF / ELSE IF Bedingungen. => "And" prüft die Bedingung und setzt bei Erfüllung die jeweilige Hilfs-Variable ($Bedingung..) auf true. Der zugehörige "Latch" schiebt dann den gewünschten Wert auf den Ausgang und übersteuert damit den grundsätzlichen Wert. [ "And",[ "$Eingang1", "$Eingang2" ], "$Bedingung1" ], [ "Latch", "$Wert1", "$Out", "$Bedingung1", 0 ], [ "And",["-$Eingang1","$Eingang2","$Eingang3" ], "$Bedingung2" ], [ "Latch", "$Wert2", "$Out", "$Bedingung2", 0 ],
Schleifen / zyklische Aufrufe
In prozeduralen Sprachen werden häufig Schleifen (for, loop, while, …) angewendet. Die Codiersprache der TWS-Logikfunktion kennt nur eine streng sequentielle Abarbeitung der Module innerhalb eines Aufrufs. Schleifen innerhalb eines Aufrufs stehen nicht zur Verfügung, da die extrem schnelle Abarbeitung eines Aufrufes im Vordergrund steht, für andere Logiken keine Verzögerungen entstehen können.
Nichtsdestotrotz gibt es Anwendungen, in denen eine kontinuierliche Wertänderung (zB. Dimmverlauf) notwendig ist. Dies wird durch einen zyklischen Aufruf der Logik erreicht.
Beispiel (Ausschnitt aus einer Dimmer-Logik)
// Zyklischer Trigger
["Clocksignal","$StatusDimmen","$Takt","$I_DauerDimmen"],
// Neuen Dimmwert ermitteln
["Polynomial", "$DimmRichtung", "$DimmwertNeu",["$DimmwertLast", "$Schrittweite"]],
// Wert nur übernehmen, wenn sich Taktsignal geändert hat
["Latch","$DimmwertNeu","$O_Dimmwert","$Takt",3]
// Am Ende den letzten Wert für den nächsten Aufruf speichern
["Latch","$DimmwertNeu","$DimmwertLast","$Takt",3]
Wichtig ist dabei, dass nur zyklische Aufrufe für die Werterhöhung berücksichtigt werden und nicht ein beliebiger Trigger durch einen Eingang. Dies wird im obigen Beispiel durch das Modul Latch erreicht, das nur auf die steigende/fallende Flanke reagiert.