User Tools

Site Tools


cds:german:skripte_2019_20

Skripte der Anlage Winter 2019/20


Anhand meiner Anlage aus der Wintersaison 2019/20 möchte ich meine Skripte vorstellen und erklären. Die Skripte dienen mehrheitlich dazu, die Automatik von Rocrail (RR) zu beeinflussen.
Wie Skripte erstellt und in RR via Aktionsdefinition eingebunden werden, ist hier erklärt; ich werde darauf nicht näher eingehen.
Weiters setze ich voraus, dass der p. t. Leser Rocrail, seine Objekte und ihre Funktionalität kennt.
Anmerkung: Viele Wege führen zum Ziel! Alle hier vorgestellten Lösungen lassen sich mit hoher Wahrscheinlichkeit anders umsetzen. Alle Lösungen arbeiteten auf meiner Anlage zuverlässig und sind unter Bedachtnahme geringstmöglicher Redundanz in Bezug auf Coding und Ausführung entwickelt worden.

Disclaimer: Meine Skripte oder Teile davon dürfen für den Privatgebrauch frei verwendet werden. Die Nutzung meiner Skripte oder Teilen davon erfolgt auf eigene Verantwortung.

Anlagenplan

Der Plan meiner Anlage:

Anlagenplan


Der Plan kurz erklärt:
Einfache zweigleisige Strecke mit Richtungsbetrieb und 7 Aufstellblöcken pro Fahrtrichtung. Die Belegungsanzahl ist in den Aufstellblöcken (AB) zu sehen, alle ABe sind gefüllt. Jeweils 7 ABe sind zu einer Ortschaft mit FiFo zusammen gefasst, pro Ortschaft dürfen max. 2 Züge ausfahren.
Es fahren max. 4 Züge auf der Anlage, 2 pro Richtung.


Alle AB mittels Schalter öffnen/schließen

Mittels des Schalters S1 können alle ABe mit einem Mausklick geöffnet oder geschlossen werden.

<?xml version="1.0" encoding="UTF-8"?>
<xmlscript desc="Script_AB_ein_aus">
 
<!-- Aufruf wenn S1 on -->
<if state="co S1 = on">
  <then>
    <sb id="AB1" exitstate="closed"/>
    <sb id="AB2" exitstate="closed"/>
    <sb id="AB3" exitstate="closed"/>
    <sb id="AB4" exitstate="closed"/>
    <sb id="AB5" exitstate="closed"/>
    <sb id="AB6" exitstate="closed"/>
    <sb id="AB7" exitstate="closed"/>
    <sb id="AB8" exitstate="closed"/>
    <sb id="AB9" exitstate="closed"/>
    <sb id="AB10" exitstate="closed"/>
    <sb id="AB11" exitstate="closed"/>
    <sb id="AB12" exitstate="closed"/>
    <sb id="AB13" exitstate="closed"/>
    <sb id="AB14" exitstate="closed"/>
    <exit cmt="Aufstellbloecke geschlossen"/>
  </then>
</if>
 
<!-- Aufruf wenn S1 off -->
<if state="co S1 = off">
  <then>
    <sb id="AB1" exitstate="open"/>
    <sb id="AB2" exitstate="open"/>
    <sb id="AB3" exitstate="open"/>
    <sb id="AB4" exitstate="open"/>
    <sb id="AB5" exitstate="open"/>
    <sb id="AB6" exitstate="open"/>
    <sb id="AB7" exitstate="open"/>
    <sb id="AB8" exitstate="open"/>
    <sb id="AB9" exitstate="open"/>
    <sb id="AB10" exitstate="open"/>
    <sb id="AB11" exitstate="open"/>
    <sb id="AB12" exitstate="open"/>
    <sb id="AB13" exitstate="open"/>
    <sb id="AB14" exitstate="open"/>
    <exit cmt="Aufstellbloecke geoeffnet"/>
  </then>
</if>
 
</xmlscript>

Der Inhalt des Skripts ist selbsterklärend.
Das Skript läßt sich vielleicht eleganter mit einer Schleife und zusammengesetzten Strings codieren.


Alle AB bei "Automatik ein/aus" öffnen/schließen

