Ampelsteuerung mit Arduino

W_87

Dieses ist das "kleine" Arduino® Uno Board. Anschluss 2 bis Anschluss 13 sind digitale Ausgänge, also entweder +5V oder 0V. Aber auch die Eingänge (Analog, A0 bis A5) können umdefiniert werden zu digitalen Ausgängen. Wenn ich nun eine Ampelkreuzung betreiben möchte, dann muss ich die verschiedenen Ampelphasen ja dadurch realisieren, dass ich - nach einem bestimmten Zeitablauf - die Ampellichter an- bzw. ausschalte. Insgesamt habe ich (mit umdefinierten Eingängen) 18 Ausgänge zur Verfügung - da jede Ampel drei Birnchen (LED's) hat macht das 6 Ampeln. Jeweils zwei sind für eine Kreuzung - also gegenläufig. Und damit nicht alle Kreuzungen, die das Board steuert, gleichzeitig das selbe Schaltbild zeigen, versetze ich das An- und Ausschalten um jeweils 1/3 der Gesamtphasendauer - das war zumindest die Idee. Das jedoch geht so einfach nicht:

w_91

Wie man sieht gehören A1 und A2 zusammen, ebenso A3 und A4 bzw. A5 und A6. Man muss die Zeitpunkte bestimmen, zu denen die Ampeln schalten sollen (und zwar für alle drei Ampelkreuzungen). Schaltzeitpunkt "12.000 Millisekunden" entspricht dem Schaltzeitpunkt "0 Millisekunden" - vom Schaltzeitpunkt davor muss man also noch 1000 Millisekunden = 1 Sekunde warten, ehe das Schaltspielchen von vorne losgeht. Nach jedem Schaltvorgang wartet man einfach genau so lange, bis der Zeitpunkt für den nächsten Schaltvorgang erreicht ist - so, wie ich das in dem nachfolgenden Programm für das Arduino (die Programme für Arduino heissen 'Sketch') gemacht habe:

// ***********************************
//
// Ampelsteuerung für Modellbahnampeln
//
// ***********************************

// Anschlüsse:

int A1R = 2; // Ampel 1 Rot - PIN 2
int A1Y = 3; // Ampel 1 Gelb - PIN 3
int A1G = 4; // Ampel 1 Grün - PIN 4
int A2R = 5; // Ampel 2 Rot - PIN 5
int A2Y = 6; // Ampel 2 Gelb - PIN 6
int A2G = 7; // Ampel 2 Grün - PIN 7
int A3R = 8; // Ampel 3 Rot - PIN 8
int A3Y = 9; // Ampel 3 Gelb - PIN 9
int A3G = 10; // Ampel 3 Grün - PIN 10
int A4R = 11; // Ampel 4 Rot - PIN 11
int A4Y = 12; // Ampel 4 Gelb - PIN 12
int A4G = 13; // Ampel 4 Grün - PIN 13
int A5R = 14; // Ampel 5 Rot - PIN A0
int A5Y = 15; // Ampel 5 Gelb - PIN A1
int A5G = 16; // Ampel 5 Grün - PIN A2
int A6R = 17; // Ampel 6 Rot - PIN A3
int A6Y = 18; // Ampel 6 Gelb - PIN A4
int A6G = 19; // Ampel 6 Grün - PIN A5

// Pins als OUTPUT definieren
void setup() {
pinMode(A1R, OUTPUT); pinMode(A1Y, OUTPUT); pinMode(A1G, OUTPUT);
pinMode(A2R, OUTPUT); pinMode(A2Y, OUTPUT); pinMode(A2G, OUTPUT);
pinMode(A3R, OUTPUT); pinMode(A3Y, OUTPUT); pinMode(A3G, OUTPUT);
pinMode(A4R, OUTPUT); pinMode(A4Y, OUTPUT); pinMode(A4G, OUTPUT);
pinMode(A5R, OUTPUT); pinMode(A5Y, OUTPUT); pinMode(A5G, OUTPUT);
pinMode(A6R, OUTPUT); pinMode(A6Y, OUTPUT); pinMode(A6G, OUTPUT);
//Ausschalten als Anfangszustand
digitalWrite(A1R, LOW); digitalWrite(A1Y, LOW); digitalWrite(A1G, LOW);
digitalWrite(A2R, LOW); digitalWrite(A2Y, LOW); digitalWrite(A2G, LOW);
digitalWrite(A3R, LOW); digitalWrite(A3Y, LOW); digitalWrite(A3G, LOW);
digitalWrite(A4R, LOW); digitalWrite(A4Y, LOW); digitalWrite(A4G, LOW);
digitalWrite(A5R, LOW); digitalWrite(A5Y, LOW); digitalWrite(A5G, LOW);
digitalWrite(A6R, LOW); digitalWrite(A6Y, LOW); digitalWrite(A6G, LOW);
}

// Ampelsequenzen steuern
void loop() {
digitalWrite(A1R, HIGH); digitalWrite(A1Y, HIGH); digitalWrite(A1G, LOW);
digitalWrite(A2R, LOW); digitalWrite(A2Y, HIGH); digitalWrite(A2G, LOW);
digitalWrite(A5R, HIGH); digitalWrite(A5Y, LOW); digitalWrite(A5G, LOW);
digitalWrite(A6R, LOW); digitalWrite(A6Y, LOW); digitalWrite(A6G, HIGH);
delay(1500);
digitalWrite(A1R, LOW); digitalWrite(A1Y, LOW); digitalWrite(A1G, HIGH);
digitalWrite(A2R, HIGH); digitalWrite(A2Y, LOW); digitalWrite(A2G, LOW);
delay(2000);
digitalWrite(A3R, HIGH); digitalWrite(A3Y, HIGH); digitalWrite(A3G, LOW);
digitalWrite(A4R, LOW); digitalWrite(A4Y, HIGH); digitalWrite(A4G, LOW);
delay(1500);
digitalWrite(A3R, LOW); digitalWrite(A3Y, LOW); digitalWrite(A3G, HIGH);
digitalWrite(A4R, HIGH); digitalWrite(A4Y, LOW); digitalWrite(A4G, LOW);
delay(2000);
digitalWrite(A5R, HIGH); digitalWrite(A5Y, HIGH); digitalWrite(A5G, LOW);
digitalWrite(A6R, LOW); digitalWrite(A6Y, HIGH); digitalWrite(A6G, LOW);
delay(1500);
digitalWrite(A1R, LOW); digitalWrite(A1Y, HIGH); digitalWrite(A1G, LOW);
digitalWrite(A2R, HIGH); digitalWrite(A2Y, HIGH); digitalWrite(A2G, LOW);
digitalWrite(A5R, LOW); digitalWrite(A5Y, LOW); digitalWrite(A5G, HIGH);
digitalWrite(A6R, HIGH); digitalWrite(A6Y, LOW); digitalWrite(A6G, LOW);
delay(1500);
digitalWrite(A1R, HIGH); digitalWrite(A1Y, LOW); digitalWrite(A1G, LOW);
digitalWrite(A2R, LOW); digitalWrite(A2Y, LOW); digitalWrite(A2G, HIGH);
delay(2000);
digitalWrite(A3R, LOW); digitalWrite(A3Y, HIGH); digitalWrite(A3G, LOW);
digitalWrite(A4R, HIGH); digitalWrite(A4Y, HIGH); digitalWrite(A4G, LOW);
delay(1500);
digitalWrite(A3R, HIGH); digitalWrite(A3Y, LOW); digitalWrite(A3G, LOW);
digitalWrite(A4R, LOW); digitalWrite(A4Y, LOW); digitalWrite(A4G, HIGH);
delay(2000);
digitalWrite(A5R, LOW); digitalWrite(A5Y, HIGH); digitalWrite(A5G, LOW);
digitalWrite(A6R, HIGH); digitalWrite(A6Y, HIGH); digitalWrite(A6G, LOW);
delay(1500);
}

(Anmerkung: Die Ampelphasen für 'Rot' und 'Grün' einer jeden Kreuzung betragen 6 Sekunden (delay(2000)), die für die 'Rot-Gelb'- bzw. 'Gelb'-Phasen jeweils 1,5 Sekunden(delay(1500)). Möchte man längere oder kürzere Ampelphasen, muss man alle (!) gleichen Delays ändern. Beispiel: Die Phase "Rot/Grün" soll 9 Sekunden betragen und die Phase "Rot-Gelb/Gelb" 2 Sekunden. Delay für "Rot/Grün" ist dann 9000 ms : 3 = 3000, delay für "Rot-Gelb/Gelb" = 2000. Trotz dieser einfachen Auswechselei der delays empfehle ich einen Ablauftable zu erstellen - wird die Gelbphase nämlich länger als 1/3 der "Rot/Grün"-Phase funktioniert das so nicht mehr.)

Das Programm, mit dem man das Arduino programmiert (also z.B. die Ampelsteuerung auf das Board lädt) gibt es kostenlos bei Arduino.cc. Auch den Treiber für die verschiedensten Betriebssysteme kann man dort kostenlos herunterladen.

Wer sich schon mal mit Programmierung eines Arduino oder mit der Programmiersprache 'C' beschäftigt hat wird sehr schnell verstehen, was da passiert. Für den Rest in aller Kürze:

1. Zu Anfang definiere ich einige Variablen für die Pinnummern des Boards, damit ich nicht die Pinnummern verwenden muss und nicht durcheinanderkomme. 'A1' steht dabei für 'Ampel 1' und 'R' für 'Red', 'Y' für 'Yellow' und 'G' für 'Green'.

2. Danach kommt ein Abschnitt, der 'void setup' heisst. Hier wird zunächst festgelegt, welche Pins des Arduino Ausgänge (OUTPUT) sind und dann der Anfangszustand der Ausgänge festgelegt (LOW, also aus) - 'void setup' wird einmal durchlaufen, wenn das Board Strom erhält.

3. Der nachfolgende 'void loop' ist eine Schleife, die fortwährend durchlaufen wird. Wenn der letzte Befehl dort abgearbeitet wurde geht 'void loop' von vorne los. Und wieder. Und wieder. Und... ;)

