Pendelzugsteuerung mit Arduino

Das ein Arduino wahrscheinlich weitaus mehr kann, als auf der Eisenbahnanlage ein paar Ampeln zu steuern oder Befehle von einem Stellpultprogramm auszuführen bzw. zurückzumelden dürfte inzwischen klar sein. Nichtsdestotrotz werde ich da skleine Board versuchen einzusetzen, wo es eben geht. Beim Thema Pendelzugsteuerung gibt es zwar auch fertige zu kaufen - aber was wäre die Modellbahn ohne Bastelei :)

Grundproblem ist für mich immer die Überlegung, dass ich gerne mit Gleisbesetztmeldern arbeiten würde, um Reedkontakte und Magnete zu vermeiden. Alle Besetztmelder, die ich gefunden habe, arbeiten nach dem Prinzip, dass ein Stromverbraucher (Motor, Beleuchtung) auch Strom verbraucht und somit die Spannung abfällt. Das stellen diese Melder fest, indem sie die Spannung des überwachten Bereiches mit der 'unverbrauchten' Fahrspannung vergleichen - ist sie niedriger, dann ist der Abschnitt halt besetzt. So weit so gut - aber: Ein Abschnitt, in dem eine Lok nur steht, weil der Abschnitt abgeschaltet ist, kann ja nicht wirklich verglichen werden - vielleicht sehe ich das falsch, wer also etwas zu dem Thema weiß darf sich gerne bei mir melden :)

Bestehende Pendelzugsteuerungen haben zudem (meistens) die Angewohnheit, dass nur an einem Ende der Pendelstrecke ein Ausweichgleis existiert und somit "nur" zwei Züge pendeln - damit fährt zwangsläufig ein Zug hin und direkt wieder zurück. Doof. Will ich nicht. Ich will, dass auch am zweiten Endpunkt der Pendelstrecke ein anderer Zug zurückfährt, damit der Pendelbetrieb nicht so offensichtlich wird - gerade bei Straßenbahnen würde das doch sehr auffallen.

Also kam mir grundsätzlich die Idee, vor dem Halteabschnitt des Endhaltepunktes in jedes Gleis einen Kontakt einzusetzen. Im Grunde fand ich die Idee gut - bis mir auffiel, dass dieser Kontakt ja richtungsunabhängig ausgelöst wird, d.h. er wird ausgelöst, wenn ein Zug den Haltebereich verlässt oder in diesen Einfährt. Das oder stört, aber gewaltig. Andererseits: Wenn jeder Halteabschnitt an den Endpunkten so einen Kontakt hat dann kann ich doch die Reihenfolge messen, mit denen diese Kontakte durchfahren werden...

...bei 4 Endgleisen sind das 4 Kontakte. Bedeutet im Klartext: Es gibt nur 4 Zustände, in denen die Kontakte im Pendelbetrieb nacheinander durchfahren werden, nämlich immer VON einem Endgleiskontakt NACH einem Endgleiskontakt. Zur Verdeutlichung mal eine Zeichnung einer Pendelstrecke mit je 2 Endgleisen:

w_93

Wie man sieht, sind es 4 verschiedene Zustände, nach denen sich das Spiel wiederholt - der fünfte "Zustand" entspricht dem ersten, auch wenn die Züge andere sind.
Und zwar fährt ein Zug immer von:

1 -> 2 oder
3 -> 1 oder
4 -> 3 oder
2 -> 4

Und da kommt ein Arduino in's Spiel: Wenn man jedem Kontaktgleis einen Eingang des Arduino-Boards zuweist kann man feststellen, welches Kontaktgleis gerade durchfahren wurde. Die Reihenfolge steht dann für den Schaltvorgang, der ausgelöst werden muss. Und die Reihenfolge ist immer eindeutig: "12", "31", "43" oder "24". Die Logiktabelle sieht dann wie folgt aus:

w_92

Soweit noch ganz einfach. Jetzt muss ich nur noch (haha) ein wenig Gedanken an das Programm verschwenden, in welcher Reihenfolge wann was abgefragt und wann was gesteuert werden muss - die Grundzüge dazu habe ich fertig (Programmflussdiagramm - das ist eine schematische Darstellung, was das Programm wann macht und welche Entscheidungen es trifft). Was mir gerade noch so einfällt - der Teufel ist ein Eichhörnchen und steckt im Detail - ist, dass ich ja auch die Stromrichtung umkehren muss... grübel...

