Der von Gregg Berman als public domain zur Verfügung gestellte DCC++ Controller, eine in Processing geschriebene Java Applikation, muss konfiguriert werden, damit er zur Steuerung des eigenen Layout verwendet werden kann.
Eine echte Anleitung, wie diese Konfiguration abzulaufen hat ist leider nirgendwo zu finden, weshalb ich mich hingesetzt und die Vorgehensweise für uns aufgeschrieben habe.
DCC++ Modellbahn-Steuerung von Gregg E. Berman
Ein paar Tipps zur Implementierung einer Steuerung des eigenen Layouts mit DCC++
Base Station
Der Code überprüft, ob in der Arduino IDE ein Arduino Mega oder eine Arduino Uno als Zielplattform eingestellt ist. Wird ein Arduino Nano V3 eingestellt, verweigert der Code das Compilieren.
Mit einem zusätzlichen #define in DCCpp_Uno.h ab Zeile 29
gaukeln wir dem Code vor, wir arbeiteten mit einem Uno und alles läuft prima, der Nano V3 ist bis auf den Formfaktor 1:1 kompatibel zum Uno.
DCCpp_Controller
Der Controller läuft unter Processing, Processing ist also auf dem Rechner vorher zu installieren. Processing erfordert JAVA, das allerdings für die Arduino-IDE ebenfalls notwendig ist, die Chancen stehen nicht schlecht, dass JAVA bereits installiert ist.
Hinweis
Windows RT (die Sparvariante von Windows) ist nicht für DCCpp_Controller geeignet,
das für den Ablauf von Processing benötigte JAVA ist nie für Windows RT implementiert worden (Stand 2019).
Gleise anlegen
Das eigene Layout muss in der Datei „controllerConfig.pde“ explizit einprogrammiert werden. Der entsprechende Code beginnt ab Zeile 371 (im Original vom 20.12.2015), bzw. ab dem Kommentar
// CREATE MAIN LAYOUT AND DEFINE ALL TRACKS.
Die Aufrufnotation ist leider nicht beschrieben, aber mit etwas Gehirnakrobatik und Stöbern in den Sourcen lässt sich das herausfinden. Meine Erkenntnisse habe ich unten zusammengetragen.
In der weiteren Beschreibung bezieht sich die Angabe von „Pixel“ immer auf das Fenster des Programms „DCC-Controller“. Bezug ist die Ecke links oben mit den Koordinaten (0, 0).
Die unten erwähnte “Platte” ist übrigens nur virtuell vorhanden und wird auf dem Bildschirm nicht angezeigt, man fischt also zu Beginn etwas im Trüben. Die angegebenen Koordinaten sind aber ein guter Start und sollte sich später herausstellen, dass die linke obere Ecke so nicht passt, kann sie einfach an dieser einen Stelle geändert werden, das komplette Layout verschiebt sich dann mit.
Das Layout wird zuerst angelegt mit
layout=new Layout(325,50,1000,80*25.4,36*25.4);
Die Parameter bestimmen der Reihe nach
Als nächstes wird das erste Gleis definiert
Track a11 = new Track(layout,20,850-korrektur2,228,90); // Gerade 228 mm
Die Parameter bestimmen der Reihe nach
Die Koordinaten dieses Startpunktes lassen sich erst final einstellen, wenn einige Gleise definiert sind und man einen Überblick über die Ausdehnung auf dem Bildschirm bekommt. Ist aber kein Problem, das komplette Layout wird mit diesen Koordinaten verschoben, denn alle anderen Gleise werden relativ zueinander definiert.
Weitere Schienen werden immer an eine bereits vorhandene Schiene angehängt, die Notation ist also einfacher, es müssen keine Koordinaten mehr angegeben werden.
Es gibt mehrere Notationen, z.B. für gerade und gebogene Gleise.
Ein gerades Gleis wird platziert mit dem Befehl
Track a12 = new Track(a11,1,228); // Gerade 228 mm
Die Parameter bestimmen der Reihe nach
Ein gebogenes Gleis wird platziert mit dem Befehl
Track a13 = new Track(a12,1,286,-7.5); // Bogen Radius 286, Kreisbogen 7,5°
Die Parameter bestimmen der Reihe nach
Es ist sinnvoll, zuerst für jedes auf dem Layout befindlichen Gleis einen eindeutigen Namen zu vergeben, bestenfalls als sprechenden Namen (Bruecke, Abstell, Kreis, ...) mit fortlaufender Nummer oder einfach durchnummeriert.
Ich habe mich auf „a“ für Abstellgleis und „k“ für Kreis beschränkt, wobei ich „a1“ als Präfix für Abstellgleis 1 verwendet habe und direkt anschließend die Gleise dieses Abstellgleises durchnummeriert angehängt habe, also a11, a12, ..., a19, a110, a111 usw.
Jede sinnfällige Notation ist geeignet, die Namen müssen allerdings den Variablennamen-Konventionen von JAVA entsprechen.
Ich habe im Code in jeder Zeile einen Kommentar angehängt. Das hilft ungemein bei der weiteren Entwicklung des Layout, denn im Prinzip muss nach ein paar Eingaben eigentlich nur noch kopiert werden und der Name des Gleises sowie dessen Ankerpunkt angepasst werden.
Weichen und Kreuzungen werden einfach aus zwei passenden Gleisstücken zusammengesetzt, eine Weiche links ergibt sich z.B. aus
Track a51 = new Track(a28,1,286,22.5); // Weiche links – Bogen
Track a29 = new Track(a28,1,114); // Weiche links – Gerade
eine Bogenweiche entsprechend aus
Track a17 = new Track(a16,1,600,-15); // Bogenweiche links – aussen
Track k12 = new Track(a17,1,286,-22.5); // Bogen Radius 286, Kreisbogen 22,5°
Track k13 = new Track(k12,2,286,30); // Bogenweiche links – innen
Beim Beispiel der Bogenweiche sieht man, dass der innere Bogen hier am vorderen Ende des vorherigen Gleises „k12“ angehängt wird. Das ergibt sich aus der Richtung, in der die Weiche beim Definieren des Layouts angefahren wird. In meinem Fall kam ich vom rechten Schenkel der Weiche, musste also erst ein weiteres Gleis an der Weiche anhängen, an das ich dann den zweiten Schenkel der Weiche anhängen konnte.
Zur Verdeutlichung hier eine Abbildung des betreffenden Abschnitts des Layouts:
Beim verwendeten Gleisplanprogramm „Railroad_Professional“ von Rodrigo Supper werden Gleisenden, die nicht exakt „einrasten“ schwarz dargestellt, eingerastete Enden sind blau.
Die beiden im Bild sichtbaren schwarz markierten Verbindungen ergeben sich auf dem Layout aus Ungenauigkeiten und ließen sich nicht fehlerfrei im Programm modellieren.
Da in DCCpp_Controller immer mit exakten Gleisanschlüssen gearbeitet wird - jedes Gleis wird an ein vorhergehendes angehängt - müssen solche Ungenauigkeiten mit „virtuellen Zwischenstücken“ ausgeglichen werden, damit zum Schluss das Ende eines Kreises wieder genau auf den Anfang trifft.
Bei einfachen Geometrien ergeben sich gemeinhin keine Probleme, aber bei komplizierten Layouts kann das schon passieren. Hier ist dann die passende Stelle im Gleisplan zu finden und es muss experimentell ein passendes Gleisstück im Code eingebaut werden. Der Vorteil von DCCpp-Controller ist in diesem Fall, dass die Gleise durch Angabe der Länge in Millimetern frei definiert werden können. In Railroad Professional können nur die in der verwendeten Gleis-Bibliothek vorhandenen Gleise platziert werden und die Bibliothek enthält im Allgemeinen nur die vom Hersteller angebotenen Gleis-Typen. (Idee: man könnte mit dem Flexgleis die Ausgleichsstücke auch in Railroad Professional nachbilden... ist zu testen)
Ist das Layout komplett programmiert (zwischendurch immer mal wieder speichern nicht vergessen!), müssen die Weichen als Solche festgelegt werden.
Das erfolgt im Anschluss ab dem Kommentar
// CREATE TURNOUT BUTTONS and ADD TRACKS FOR EACH TURNOUT
Die oben beschriebene Bogenweiche wird so definiert
tButton1 = new TrackButton(20,20,1);
tButton1.addTrack(k13,0);
tButton1.addTrack(a17,1);
Die Aufrufe im Einzelnen
tButton1 = new TrackButton(20,20,1);
Die Parameter bestimmen der Reihe nach
Mit den beiden Aufrufen
tButton1.addTrack(k13,0);
tButton1.addTrack(a17,1);
werden die Gleise k13 und a17 der Weiche zugeordnet, die Parameter „0“ und „1“ bestimmen die Defaultlage der Weiche und das jeweils aktive Gleis, wenn später die Weiche mit einem DCC++ Befehl betätigt wird. Der Dcc++ Befehl enthält die gewünschte Lage in Form des letzten Parameters „0“ oder „1“.
In bestimmten Situationen ist es für den ordnungsgemäßen Betrieb der Anlage erforderlich, dass zwei Weichen immer gleichzeitig und abhängig voneinander geschaltet werden müssen:
Wenn der Wechsel vom zweiten auf das vierte Gleis erfolgen soll, müssen immer beide Weichen auf Kurve geschaltet sein:
Im anderen Fall sollten beide Weichen auf Geradeausfahrt stehen:
Diese Abhängigkeit wird im Programm modelliert indem alle vier betroffenen Gleisabschnitte einem „Button“ (hier Nummer 10) zugeordnet werden:
tButton10 = new TrackButton(20,20,10); // 10+11 müssen immer gleichzeitig schalten
tButton10.addTrack(k413,0); // gehört zu Weiche 10
tButton10.addTrack(k418,1); // gehört zu Weiche 10
tButton10.addTrack(k315,0); // gehört zu Weiche 11
tButton10.addTrack(k420,1); // gehört zu Weiche 11
Ist das abgeschlossen, können alle Weichen vom Programm aus bedient werden (vorausgesetzt, dem Arduino in der Base Station wurden die Weichen mit ihren IDs und Adressen/Subadressen bereits bekannt gemacht, siehe Einschub „Vorgriff auf später”).
Das Programm hat noch ein Schmankerl in Form von sogenannten „Routen“. Hiermit können ganze Gleisabschnitte zusammengefasst und alle zugehörigen Weichen mit einem Click passend geschaltet werden. Netterweise zeigt das Programm diese definierten Straßen aufgehellt an, wenn mit der Maus der zugehörige Button überfahren wird (MouseOver). Falsch gestellte Weichen werden dabei rot hervorgehoben (siehe Beispiele weiter unten).
Diese Gleisstraßen werden im Programm ab dem Kommentar
// CREATE ROUTE BUTTONS and ADD TRACKS and TURNOUT BUTTONS
definiert.
Einfache Routen, z.B. ein Abstellgleis, erhalten einen Clickpunkt für die Maus als Auslöser:
rButton1 = new RouteButton(a11,20,20);
rButton1.addTrackButton(tButton1,1);
rButton1.addTrack(a11);
rButton1.addTrack(a12);
rButton1.addTrack(a13);
rButton1.addTrack(a14);
rButton1.addTrack(a15);
rButton1.addTrack(a16);
rButton1.addTrack(a17);
In der ersten Zeile wird die Route erzeugt und der Hotspot definiert, X- und Y-Ausdehnung jeweils wieder 20 Pixel, sowie das Gleisstück, auf dem der Button platziert werden soll (hier a11). Der Button wird in der Mitte der Schiene platziert.
Anschließend wird mit
rButton1.addTrackButton(tButton1,1);
die Bogenweiche als der Route zugehörig angegeben und anschließend alle Gleisstücke, die dazu gehören. Alle diese hier angegebenen Gleise und Weichen werden später bei MouseOver hell dargestellt.
Das Abstellgleis das oben definiert wurde.
Der grüne Punkt ist der Hotspot der Route.
Bei MouseOver werden die Gleise der Route hell markiert.
Die Bogenweiche steht falsch für die Route, ist deshalb rot markiert.
Bei Mausclick wird die Route aktiviert, die Weiche wird geschaltet und der Button ist hellgrün.
Kompliziertere Routen, z.B. komplette Kreise, Kombinationen oder Gleisharfen, erfordern dieselben Maßnahmen im Programm, hierbei kann es dann notwendig sein, dass mehrere Weichen (tButtons#) und jede Menge an Gleisen der Route zugeordnet werden.
Das Abstellgleis im Bild muss über vier passend eingestellte Weichen erreicht werden.
Die Definition eines Kreises als Route mit eigenem Button erfolgt über diesen Aufruf:
rButton10 = new RouteButton(rX,rY,80,40,"Innen");
rButton10.addTrackButton(tButton9,0);
rButton10.addTrackButton(tButton11,0);
rButton10.addTrack(k44);
rButton10.addTrack(k45);
rButton10.addTrack(k46);
...
Die Aufrufe im Einzelnen
rButton10 = new RouteButton(rX,rY,80,40,"Innen");
Die Parameter bestimmen der Reihe nach
Der Button für die Maus wird dann so dargestellt:
Bei MouseOver passiert Folgendes:
Die gesamte Route wird grün hervorgehoben. Die beiden Weichen stehen falsch, was durch die rote Markierung angezeigt wird.
Wird die Route per Mausclick aktiviert, werden die Weichen (alle vier) passend geschaltet und der Button wird hell dargestellt:
Loks anlegen
Loks, die über die Oberfläche gesteuert werden sollen, müssen, wie die Gleise, im Programm programmiert werden. Das passiert ab der Zeile 289 (im Original vom 20.12.2015), bzw. ab dem Kommentar
// CREATE THROTTLE, DEFINE CAB BUTTONS, and SET FUNCTIONS FOR EACH CAB
wobei die Koordinaten direkt unterhalb dieser Zeile sowie der Aufruf
throttleA = new Throttle(tAx,tAy,1.3);
unverändert bleiben können. Die Koordinaten tAx, tAy bilden den Ankerpunkt für die komplette Liste der Loks, durch Anpassung dieser Koordinaten kann die Anzeige der Loks an die passende Stelle geschoben werden, sollte sich das als notwendig erweisen. Die Koordinaten rX, rY bestimmen den Ankerpunkt der Route-Buttons, die wir weiter oben bereits besprochen haben.
Eine Lok wird definiert mit
cab0003 = new CabButton(tAx-125,tAy-150,50,30,150,15,3,throttleA);
cab0003.setThrottleDefaults(100,50,-50,-45);
cab0003.functionButtonWindow(220,59,70,340,backgroundColor,backgroundColor);
cab0003.setFunction(35,15,60,22,60,10,0,"Headlight",ButtonType.NORMAL,CabFunction.F_LIGHT);
cab0003.setFunction(35,45,60,22,60,10,1,"Tailight",ButtonType.NORMAL,CabFunction.R_LIGHT);
Die erste Zeile definiert den Button für die Lok, der Button wird links vom Schieberegler für die Geschwindigkeit platziert.
cab0003 = new CabButton(tAx-125,tAy-150,50,30,150,15,3,throttleA);
Die Parameter bestimmen der Reihe nach
Die zweite Zeile legt die verschiedenen Geschwindigkeiten fest
cab0003.setThrottleDefaults(100,50,-50,-45);
Die Parameter bestimmen der Reihe nach
Die dritte Zeile legt die Funktionsbuttons rechts des Schiebereglers fest
cab0003.functionButtonWindow(220,59,70,340,backgroundColor,backgroundColor);
Die Parameter bestimmen der Reihe nach