Man "schreibt" also digital den Zustand '+5V' an den entsprechenden Pin und wartet danach einfach eine Zeit in Millisekunden ab (delay = Verzögerung). Einmal mit einem solchen Sketch programmiert, führt das Arduino diesen aus, sobald es Strom erhält. ein kleines 12V-Netzteil für 5,95 Euro (z.B. CONRAD) reicht vollkommen aus - das Arduino verträgt angeblich Eingangsspannungen von 6 bis 20 V Gleichstrom.

Wie das Ganze dann auf einer Experimentierplatine aussieht kann man hier sehen (unten Ampeln 1 & 2, oben Ampeln 3 & 4 - Ampeln 5 & 6 noch nicht angeschlossen - Vorwiderstände 560 ΩO):

w_88

...zum Ausprobieren ist so eine Experimentierplatine eine prima Sache, auch wenn das Zubehör dafür nicht ganz billig ist. So kann man die Funktion sehr schön testen, ehe man das Board einbaut oder auch weitergehende Schaltungen auf eine Platine lötet... :)

So sieht dann nach der Programmierung des Arduino der Anschluss aus:

w_89

Die Steuerung übernimmt nun drei "unabhängig" voneinander geschaltete Ampelkreuzungen. Da das Board aber einen Strom von bis zu ~40 mA pro Pin Stromaufnahme der angeschlossenen Verbaucher aushält, können - je nach Ampeln - auch zwei Kreuzungen parallel betrieben werden. Nicht vergessen, dass dann eine Ampel nur 10mA aufnehmen darf ;) Im Test hat das Board mit 3mm-LED's sogar sechs (6) Ampelkreuzungen je Schaltkreuzung (A, B, C) geschafft - so weit ich weiss, sind in Modellampeln wesentlich kleinere LED's verbaut, so dass die Stromaufnahme auch dort bei jeweils 6 angeschlossenen Ampeln völlig i.O. ist. Als Vorwiderstand waren die LED mit 1kΩO relativ schwach, mit 560ΩO etwas heller. Insgesamt gesehen belaufen sich die Kosten für eine Ampelsteuerung für bis zu 18 Kreuzungen somit auf 29,95 Euro für das Arduino und 5,95 Euro für das Netzteil, also 35,90 Euro insgesamt. Geht doch, oder?