So, gut ein Jahr ist in’s Land gegangen, und da meine Anlage sich dem Rohbaustadium nähert, werden die Gedankn zu einigen Problemchen wieder dichter: Könnte man auch eine Pendelstrecke anlegen mit je drei Endgleisen, also für fünf Züge? Hmja, das geht:

Pendelzugsteuerung für 5 Züge

Pendelstrecke_5_Bahnen

Das Bildchen zeigt die Logik, die dahintersteht, sowie die daraus resultierenden Abfragen, also z.B.:

WENN L1 besetzt UND L2 besetzt UND L3 besetzt UND R1 besetzt UND R2 besetzt UND R3 frei DANN Strom nach rechts UND Weichen von L3 nach R3 schalten UND Fahrt in L3 freigeben.

In Basic kann ich das...

...jetzt nur noch im Arduino, denn das kleine Board kann so etwas auch eigenständig und muss nicht nur als Schaltzwischenbaustein für VB2010 herhalten!

// *********************************************
//                                             *
//       Pendelzugsteuerung für 5 Züge         *
//           - 3 Gleise pro Seite -            *
//                                             *
// *********************************************

  // Anschlüsse:

    //a: Melder

    

    int L1 = 97;     // Links 1 Melder - PIN A0

    int L2 = 96;     // Links 2 Melder - PIN A1

    int L3 = 95;     // Links 3 Melder - PIN A2

    int R1 = 94;     // Rechts 1 Melder - PIN A3

    int R2 = 93;     // Rechts 2 Melder - PIN A4

    int R3 = 92;     // Rechts 3 Melder - PIN A5

    

    //b: Weichen

    

    int WL2_G = 6;     // Weiche Links2 geradeaus - PIN 2

    int WL2_A = 7;     // Weiche Links2 abzweigend - PIN 3

    int WL3_G = 1;     // Weiche Links3 geradeaus - PIN 4

    int WL3_A = 5;     // Weiche Links3 abzweigend - PIN 5

    int WR2_G = 15;    // Weiche Rechts2 geradeaus - PIN 6

    int WR2_A = 16;    // Weiche Rechts2 abzweigend - PIN 7

    int WR3_G = 17;    // Weiche Rechts3 geradeaus - PIN 8

    int WR3_A = 18;    // Weiche Rechts3 abzweigend - PIN 9

    

    //c: Strom links

    

    int SL1H = 23;   // Strom Links1 High - PIN 10

    int SL1L = 24;   // Strom Links1 Low - PIN 11

    int SL2H = 25;   // Strom Links2 High - PIN 12

    int SL2L = 26;   // Strom Links2 Low - PIN 13

    int SL3H = 64;   // Strom Links3 High - PIN 14

    int SL3L = 63;   // Strom Links3 Low - PIN 15

    

    //d: Strom rechts

    

    int SR1H = 78;     // Strom Rechts1 High - PIN 22

    int SR1L = 77;     // Strom Rechts1 Low - PIN 23

    int SR2H = 76;     // Strom Rechts2 High - PIN 24

    int SR2L = 75;     // Strom Rechts2 Low - PIN 25

    int SR3H = 74;     // Strom Rechts3 High - PIN 26

    int SR3L = 73;     // Strom Rechts3 Low - PIN 27

    

    //e: Stromrichtung

    

    int SR_L = 59;     // Strom Fahrtrichtung Links - PIN 31

    int SR_R = 58;     // Strom Fahrtrichtung Rechts - PIN 32

    

    

    void setup() {             

      // Pins als OUTPUT oder INPUT definieren

    

      pinMode(L1, INPUT); pinMode(L2, INPUT); pinMode(L3, INPUT);

      pinMode(R1, INPUT); pinMode(R2, INPUT); pinMode(R3, INPUT);

      pinMode(WL2_G, OUTPUT); pinMode(WL2_A, OUTPUT);

      pinMode(WL3_G, OUTPUT); pinMode(WL3_A, OUTPUT);

      pinMode(WR2_G, OUTPUT); pinMode(WR2_A, OUTPUT);

      pinMode(WR3_G, OUTPUT); pinMode(WR3_A, OUTPUT);

      pinMode(SL1H, OUTPUT); pinMode(SL1L, OUTPUT);

      pinMode(SL2H, OUTPUT); pinMode(SL2L, OUTPUT);

      pinMode(SL3H, OUTPUT); pinMode(SL3L, OUTPUT);

      pinMode(SR_L, OUTPUT); pinMode(SR_R, OUTPUT);

    

    

    // Anfangszustand - wird nicht benötigt

    

    }

    

    void loop() {

    

    // von L3 -> R3

    if (L1 == HIGH && L2 == HIGH && L3 == HIGH && R1 == HIGH && R2 == HIGH && R3 == LOW) {

       digitalWrite(SR_L, LOW); digitalWrite(SR_R, HIGH);

       digitalWrite(WR3_G, LOW); digitalWrite(WR3_A, HIGH);

       digitalWrite(WL3_A, LOW); digitalWrite(WL3_G, HIGH);

       digitalWrite(SR3H, LOW); digitalWrite(SR3L, HIGH);

       digitalWrite(SL3L, LOW); digitalWrite(SL3H, HIGH);

      }

    

    // von L3 -> R2

    if (L1 == HIGH && L2 == HIGH && L3 == LOW && R1 == HIGH && R2 == HIGH && R3 == HIGH) {

       digitalWrite(SR_R, LOW); digitalWrite(SR_L, HIGH);

       digitalWrite(WR3_G, LOW); digitalWrite(WR3_A, HIGH);

       digitalWrite(WL3_A, LOW); digitalWrite(WL3_G, HIGH);

       digitalWrite(WR2_G, LOW); digitalWrite(WR3_A, HIGH);

       digitalWrite(SL3H, LOW); digitalWrite(SL3L, HIGH);

       digitalWrite(SR2L, LOW); digitalWrite(SR2H, HIGH);

      }

    

    // von L2 -> R2

    if (L1 == HIGH && L2 == HIGH && L3 == HIGH && R1 == HIGH && R2 == LOW && R3 == HIGH) {

       digitalWrite(SR_L, LOW); digitalWrite(SR_R, HIGH);

       digitalWrite(WR3_G, LOW); digitalWrite(WR3_A, HIGH);

       digitalWrite(WL3_G, LOW); digitalWrite(WL3_A, HIGH);

       digitalWrite(WR2_G, LOW); digitalWrite(WR2_A, HIGH);

       digitalWrite(WL2_G, LOW); digitalWrite(WL2_A, HIGH);

       digitalWrite(SL2L, LOW); digitalWrite(SL2H, HIGH);

       digitalWrite(SR2H, LOW); digitalWrite(SR2L, HIGH);

      }

    

    // von R1 -> L2

    if (L1 == HIGH && L2 == LOW && L3 == HIGH && R1 == HIGH && R2 == HIGH && R3 == HIGH) {

       digitalWrite(SR_R, LOW); digitalWrite(SR_L, HIGH);

       digitalWrite(WR3_G, LOW); digitalWrite(WR3_A, HIGH);

       digitalWrite(WL3_G, LOW); digitalWrite(WL3_A, HIGH);

       digitalWrite(WR2_A, LOW); digitalWrite(WR2_G, HIGH);

       digitalWrite(WL2_G, LOW); digitalWrite(WL2_A, HIGH);

       digitalWrite(SL2H, LOW); digitalWrite(SL2L, HIGH);

       digitalWrite(SR1L, LOW); digitalWrite(SR1H, HIGH);

      }

    

    // von L1 -> R1

    if (L1 == HIGH && L2 == HIGH && L3 == HIGH && R1 == LOW && R2 == HIGH && R3 == HIGH) {

       digitalWrite(SR_L, LOW); digitalWrite(SR_R, HIGH);

       digitalWrite(WR3_G, LOW); digitalWrite(WR3_A, HIGH);

       digitalWrite(WL3_G, LOW); digitalWrite(WL3_A, HIGH);

       digitalWrite(WR2_A, LOW); digitalWrite(WR2_G, HIGH);

       digitalWrite(WL2_A, LOW); digitalWrite(WL2_G, HIGH);

       digitalWrite(SR1H, LOW); digitalWrite(SR1L, HIGH);

       digitalWrite(SL1L, LOW); digitalWrite(SL1H, HIGH);

      }

    

    // von R3 -> L1

    if (L1 == LOW && L2 == HIGH && L3 == HIGH && R1 == HIGH && R2 == HIGH && R3 == HIGH) {

       digitalWrite(SR_R, LOW); digitalWrite(SR_L, HIGH);

       digitalWrite(WR3_A, LOW); digitalWrite(WR3_G, HIGH);

       digitalWrite(WL3_G, LOW); digitalWrite(WL3_A, HIGH);

       digitalWrite(WL2_A, LOW); digitalWrite(WL2_G, HIGH);

       digitalWrite(SL1H, LOW); digitalWrite(SL1L, HIGH);

       digitalWrite(SR3L, LOW); digitalWrite(SR3H, HIGH);

      }

 

}