Cessna 208 True Airspeed Calibration
Wie schon angedeutet, verhält sich das Event (>K:TRUE_AIRSPEED_CAL_SET) zum Einstellen der Airspeed Kalibrierung leider genau so, wie im AAO Thread Post #329 das Event (>K:AILERON_TRIM_SET). Kurz zusammengefasst: im positiven Bereich lässt sich über das Event die Calibrierung setzen, im negativen Bereich wird immer 1 Prozentpunkt niedriger gesetzt als gesendet wird. Details zu diesem Verhalten bitte im o.g. verlinkten Post nachlesen. Irgendwie ist aber bei diesem Event noch mehr im Argen...
Es fällt auf, dass beim Drehen des zugehörigen Drehknopfes mit der Maus die Calibrierung in 0.5° Schritten verstellt werden kann (Screenshot links). Will man jedoch den Wert über das Event setzen, wird auf die nächste Ganzzahl gerundet (genau das selbe Rundungsverhalten wie beim AILERON_TRIM_SET, also im negativen Bereich immer auf die nächste kleinere Ganzzahl, im positiven Bereich bei .5 ab- und nicht aufgerundet) (Screenshot rechts).
Wie soll ich denn .5 setzen, wenn es das Event gar nicht kann?
Also nach Alternativen Events gesucht. Im Gegensatz zum AILERON_TRIM, wo das (>K:AILERON_TRIM_SET_EX1) als Alternative existiert, habe ich hier nur (>K:TRUE_AIRSPEED_CAL_DEC) und (>K:TRUE_AIRSPEED_CAL_INC) gefunden.
Getestet - die funktionieren auch. Auch im negativen Bereich. Und das sogar in .25er-Schritten, nicht nur .5. Mein Problem: Wenn ich aber .5er Schritte machen will, um das Mausverhalten genau nachzubilden - wie mache ich das? (Ok, das wäre trivial). Wie mache ich das, wenn ich eine beliebige Schrittgröße erlauben möchte (jetzt wird's deutlich kniffeliger)? Ihr wisst aus o.g. Post schon, dass ich ein Freund davon bin, dem Script über die Script-Variable einen beliebigen Wert mitgeben zu können - und das Script macht das dann schon richtig... Das ist also jetzt unsere Herausforderung.
.5er Schritte wären einfach - einfach 2x das Event triggern (also 1·(>K:TRUE_AIRSPEED_CAL_INC)·1·(>K:TRUE_AIRSPEED_CAL_INC). Aber wie mache ich so etwas mit einer variablen Anzahl von Wiederholungen?
Hierzu gibt es 2 mögliche Ansätze, die ich hier vorstellen möchte.
Variante 1: Nutzung einer Schleife
In anderen Programmiersprachen bietet sich für so ein Vorgehen eine Schleife an: x mal den selben Code ausführen. Üblich sind hierfür Befehle wie "For" oder "While". Diese sind in RPN nicht vorhanden. Wäre ja auch zu einfach. Was uns aber weiterhelfen könnte ist der "g" Befehl: "GoTo Label". Wie würde man so etwas implementieren (Spoiler: Das Script funktioniert so nicht! Aber zur Herleitung und Erklärung der Fallstricke ist es gut geeignet):
:1
(L:Generic-___Test)
0·>·if{·1·(>K:TRUE_AIRSPEED_CAL_INC)
········(L:Generic-___Test)·--·(>L:Generic-___Test)
········g1·}
Die Variable (L:Generic-___Test) ist die Script-Variable (nicht an den ____ stören, das ist einfach nur Teil des Namens) - die also den vom Assignment eingestellten Wert enthält. Sagen wir mal der Wert wäre 5. Nach dem Ausführen des Scriptes müsste die Airspeed Calibration also um 5x0.25° vergrößert worden sein (vorausgesetzt wir sind noch nicht am Anschlag). Gehen wir von einer Initialstellung von 0° aus, dann sollte danach also 1,25° eingestellt sein.
Was passiert im Script:
Zeile 1: Das :1 ist kein Tippfehler sondern das "Label 1", stellt euch "Markierung 1" vor.
Zeile 2: Hier holen wir den Wert der Script-Variable auf den Stack. In unserem Beispiel also 5.
Zeile 3: Ist der Wert größer als 0? Wenn ja dann einmal (>K:TRUE_AIRSPEED_CAL_INC) aufrufen (also die Calibrierung um 0.25° erhöhen)
Zeile 4: Ich nehme mir nochmal den Wert der Script-Variablen (also 5), erniedrige den um 1 und schreibe den neuen Wert (jetzt 4) wieder zurück in die Script-Variable
Zeile 5: Das g1 weißt RPN an, jetzt an der Stelle mit dem Label 1 (deshalb die 1 hinter dem g) mit dem Script fortzufahren. (hätte ich das Label :7 genannt, hätte ich g7 ausführen müssen, um die Ausführung am Label 7 fortzusetzen)
D.h. jetzt sind wir auf einmal wieder in
Zeile 1: mit Label 1. Dann
Zeile 2: Wert der Script-Variablen, jetzt aber 4 (nicht mehr 5 wie zu Beginn)
Zeile ...
Ok, ich denke ihr versteht. Wir machen das jetzt 5 mal, dann trifft die if Bedingung in Zeile 3 nicht mehr zu und das Script hört auf. Ziel erreicht? Ich verrate es Euch: nein, das Script wird nur 1x ausgeführt, erhöht wird also nur um 0.25.
Was ist das Problem?
1. SimConnect (die API, an die AAO das Script schickt) kann im RPN Script nur nach vorne springen nicht rückwärts. Wir könnten also Teile vom Script überspringen - aber eine Schleife ist damit NICHT möglich
2. SimConnect ersetzt die Script-Variable VOR dem Ausführen des Scripts. Wenn wir das Script starten, starten wir in Wahrheit folgendes (bleiben wir beim Wert 5 der Script-Variablen):
Das bedeutet, dass wir zwar die Script-Variable auf 4 runter setzen - aber (wenn der Sprung funktionieren würde) der if immer wieder gegen 5 prüfen würde, NICHT gegen den NEUEN Inhalt der Script-Variablen!
Die Lösung: wir lassen das RPN Script nicht über die SimConnect API ausführen, sondern direkt im Sim. Dies geschieht über den Befehl SIMPROC:
Das Script sieht dann wie folgt aus (und funktioniert auch noch ) :
SIMPROC:
:1
(L:Generic-___Test)
0·>·if{·1·(>K:TRUE_AIRSPEED_CAL_INC)
········(L:Generic-___Test)·--·(>L:Generic-___Test)
········g1·}
Was mir an der Stelle wichtig ist und ihr Euch wirklich merken sollt: ALLE Variablen, die gelesen werden (also die Werte auf den Stack kopiert, also ohne das >) werden (ohne SIMPROC:) VOR der Ausführung des Scripts durch den Wert ersetzt! Ich wette, ihr werdet trotzdem noch darauf hereinfallen...
Fortsetzung im nächsten Post - hab die 10.000 Zeichen überschritten...