Nachtrag: Ich habe das ganze nun mal an die Busch-Ampeln in Spur N angeschlossen - und ersteinmal tat sich gar nix. Wie sich herausstellte, haben die Ampeln von Busch (zumindest die N-Ampeln) einen gemeinsamen +Pol und schalten über Masse, so dass die ganze Schaltung 'verpolt' war. Das Arduino bietet aber auch einen +5V-Anschluss, so dass ich diesen benutzt habe. Das Schaltbild war dann allerdings gegensätzlich zu dem, was ich erreichen wollte - statt 'Rot' brannte 'Gelb-Grün'. Logisch, wenn immer dann geschaltet wird, wenn der Sketch den Pin auf 'LOW' setzt... Also habe ich den Sketch umgeschrieben für die Busch-Ampeln - überall 'HIGH' durch 'LOW' ersetzt und 'LOW' durch 'HIGH'. Nun müsste es auch für diese Ampeln funktionieren - gleicher Anschluss wie sonst auch, aber der graue Draht der Ampeln kommt nicht auf Masse sondern auf den PIN '+5V'. Den Sketch für die Busch-Ampel-Ansteuerung findet Ihr hier: Ampelsteuerung_Masse.zip (Ausprobiert und funktioniert!)

Was mir aber auffiel: Eine Ampel 'frisst' bei den angegebenen 2V Betriebsspannung locker bis zu 17 mA (gemessen) wenn zwei LED gleichzeitig brennen - da alles in einer solchen Schaltung über einen Pin läuft würde das die Verwendung auf max. 2 Ampeln (und damit nur 1 Kreuzung) einschränken. Aber die LED's waren mir ohnehin viel zu hell. Ein Vorwiderstand von 2,2kΩO frisst genug Strom weg, dass die LED's vernünftig hell - aber nicht zu hell - brennen, und das man so auch mit den Busch-Ampeln immerhin drei Kreuzungen mit jeweils 4 Ampeln am Arduino betreiben kann. Zur Zeit warte ich noch auf ein paar Darlington-Arrays per DHL, um damit mehr Kreuzungen schalten zu können. Auch die Idee, eine Kreuzung ggf. gegenläufig anschalten zu können, spukt noch in meinem Kopf herum - was dann 6 'unabhängige' Schaltbilder bei nahezu beliebig vielen Ampeln ermöglichen würde.