Die Funktion "Automatik ein/aus" beeinflusst die ABe nicht. Nach Ausschalte der Automatik würden dennoch Züge aus den ABen ausfahren und erst im ersten nachfolgenden normalen Block gestoppt werden. Gleiches gilt für die Funktion "Alle Loks in den manuellen Mode setzen" (sprich: "Alle Loks stoppen").
Um die ABe ebenfalls zu beeinflussen, hilft dieses Skript:

<?xml version="1.0" encoding="UTF-8"?>
<xmlscript desc="Script_AB_ein_aus_Automatik">
 
<!-- Aufruf wenn Automatik aus -->
<if state="auto auto = off">
  <then>
    <sb id="AB1" exitstate="closed"/>
    <sb id="AB2" exitstate="closed"/>
    <sb id="AB3" exitstate="closed"/>
    <sb id="AB4" exitstate="closed"/>
    <sb id="AB5" exitstate="closed"/>
    <sb id="AB6" exitstate="closed"/>
    <sb id="AB7" exitstate="closed"/>
    <sb id="AB8" exitstate="closed"/>
    <sb id="AB9" exitstate="closed"/>
    <sb id="AB10" exitstate="closed"/>
    <sb id="AB11" exitstate="closed"/>
    <sb id="AB12" exitstate="closed"/>
    <sb id="AB13" exitstate="closed"/>
    <sb id="AB14" exitstate="closed"/>
    <co id="S1" cmd="off"/>
    <exit cmt="Aufstellbloecke geschlossen"/>
  </then>
</if>
 
<!-- Aufruf wenn Automatik ein -->
<if state="auto auto = on">
  <then>
    <sb id="AB1" exitstate="open"/>
    <sb id="AB2" exitstate="open"/>
    <sb id="AB3" exitstate="open"/>
    <sb id="AB4" exitstate="open"/>
    <sb id="AB5" exitstate="open"/>
    <sb id="AB6" exitstate="open"/>
    <sb id="AB7" exitstate="open"/>
    <sb id="AB8" exitstate="open"/>
    <sb id="AB9" exitstate="open"/>
    <sb id="AB10" exitstate="open"/>
    <sb id="AB11" exitstate="open"/>
    <sb id="AB12" exitstate="open"/>
    <sb id="AB13" exitstate="open"/>
    <sb id="AB14" exitstate="open"/>
    <co id="S1" cmd="on"/>
    <exit cmt="Aufstellbloecke geoeffnet"/>
  </then>
</if>
 
</xmlscript>

Das Skript wird wie üblich als Aktion definiert und einmal als Systemaktion mit dem Status "on-auto" (Automatik ein/aus) und einmal als Systemaktion mit dem Status "stoplocs" (Loks stoppen) konfiguriert. Der Schalter S1 wird im Skript mitgesetzt, um eine synchrone Anzeige zu gewährleisten (Schalter grau → ABe geschlossen, Schalter weiß → ABe geöffnet).


Steuerung Anzahl gefahrener Runden, Innenbahn

Das Skript steuert die Anzahl der gefahrenen Runden in der Innenbahn. Jeder Zug soll 5 Runden drehen und dann wieder in den Bf. fahren. Ist die fünfte Runde erreicht, wird der Melder B_I_1 auf ON gesetzt. Der Melder ist in der Fahrstraße (FS) [I_2-]-[I_3+] unter "Rückmelder" eingetragen und sperrt diese FS im gesetzten Zustand; der Zug nimmt die FS [I_2-]-[EF-]. Ist die fünfte Runde nicht erreicht, wird die FS [I_2-]-[EF-] gesperrt. Das Öffnen der FS und das OFF-Setzen des Melders kann im Skript nachvollzogen werden.

<?xml version="1.0" encoding="UTF-8"?>
<xmlscript desc="Script_Steuerung_Runden_I">
 
<!-- Aufruf Innenbahn, Block I_1 ENTER -->
<if condition="%callerid% # I_1">
  <then>
    <!-- Neuer Zug aus AB_1-7, W10 oder W14 ist abzweigend -->
    <if state="sw W10 = turnout|sw W14 = turnout" alltrue="false">
      <then>
	<vr id="var_%lcid%" value="0"/>
	<!-- <trace text="I: var_%lcid%: #var_%lcid%"/> -->
	<fn id="%lcid%" fnchanged="0" f0="true"/>
	<exit cmt="Script_Steuerung_Runden_I: ENTER I_1, Zähler=0 -> verlassen"/>
      </then>
      <else>
	<vr id="var_%lcid%" value="#var_%lcid% + 1"/>
	<!-- <trace text="I: var_%lcid%: #var_%lcid%"/> -->
	<exit cmt="Script_Steuerung_Runden_I: ENTER I_1, Zähler+=1 -> verlassen"/>
      </else>
    </if>
  </then>
