|
Schrankensteuerung am Modellbahnübergang mittles MikrocontrollerWie kam es zu dem Projekt ?Ich baue an einer Spur N-Anlage, die ich sehr kompakt ausgelegt habe, damit sie in die Dachboden-Abseite passt. Die Hauptstrecke ist ein zweigleisiger Ring mit einer Länge von (nur) ca. 4,50 m. Ein Zug braucht da gerade mal 20 s, um einmal rumzufahren.Es sollte nun auch ein beschrankter, automatisch betriebener Bahnübergang an die Hauptstrecke. Dazu hatte ich mir einen Faller-Bausatz 222170 für einen Bahnübergang mit elektrischem Schrankenantrieb besorgt. Bei diesem Antrieb erfolgt die Bewegung zum Senken und Heben der Schranken über eine Exzenterscheibe (unterer Totpunkt: Schranken zu, oberer Totpunkt: Schranken offen). Der Getriebe-Synchronmotor, der die Scheibe dreht, kann nur in eine Richtung laufen. Zum Anhalten in der jeweiligen Endstellung, wird ein Kontakt am unteren bzw. oberen Totpunkt über entsprechende Nocken (angegossene Stifte auf der Exzenterscheibe) geöffnet. Wieso nicht so wie vom Hersteller gedacht?Der Schaltplan in der Anleitung sieht Kontaktgleise bzw. Reedkontakte und Relais zur Steuerung vor. Entsprechend der langsamen Drehbewegung der Scheibe ist eine Vorlaufzeit von 8 s für die Meldung eines ankommenden Zuges angegeben. Dies bedeutet einen Abstand der Kontakte vor der Schranke von ca. 1,80 m. Ich musste feststellen, dass das auf meiner kleinen Anlage keinen Sinn machen würde. Der Antrieb musste also irgendwie schneller und die Steuerung möglichst effektiv werden. Dazu waren mir die Möglichkeiten der Elektromechanik zu eingeschränkt und die entsprechenden Komponenten auch zu teuer.Und überhaupt wollte ich für dem Einbau von Kontaktgleisen oder Reedkontakten nicht die bereits fest verlegten und eingeschotterten Schienen wieder rausreissen. Aber wie dann ?Wenn es darum geht, eine Steuerung zu realisieren, die flexibel alle Funktionen abdeckt, setzt man heutzutage natürlich einen Microcontroller ein. Wie auch bei anderen Projekten, habe ich das Board Pro Mini (Arduino bzw. kompatible) in der 5V/16MHz-Ausführung genommen. Hier gibt's Näheres zum Einsatz dieser Technik..Beim Grübeln, wie sich die Zug-Detektion preiswert, dezent und gleisschonend machen ließe, ist mir eine Lösung mit induktiven Sensoren eingefallen, die sich sehr gut und quasi nebenbei mit mit dem Prozessor auswerten lassen. Ich beschreibe das ausführlich auf meiner Seite "Näherungssensor". Wichtiger Hinweis dazu: Im Gegensatz zu Reed-Kontakten oder Hall-Sensoren braucht dieser Sensor keine Magneten am rollenden Material. Ein bisschen Metall ist auch einfachen Waggons dran. Das genügt. Sensoren braucht's in jeder Fahrtrichtung, und zwar:
Ein Sensor besteht aus einer zylindrischen Induktivität mit einem Duchmesser von ca. 6 mm. Er kann in eine entsprechende Bohrung im Gleis eingeklebt werden.
Die Bilder zeigen übrigens einen der beiden Sensoren für ankommende Züge im Bahnhofsbereich. Kann man den Antrieb schneller machen ?Da schaut's auf den ersten Blick schlecht aus. Der Synchronmotor läuft halt nun mal so schnell, wie es die 50 Hz aus dem Trafo vorgeben,oder?Aber nein, wir haben doch den Controller! Der kann jede Frequenz erzeugen, wenn auch der Einfachheit halber nur als Rechteck. Eine H-Brücke hinten dran, die ausreichend Strom treiben kann und schon hat man zwei Fliegen mit einer Klappe geschlagen: Ein-/Ausschalten des Motors und Geschwindigkeits-Boost. O.k., jetzt erst mal der SchaltplanDie Stromversorgung der Schaltung erfolgt über den Stiftverbinder J0. Die gleichgerichtete und gesiebte Spannung aus einem üblichen Eisenbahntrafo kann verwendet werden. Die 5 V Für die Versorung des Microcontrollers (VCC ) werden mit einem 7805-Spannungsregler eingestellt. Für den Motor, d.h. für die Betriebsspannung der Leistungs-OPs, mit denen die H-Brücke realisiert ist, wird die Eingangsspannung direkt weitergeführt. Mit C1 (4,7 μF, 35V) erfolgt eine lokale Glättung dieser Spannung. An die Analog-Eingänge A0...A5 des Controllers werden über die Stiftverbinder J1...J6 die induktiven Sensoren angeschlossen. Bei den Pro Mini-kompatiblen Boards sind meist auch noch die Analog-Pins A6 und A7 herausgeführt, so dass an A6 ein weiterer Sensor angeschlossen werden kann. Mehr geht aber nicht, da A7 nur als Eingang verwendbar ist. Die Controller-Pins D2 und D3 werden als Ausgänge zur Ansteuerung der Leistungs-OPs des L272-Bausteins verwendet. Die Signale gehen an die invertierenden Eingänge. Für die nicht-invertierenden Eingänge der beiden OPs wird mit dem Spannungsteiler R9/R10 eine Referenz erzeugt, die zwischen den Logikpegeln des Microcontrollers liegt. Da die OPs ohne Gegenkopplung betrieben werden, werden ihre Ausgänge, entsprechend der anliegenden Logikpegel entweder voll auf Masse oder voll auf die Versorgungsspannung gezogen. Bei komplementärer Ansteuerung der Controller-Ausgänge D2, D3 ergibt sich am Motor eine rechteckige Wechselspannung, die nahezu die gleiche Amplidude wie die ursprüngliche Spannung aus dem Trafo hat, nur dass die Frequenz nun variabel ist. D1...D4 sind Freilaufdioden, die gebraucht werden, um Spannungsspitzen beim Umschalten zu unterdrücken. Gewöhnliche Gleichrichterdioden, z.B. 1N4004, tun es hier. Der Dritte, etwas abgesetzte, Pin J10 wird mit dem oben erwähnten Nocken-Kontakt der Mechanik verbunden. Dieses Bild zeigt den Stecker an J9/J10, wie ich ihn realisiert habe. D.h. verdrehsicher durch die Lücke, die durch einen Batzen Schmelzkleber verfüllt ist. Hier sieht man die Farbbelegung der Anschlussleitungen. Bei dem verwendeten Faller-Bausatz sind gelb und grün die Motoranschlüsse. Der Nocken-Kontakt liegt zwischen dem grünen und dem blauen Draht. Die meiste Zeit ist also das Potential auf grün und blau identisch. Nur wenn der Kontakt offen ist, ist blau hochohmig. Die Unterbrechung am oberen Totpunkt wird für den zyklischen Reset der inkrementellen Positionsbestimmung benutzt. Die untere Nocke, d.h. dieser angegossene Stift auf der Exzenterscheibe, muss leider abgeschnitten werden, um Eindeutigkeit zu garantieren.. Um festzustellen, ob der Nocken-Kontakt geschlossen oder geöffnet ist, muss der Microcontroller prüfen, ob dieser Motorspannung führt oder hochohmig ist. Die Kombination R11, R12, D5 setzt dafür die Motorspannung auf Logikpegel um bzw. liefert 0 V an den Eingang D8, wenn der Kontakt offen ist. Zu guter Letzt wäre da noch die Ansteuerung eventueller Lichter zu erwähnen. Ich habe mir Andreaskreuze mit Blinklichtern, also mit kleinen roten LEDs, dazugekauft. Auch die, vielleicht authentischeren, gelb/roten Lichtsignale (Ampeln) sind denkbar. Der Anschluss der Lichter erfolgt über J8. Die Controller-Ausgänge D4 und D5 treiben über die Vorwiderstände R13 und R14 die entsprechenden Leuchtdioden getrennt nach linker und rechter Straßenseite bzw. nach gelbem und grünem Licht. Die im Schaltplan angegebenen Vorwiderstände sind für je eine LED ausgelegt, die damit ca. 3 mA erhält. Habt Ihr mehrere Lichter zu treiben, weil Ihr z.B. beide Seiten des Übergangs bestückt habt, so müsst Ihr weitere Verbinder mit eigenen Vorwiderständen hinzufügen. Was muss die Controller-Software also alles machen?Der Microcontroller muss dazu folgende Aufgaben erledigen:
Den kompletten Arduino-Sketch dazu könnt Ihr hier runterladen. Der Sketch gliedert sich in Deklarationen, Initialisierung (setup()), Hauptprogramm (loop()) und Interrupt-Routinen für Timer 2 (ISR(TIMER2_COMPA_vect, ...) und den Komparator ISR(ANALOG_COMP_vect)). Im Hauptprogramm passieren die Steuerentscheidungen, d.h. die Aufgaben 2) und 3). In der Timer-Interrupt-Routine wird alles gemacht was sauber zyklisch ablaufen soll, nämlich die Signalerfassung und -verarbeitung, die Motoransteuerung mit Abfrage des Nocken-Kontakts und das Blinken der Lichter. Im Folgenden erläutere ich jeweils auszugweise die Code-Schnipsel mit denen die oben beschriebenen Aufgaben erledigt werden. Der Rest sollte sich von selbst erklären.
1) Betrieb der Sensoren und Signalverarbeitung:
Der Code beginnt mit dem Umspeichern des alten Messwertes measurement[] nach m_smooth. Der neue Messwert (in comparator_count) wird, nachdem er nach oben auf den maximal möglichen Zählwert ZERO_MEASUREMENT begrenzt wurde, dazu addiert. Anschließend wird um eins nach rechts geschiftet, also durch zwei geteilt. In m_smooth steht also dann der Mittelwert aus dem bisherigen Messwert und dem neuesten Zählwert. Das beseitigt schon mal einen Gutteil eventuellen Bit-Klapperns (häufiges Hin- und Herspringen um eine Stufe). Die Begrenzung des aktuell hinzu addierten Wertes unterdrückt Ausreisser, die durch Störeinstreuungen, z.B. durch kurzzeitige Unterbrechungen beim Scheine-Lokomotiv-Kontakt, auftreten können. Anschließend wird measurement_delta[], d.h. ein Wert für die Betragsänderungen von m_smooth, gebildet. Eine mit einer Zeitkonstante von ca. 0,6 s verzögerte Anpassung (ein 1/64 pro 10 ms Zeitschritt) an die momentanten Änderungen sorgt dafür, dass die Lücken zwischen den Achsen überbrückt werden und measurement_delta[] somit als verlässlicher Indikator für Zugbewegungen verwendet werden kann. Die Multiplikation mit 256 (Shift um 8 nach links) bei der Speicherung ist aus Gründen der numerischen Genauigkeit nötig. Die bool'sche Variable motion_detected[], die im Hauptprogramm letztendlich zum Einsatz kommt, wird unter Berücksichtigung der Schwelle MOTION_DETECTION_THRESHOLD gebildet. Je niedriger diese Schwelle gesetzt wird, desto später fällt das motion_detected-Flag ab, nachdem sich am Sensor nichts mehr rührt. Ein zeitlicher Nachlauf dieser Variablen, der im Hauptprogramm ebenfalls gebraucht wird, wird mit time_extension[] realisiert. SIGNAL_HOLD habe ich in meiner Implementierung auf 600 gesetzt, d.h. time_extension[] geht 6 s nach der abfallenden Flanke von motion_detected[] auf Null. Es ist die maximal angenommene Zeit zwischen Annäherung und Durchfahrt. 2) Feststellung des Zugverkehrs-Status:Diese Aufgabe wird asynchron zur Messwerterfassung in der Endlosschleife des Hauptprogramms ca. alle 0,1 s ausgeführt. Auf der Basis der oben beschriebenen Indikatoren (von den Sensoren beider Fahrtrichtungen) und der vorherigen Situation muss festgestellt werden, ob gerade (mindestens) ein Zug in Anfahrt ist, der Zug (die Züge) bereits durchgefahren ist (sind) oder ob gerade gar kein Verkehr zu beachten ist. Das klingt einfach, kann aber bei zwei Fahrtrichtungen bereits unübersichtlich werden. Da die bisherige Situation (Zustand) eine Rolle spielt, bietet sich die Programmierung mit Zustandsautomaten an. Das sind die beiden switch-Befehle für je eine Fahrtrichtung mit den Zustandsvariablen train_on_inner_ring und train_on_outer_ring:
Diese Zustandsvariablen können die Werte:
Die Zustände der einzelnen Fahrtrichtungen werden letztendlich zu den Flags some_train_approaching (mindestens ein Zug ist in Anfahrt) und some_train_leaving (mindestens ein Zug ist dabei den Übergang zu passieren) verknüpft. 3) Entscheidung über Schrankenbewegung:Ein weiterer switch-Befehl (Zustandsautomat) mit dem Argument state_of_gate entscheidet auf Basis der o.g. Flags und der aktuellen Position motor_position , ob der Antriebsmotor laufen soll und, wenn ja, wie schnell:
Die Zustandsvariable state_of_gate kann die Werte:
motor_position wird durch Mitzählen bei der Erzeugung der Motor-Wechselspannung ermittelt (siehe weiter unten). Das Argument des Untergrogramms Motor_On() gibt an, um wieviel höher die Motorspeisung über den 50 Hz liegen soll. NORMAL_BOOST ergibt 80 Hz. Bei MAX_BOOST werden 114 Hz erzeugt, der Motor läuft also mehr als doppelt so schnell! Viel höher geht es aber nicht, da bei zu hoher Frequenz der Motor nicht mehr mitmacht, also stehen bleibt. Was und wann unter welchen Bedingungen gemacht wird, ist im Code zu sehen. Speziell im Zustand OPENING gibt es mehrere wenn-dann-Entscheidungen. Das liegt an folgenden Situationen, die vor allem bei kompakten Anlagen, d.h. bei kurzen Annäherungs- und Öffnungsverzögerungszeiten, auftreten: Sind die Schranken nämlich gerade wieder am Aufgehen und es kommt just ein Zug auf dem Gegengleis, dann muss die Mechanik zunächst über den oberen Totpunkt (komplett offen) laufen, um dann erst wieder schließen zu können. Das muss möglichst schnell gehen, um zu vermeiden, dass bei Durchfahrt dieses Gegenzuges die Schranken noch offen sind. Dafür kommt MAX_BOOST bei einem direkt eingeleiteten Schließvorgang zum Einsatz. Sind die Schranken bei Annäherung des Gegenzuges aber erst gerinfügig geöffnet, wird der Antrieb lediglich vorübergehend angehalten. Strebt man eine kurze Verzögerungszeit für das Wiederöffnen der Schranke an, kommt es bei langsamen Zügen mit langen Waggons vor, dass das motion_detected-Flag zwischen den Drehgestellen der Waggons, zeitweise schon wieder abfällt und somit kurzzeitig von einer erfolgten Durchfahrt des Zuges ausgegangen wird. Die Schranken sind dann bereits ein Stück offen, wenn weitere Radsätze vorbeikommen, also erkannt wird, dass der Zug doch noch nicht durch ist. In dem Fall bleibt die Logik zwar weiterhin bei OPENING, der Antrieb wird aber vorübergehend angehalten. Am Ende der Öffnungsphase werden die Schranken in eine Bereitschaftsposition gefahren, die ein Stück (EXTRA_MOVEMENT) über dem Totpunkt liegt. Der nächste Schließvorgang kann damit schneller erfolgen.4) Erzeugung der Motor-Wechselspannung und Abfrage des Nocken-Kontakts:
Die gezeigte Codesequenz wird, wie auch die gesamte Interrupt-Routine, mit 3,2 kHZ aufgerufen. Über den Zähler chopping_count und den Vergleich mit THE_100HZ_INTERVAL-chopping_boost erfolgt ein Herunterteilen auf eine Rate von 100 Hz plus X (konkret verwendete Werte siehe oben). Entsprechend dem Flag motor_on, das vom Hauptprogramm gesetzt wird, werden die beiden Motorausgänge D2/D3 alternierend geschaltet oder zu Null gesetzt. Nebenbei wird motor_position mitgezählt. Der aktuelle Stand des Antriebes, ausgehend vom Reset am oberen Totpunkt, ist damit exakt bestimmt. chopping_boost wird bei Motorstart vom Hauptprogramm zunächst auf Null gesetzt und hier langsam auf max_boost hochgezählt. Die Abfrage des Nocken-Kontakts (Pin B0) erfolgt vor dem Schalten der Motorpins. Wenn festgestellt wird, dass B0 nicht auf high steht, obwohl D3 low ist (der zugehörige Motorpin ist über die Negierung des Verstärkers dann high), wird der Reset von motor_position durchgeführt. 5) Blinken der Warnlichter:
Auch dieser Teil wird 3200 mal pro Sekunde aufgerufen. Hier wird mit dem Zähler und dem Vergleichswert FLASHING_INTERVAL heruntergeteilt. Mir einem Wert von 4000 für FLASHING_INTERVAL ist ein Blinkzyklus, bei dem die halbe Zeit D5 und die andere Zeit D6 high ist, etwas über eine Sekunde lang. Ob überhaupt geblinkt wird, wird mit flashing_on aus dem Hauptprogramm gesteuert. Fällt flashing_on auf false, so wird der aktuelle Blinkzyklus noch zu Ende gebracht. Für die Testphase: Definiert man den Compiler-Switch TEST, so werden die Lichter zur Anzeige der Steuerungszustände verwendet. Das Ganze auf LochstreifenplatteUm diese Anleitung abzurunden, habe ich keine Mühe gescheut und die Schaltung in fritzing auf Lochstreifenplatte entworfen. Ihr könnt die entsprechende fritzing-Datei hier herunterladen. Die Leiterplattenansicht braucht Ihr nicht zu beachten. Ich habe da nur mal das Auto-Routing drüber laufen lassen.Für den Nachbau genügt es aber eigentlich, wenn Ihr Euch die fogenden Bilder runterholt (mit der linken Maustaste groß anzeigen lassen, dann mit der rechten Maustaste draufgehen und "Grafik kopieren" wählen): Hier sieht man die Lochstreifenplatte mit den Bauteilen. Die orangenen Drahtbrücken sind am besten mit Kupferlackdraht zu machen. Mit ihnen wird das Microcontroller-Board angeschlossen. Sie müssen nicht genau so gelegt werden, wie es gezeichnet ist. Man lötet sie von oben am Microcontroller-Board an, führt sie durch ein passendes Loch auf die Unterseite und lötet sie dort an.
Die grau abgebildeten Drahtbrücken könnt Ihr mit blankem Draht machen. Bei schwarz und rot braucht Ihr isolierten Draht. Ich hoffe, Ihr könnt mit dieser Anleitung etwas anfangen. Viel Erfolg ! Und hier die automatische Schranke im Betrieb:In schneller Abfolge rauschen die Züge von beiden Seiten durch. Die Annäherungs-Sensoren befinden sich auf der Anlage ungefähr da, wo im Video der linke bzw. rechte Bildrand ist. Das Gebrumme, das zu hören ist, ist die, über Lautsprecher hörbar gemachte, Motor-Wechselspannung. Man hört die oben erwähnten Frequenzen, inklusive Hochlaufen aus 50 Hz. Das normale Schließen und Öffnen erfolgt mit 80 Hz. Nach dem oberen Totpunkt bis zum Erreichen der Bereitschaftsposition wird noch kurz auf die schnellere Frequenz, also 114 Hz hochgeschaltet. Im Video sieht man auch folgende spezielle Situationen:
Wollt Ihr einen Kommentar loswerden oder habt Ihr eine Frage? Schickt mir eine Mail |