Zwischenzeitlich habe ich mich mal mit dem Darlington-Array ULN 2803 beschäftigt. Dieser kleine IC-Baustein schaltet, wenn der Eingang bis zu +5V erhält, den Ausgang frei - aber gegen Masse. Das bedeutet, dass dort auch z.B. die Busch-Ampeln angeschlossen werden könnten. Da ich das Päckchen noch nicht abgeholt habe, ist die folgende Schaltung erst einmal nur theoretisch:

w_94

Das ARDUINO schaltet mit den Ausgängen 2 bis 7 auf sechs Eingänge des ULN 2803. Liegt dort jeweils ein HIGH an (also +5V), dann schaltet der 2803 auf Masse durch. Bedeutet: Die Ampeln bekommen ein gemeinsames '+' in Höhe von ungefähr 14V (Gleichstrom! Deshalb der Gleichrichter!) am grauen Draht und die roten/gelben/grünen Drähte werden mit dem Ausgang des 2803 verbunden. Der Vorwiderstand muss nun wesentlich mehr Strom 'verbraten' als bei 5V - als Vorwiderstand kommen nun 6,8kΩO in Frage. Bei diesem Vorwiderstand sinkt die Stromstärke des Verbrauchs in den LED's auf 1,7 mA ab, unser 2803 verträgt bis zu 500 mA. Also: 14 gleichzeitig Leuchtende LED pro Kreuzung à 1,7 mA = 23,8 mA pro Kreuzung. Theoretisch sollten also 21 Kreuzungen pro ULN 2803 möglich sein... keine Gewähr! ;)

Versuchsanordnung mit 10kΩ-Vorwiderständen - es funktioniert :)

w_95

Die drei ULN 2803 Darlington-Arrays sowie der kleine Gleichrichter B40D,
der den Trafostrom (14V~) eines alten Minitrix-Trafos in Gleichstrom verwandelt

w_96

Das Schaltbild des ULN 2803 Darlington-Arrays

Das Durchschalten gegen Masse funktioniert mit den Darlington-Arrays sehr gut. Nicht vergessen, die Masse (GND) des ARDUINO-Boards und die Masse (GND) der ULN 2803 zusammenzulegen...

Und so sieht das ganze dann mit den Modellampeln aus:

w_100

Und wer immer noch nicht glaubt, wie viele Ampeln man damit gleichzeitig steuern kann:

w_105

Hinweis: Wir haften nicht für Schäden, die durch die Anwendung eines Sketches oder einer Schaltung von dieser Seite entstehen. Auch können Tippfehler auftreten, sich Fehler einschleichen usw. - jeder ist für das, was er mit den Tipps auf dieser Seite anstellt, selbst verantwortlich. Nur mal so am Rande :)