</if>
 
<!-- Aufruf Innenbahn, Block I_2 RESERVED -->
<if condition="%callerid% # I_2">
  <then>
    <!-- Zählerstand erreicht? -->
    <if condition="#var_%lcid% > 3">
      <!-- Ja -->
      <then>
	<!-- Melder B_I_1 setzen -->
	<fb id="B_I_1" cmd="on"/>
	<!-- <trace text="I: Melder B_I_1 ON"/> -->
	<exit cmt="Script_Steuerung_Runden_I: RESERVED I_2, Melder B_I_1 ist ON"/>
      </then>
      <!-- Nein -->
      <else>
	<!-- FS nach EF sperren -->
	<st id="[I_2-]-[EF-]" state="closed"/>
	<!-- <trace text="I: Zähler passt nicht, FS gesperrt"/> -->
        <exit cmt="Script_Steuerung_Runden_I: RESERVED I_2, Zähler passt nicht, FS EF gesperrt"/>
      </else>
    </if>
  </then>
</if>
 
<!-- Aufruf Innenbahn, Block I_3 RESERVED -->
<if condition="%callerid% # I_3" state="st [I_2-]-[EF-] = closed" alltrue="true">
  <then>
    <!-- FS EF öffnen -->
    <st id="[I_2-]-[EF-]" state="open"/>
    <!-- <trace text="I: FS EF offen"/> -->
    <exit cmt="Script_Steuerung_Runden_I: RESERVED I_3, FS EF offen"/>
  </then>
</if>
 
<!-- Aufruf Innenbahn, Block EF ENTER -->
<if condition="%callerid% # EF">
  <then>
    <!-- Melder B_I_1 OFF -->
    <fb id="B_I_1" cmd="off"/>
    <!-- <trace text="I: Melder B_I_1 OFF"/> -->
    <fn id="%lcid%" fnchanged="0" f0="false"/>
    <exit cmt="Script_Steuerung_Runden_I: ENTER EF, Melder B_I_1 ist OFF"/>
  </then>
</if>
 
</xmlscript>

Zusätzlich schaltet das Skript die Spitzenbeleuchtung der jeweils fahrenden Lok ein bzw. aus. Die Trace-Zeilen sind auskommentiert, können bei Bedarf aber leicht aktiviert werden. Die Aktionsaufrufobjekte des Skripts und die zugehörigen Stati sind aus den Kommentarzeilen zu entnehmen.


Steuerung Anzahl gefahrener Runden, Außenbahn

Das Skript steuert die Anzahl der gefahrenen Runden in der Außenbahn. Das Skript arbeitet analog dem o. a. Skript. Hier wird der Melder B_A_1 gesetzt und das Aktivieren/Deaktivieren der Weiche W19 steuert die Fahrt in den Bf. Hier wird die Weiche als Steuerungsobjekt verwendet, da ansonsten 7 FS manipuliert werden müssten. Das Manipulieren der Weiche und das OFF-Setzen des Melders kann im Skript nachvollzogen werden.

<?xml version="1.0" encoding="UTF-8"?>
<xmlscript desc="Script_Steuerung_Runden_A">
 
<!-- Aufruf Außenbahn, Block A_1 ENTER -->
<if condition="%callerid% # A_1">
  <then>
    <!-- Neuer Zug aus AB_8-14, W27 ist abzweigend -->
    <if state="sw W27 = turnout">
      <then>
        <vr id="var_%lcid%" value="0"/>
        <!-- <trace text="A: var_%lcid%: #var_%lcid%"/> -->
        <fn id="%lcid%" fnchanged="0" f0="true"/>
        <exit cmt="Script_Steuerung_Runden_A: ENTER A_1, Zähler=0 -> verlassen"/>
      </then>
      <else>
        <vr id="var_%lcid%" value="#var_%lcid% + 1"/>
        <!-- <trace text="A: var_%lcid%: #var_%lcid%"/> -->
        <exit cmt="Script_Steuerung_Runden_A: ENTER A_1, Zähler+=1 -> verlassen"/>
      </else>
    </if>
  </then>
</if>
 
<!-- Aufruf Außenbahn, Block A_2 RESERVED -->
<if condition="%callerid% # A_2">
  <then>
    <!-- Zählerstand erreicht? -->
    <if condition="#var_%lcid% > 3">
      <!-- Ja -->
      <then>
	<!-- Melder B_A_1 setzen -->
	<fb id="B_A_1" cmd="on"/>
	<!-- <trace text="A: Melder B_A_1 ON"/> -->
	<fn id="%lcid%" fnchanged="0" f0="false"/>
	<exit cmt="Script_Steuerung_Runden_A: RESERVED A_2, Melder B_A_1 ist ON"/>
      </then>
      <!--Nein -->
      <else>
	<!-- Weiche W19 sperren -->
	<sw id="W19" cmd="close"/>
	<!-- <trace text="A: Zähler passt nicht, Weiche W19 gesperrt"/> -->
        <exit cmt="Script_Steuerung_Runden_A: RESERVED A_2, Zähler passt nicht, Weiche W19 gesperrt"/>
      </else>
    </if>
  </then>
</if>
 
<!-- Aufruf Außenbahn, Block A_3 RESERVED -->
<if condition="%callerid% # A_3" state="sw W19 = closed" alltrue="true">
  <then>
    <!-- Weiche in Betrieb nehmen -->
    <sw id="W19" cmd="open"/>
    <!-- <trace text="A: Weiche W19 in Betrieb"/> -->
    <exit cmt="Script_Steuerung_Runden_I: RESERVED I_3, Weiche W19 in Betrieb"/>
  </then>
</if>
 
<!-- Aufruf Außenbahn, Weiche W20 abzweigend -->
<if condition="%callerid% # W20">
  <then>
    <!-- Melder B_A_1 OFF -->
    <fb id="B_A_1" cmd="off"/>
    <!-- <trace text="A: Melder B_A_1 OFF"/> -->
    <exit cmt="Script_Steuerung_Runden_A: W20 abzweigend, Melder B_A_1 ist OFF"/>
  </then>
</if>
 
</xmlscript>

Zusätzlich schaltet das Skript die Spitzenbeleuchtung der jeweils fahrenden Lok ein bzw. aus. Die Trace-Zeilen sind auskommentiert, können bei Bedarf aber leicht aktiviert werden. Die Aktionsaufrufobjekte des Skripts und die zugehörigen Stati sind aus den Kommentarzeilen zu entnehmen.


Steuerung Ausfahrt aus Block AF

Es soll verhindert werden, dass ein aus Block "AF" ausfahrender Zug auf der Innen- und Außenbahn nahende Züge zum Halt zwingt. Auch hier wird als Steuerungsobjekt ein Melder ("B_AF") verwendet, der, als Rückmelder in die FS "[AF-]-[A_1-]" eingetragen, die FS einstellbar macht oder nicht. Alternativ könnte man die FS konventionell öffnen/schließen und das FS-Symbol für die Visualisierung verwenden.

<?xml version="1.0" encoding="UTF-8"?>
<xmlscript desc="Script_Steuerung_Ausfahrt_AF">
 
<!-- Aufruf Innenbahn, Block I_12 ENTER -->
<if condition="%callerid% # I_12">
  <then>
    <if condition="#var_%lcid% <= 4">
	  <then>
	    <!-- Zug innen, fährt nicht in den Bf -->
		<!-- Melder B_AF setzen -->
		<fb id="B_AF" cmd="on"/>
		<!-- Zweiter Zug? Variable var_B_AF_I_2 setzen -->
		<if condition="#var_B_AF_I_1 = 1">
		  <then>
		    <vr id="var_B_AF_I_2" value="1"/>
			<!-- <trace text="I_12: var_B_AF_I_2: #var_B_AF_I_2"/> -->
		  </then>
		</if>
		<!-- Erster Zug, Variable var_B_AF_I_1 setzen -->
		<vr id="var_B_AF_I_1" value="1"/>
		<!-- <trace text="I_11: var_B_AF_I_1: #var_B_AF_I_1"/> -->
	    <exit cmt="Script_Steuerung_Ausfahrt_AF: ENTER I_12, Melder B_AF ON -> exit"/>
      </then>
	  <else>
	    <!-- Zug innen, fährt in den Bf -> Variable var_B_AF_I_* = 0 setzen -->
		<vr id="var_B_AF_I_1" value="0"/>
		<!-- <trace text="I_11 -> Bf: var_B_AF_I_1: #var_B_AF_I_1"/> -->
		<vr id="var_B_AF_I_2" value="0"/>
		<!-- <trace text="I_11 -> Bf: var_B_AF_I_2: #var_B_AF_I_2"/> -->
		<exit cmt="Script_Steuerung_Ausfahrt_AF: ENTER I_12, Bf., Var = 0 -> exit"/>
	  </else>
	</if>
  </then>
</if>
 
<!-- Aufruf Außenbahn, Block A_34 ENTER -->
<if condition="%callerid% # A_34">
  <then>
	<!-- Zug kommt Außenbahn -> Melder B_AF setzen -->
	<fb id="B_AF" cmd="on"/>
	<!-- Zug kommt Außenbahn -> Variable var_B_AF_A setzen -->
	<vr id="var_B_AF_A" value="1"/>
	<exit cmt="Script_Steuerung_Ausfahrt_AF: ENTER A_34, Melder B_AF ON -> exit"/>
  </then>
</if>
 
<!-- Aufruf Innenbahn, Block I_3 ENTER -->
<if condition="%callerid% # I_3">
  <then>
    <!-- Zweiter Zug? -->
    <if condition="#var_B_AF_I_1 = 0">
	  <then>
	    <!-- Ja: var_B_AF_I_2 = 0 -->
	    <vr id="var_B_AF_I_2" value="0"/>
		<!-- <trace text="I_3: var_B_AF_I_2: #var_B_AF_I_2"/> -->
	  </then>
	</if>
    <!-- Erster Zug, var_B_AF_I_1 = 0 -->
    <vr id="var_B_AF_I_1" value="0"/>
	<!-- <trace text="I_3: var_B_AF_I_1: #var_B_AF_I_1"/> -->
    <!-- Anrückung außen und Nachrückung innen? -->
    <if condition="#var_B_AF_A = 0|#var_B_AF_I_2 = 0" alltrue="true">
	  <then>
	    <!-- Zweiter Zug innen vorbei und keine Anrückung außen -> Melder B_AF rücksetzen -->
	    <fb id="B_AF" cmd="off"/>
		<vr id="var_B_AF_A" value="0"/>
		<!-- <trace text="I_3: var_B_AF_A: #var_B_AF_A"/> -->
		<vr id="var_B_AF_I_2" value="0"/>
		<!-- <trace text="I_3: var_B_AF_I_2: #var_B_AF_I_2"/> -->
		<exit cmt="Script_Steuerung_Ausfahrt_AF: ENTER I_3, Melder B_AF OFF -> exit"/>
	  </then>
	</if>
	<exit cmt="Script_Steuerung_Ausfahrt_AF: ENTER I_3, var_B_AF_I_1 = 0 -> exit"/>
  </then>
</if>
 
<!-- Aufruf Außenbahn, Block A_1 ENTER -->
<if condition="%callerid% # A_1">
  <then>
    <vr id="var_B_AF_A" value="0"/>
	<!-- <trace text="A_3: var_B_AF_A: #var_B_AF_A"/> -->
    <!-- Anrückung Innenbahn? -->
    <if condition="#var_B_AF_I_1 = 0|#var_B_AF_I_2 = 0" alltrue="true">
	  <then>
	    <!-- Zug Außenbahn vorbei und keine Anrückung Innenbahn -> Melder B_AF rücksetzen -->
    	<fb id="B_AF" cmd="off"/>
		<vr id="var_B_AF_I_1" value="0"/>
		<!-- <trace text="A_1: var_B_AF_I_1: #var_B_AF_I_1"/> -->
	    <vr id="var_B_AF_I_2" value="0"/>
		<!-- <trace text="A_1: var_B_AF_I_2: #var_B_AF_I_2"/> -->
	    <exit cmt="Script_Steuerung_Ausfahrt_AF: ENTER A_1, Melder B_AF OFF -> exit"/>
	  </then>
	</if>
	<exit cmt="Script_Steuerung_Ausfahrt_AF: ENTER A_1, var_B_AF_A = 0 -> exit"/>
  </then>
</if>
 
</xmlscript>


Erklärungen zum Skript:
Es fahren max. je 2 Züge auf der Innen- und Außenbahn. Der Grundablauf ist, dass die auf der Innen- und Außenbahn verkehrenden Züge bei Annäherung zum Block "AF" einen Melder "B_AF" setzen und nach Passieren des Blocks "AF" wieder zurücksetzen.

Aufruf in Block "I_12" bei ENTER:
Zuerst wird geprüft, ob der aktuelle Zug in seiner letzten Runde ist (kleiner gleich 4). Wenn nein, wird der Melder "B_AF" gesetzt. Dieser verhindert, dass die FS "[AF-]-[A_1-]" gestellt werden kann. Weiters wird geprüft, ob der aktuelle Zug ein zweiter Zug ist ("var_B_AF_I_1" ist schon "1") und die Variable "var_B_AF_I_2" auf "1" gesetzt. Wenn es kein zweiter Zug ist, wird die "var_B_AF_I_1" auf "1" gesetzt. Zum Schluss wird das Skript verlassen. Wenn ja ("else"-Zweig, Zug ist in seiner letzten Runde), werden die Variablen "var_B_AF_I_1" und "var_B_AF_I_2" "0" gesetzt (sie werden nicht mehr gebraucht, der Zug fährt in den Bf. und blockiert somit eine potentielle Ausfahrt aus AF nicht). Der Melder "B_AF" bleibt ungesetzt, ein Zug kann via FS "[AF-]-[A_1-]" in die Außenbahn ausfahren (sofern kein ankommender Zug auf der Außenbahn den Melder "B_AF" gesetzt hat). Zum Schluss wird das Skript verlassen.

Aufruf in Block "A_34" bei ENTER:
Ein Zug rückt auf der Außenbahn an, der Melder "B_AF" wird gesetzt, die Variable "var_B_AF_A" wird auf "1" gesetzt, das Skript verlassen. Die Variable wird hier gesetzt, um im Block "I_3" zu verhindern, dass der Melder "B_AF" zurückgesetzt wird, obwohl auf der Außenbahn ein Zug anrückt.

Aufruf in Block "I_3" bei ENTER:
Es wird geprüft, ob der aktuelle Zug ein zweiter Zug (Nachfolgezug) auf der Innenbahn ist ("var_B_AF_I_1 = 0"). Wenn ja, wird die Variable "var_B_AF_I_2" gleich "0" gesetzt. Wenn nein, wird "var_B_AF_I_1" zurückgesetzt (="0"). Danach wird geprüft, ob kein Zug auf der Außenbahn anrückt ("var_B_AF_A = 0") und kein zweiter Zug auf der Innenbahn am Weg ist ("var_B_AF_I_2 = 0"). Wenn ja, wird der Melder "B_AF" zurückgesetzt, die Variablen "var_B_AF_A" und "var_B_AF_I_2" jedenfalls auf "0" gesetzt (redundant, könnte gelöscht werden). Am Ende dieses Programmzweiges wird das Skript verlassen. Wenn nein, wird das Skript verlassen (der Melder "B_AF" bleibt gesetzt).

Aufruf in Block "A_1" bei ENTER:
Der Zug auf der Außenbahn von "A4" (oder auch von "AF") kommend, setzt die Variable "var_B_AF_A" hier definiert zurück ("0"). Danach wird geprüft, ob nicht zwei Züge auf der Innenbahn im Anrollen sind. Wenn ja (es kommt kein Zug auf der Innenbahn), wird der Melder "B_AF" zurückgesetzt, die beiden Variablen für die Innenbahn "var_B_AF_I_1" und "var_B_AF_I_2" = "0" gesetzt und das Skript verlassen. Wenn nein (es kommt mind. ein Zug auf der Innenbahn), wird das Skript verlassen (der Melder "B_AF" bleibt gesetzt).

Lebenszyklus der Anlage

Oktober 2019 bis xx.xx.2020

cds/german/skripte_2019_20.txt · Last modified: 2020/01/01 13:11 by cds