Die Planung der Gleisanlage umfasst auch die Weichen und deren Steuerung. Für die Planung meiner kleinen Anlage habe ich zunächst einen Gleisplan mit dem Traxeditor erstellt. In diesem Programm kann man das gewünschte Gleissystem auswählen – in meinem Fall das Piko A-Gleis ohne Bettung (siehe diesen Post) – und sicherstellen, dass beim Zusammenbau alles korrekt zusammenpasst.
Der Antrieb
Die Weichen lassen sich ab Werk zunächst nur manuell umstellen. Das ist wenig sinnvoll, insbesondere da auch im hinteren Bereich der Anlage Weichen verbaut sind. Daher ist ein elektrischer Weichenantrieb erforderlich, der die Weichenzunge automatisch bewegen kann. Grundsätzlich gibt es zwei Methoden, diesen Antrieb zu installieren: Entweder wird der Weichenantrieb je nach Hersteller direkt auf der Oberfläche an der Weiche befestigt, oder man bohrt unter der Weiche ein Loch und verwendet einen Unterflurantrieb mit Schubstange.
Unterflur | Oberflur |
---|---|
– Platzsparend – Unauffällig – Flexibler – z.T. universal für mehrere Hersteller | – Einfache Installation – Leichte Wartung – einfachere Verkabelung |
– Komplexere Montage – Eingeschränkter Zugriff – Anfälligkeit | – Optik – Platzbedarf – laut – meist Herstellergebunden |
Die Steuerung
Die Steuerung von Weichen ist ein komplexes und vielseitiges Thema, das zahlreiche Möglichkeiten bietet. Klassische Oberflurantriebe, wie sie beispielsweise von Piko angeboten werden, lassen sich mit einem herkömmlichen analogen Stellpult schalten. Unterflurantriebe hingegen benötigen häufig Wechselstrom. Sofern Gleichstrom möglich ist, muss dieser i.d.R. je nach gewünschter Schaltstellung (rechts/links) eine unterschiedliche Polarität aufweisen.
Eine moderne Lösung hierfür sind sogenannte Weichendecoder. Diese praktischen Geräte übernehmen die Steuerung der Weichen und ermöglichen das Schalten über digitale Protokolle, wie etwa das DCC-Protokoll, in Verbindung mit einem passenden Controller. Der große Vorteil dieser Methode liegt darin, dass sowohl die Weichen als auch die Lokomotiven mit demselben Steuergerät bedient werden können, was die Handhabung deutlich vereinfacht und zentralisiert.
Weichensteuerung mit Arduino
Da mein DCC-Controller leider keine Weichensteuerung unterstützt und ich viele Arduinos und Bauteile zur Verfügung habe, habe ich beschlossen, das Problem selbst zu lösen. Zudem wollte ich eine grafische Oberfläche erstellen, mit der ich sowohl die Weichen als auch andere Funktionen auf der Anlage, wie Lichtabschnitte, steuern kann. Hierfür bot sich eine Kombination aus Processing 4 (zur grafischen Oberfläche auf dem PC) und einem Arduino Mega an.
Als Weichenantrieb habe ich mich für den günstigen Unterflurantrieb von Conrad mit Endabschaltung entschieden, da ich ein großes Konvolut günstig auf eBay erwerben konnte. Unterflurantriebe empfinde ich generell als realistischer. Die integrierte Endabschaltung schaltet den Antrieb automatisch ab, sobald die jeweilige Endposition (ganz rechts oder ganz links) erreicht ist. Dadurch entfällt die Notwendigkeit, die Dauer des Stromflusses präzise zu steuern.
Die Schaltung der Antriebe erfolgt normalerweise mit Wechselstrom. Da ich jedoch mit Gleichstrom arbeiten wollte, benötige ich für jede Weiche zwei Relais, die jeweils als Doppelmodul verfügbar sind. Aus diesen Relais habe ich eine sogenannte H-Brücke aufgebaut. Auch bei Gleichstromantrieben sind zwei Relais notwendig. Man muss schließlich einen Schaltimpuls für zwei mögliche Signaleingänge erzeugen können. Statt den Relais könnte man z.B. auch Mosfets nutzen
Die H-Brücke ist eine Schaltung, die es ermöglicht, die Polarität einer Gleichstromquelle umzudrehen, um den Stromfluss in beide Richtungen zu steuern. Sie besteht aus vier Schaltelementen, die in einer H-förmigen Anordnung verschaltet sind. In meinem Fall übernehmen zwei Relais diese Funktion: Schaltet das erste Relais, ergibt sich die Polarität + und – am Antrieb, während das zweite Relais die Polarität auf – und + umkehrt. So kann der Conrad-Unterflurantrieb die Weichenzunge zwischen den beiden Endpositionen hin- und herbewegen.
Zwei Dioden sind ab Werk bereits am Weichenantrieb angebracht, wodurch die richtige Stromflussrichtung sichergestellt wird. Meine Schaltung ist also in Wirklichkeit nur eine halbe H-Brücke :-). Ein Vorteil dieser Methode ist, dass nur zwei Kabel zur Weiche gezogen werden müssen. Man kann also ein vieradriges Kabel somit für zwei Weichen gleichzeitig benutzen, was die Verkabelung schonmal vereinfacht.
Bevor alle Bauteile zusammengefügt werden, sollte zunächst eine durchdachte Skizze erstellt werden. Diese hilft, Denkfehler zu vermeiden und Kurzschlüsse zu verhindern. Aufgrund der Vielzahl der Relais empfiehlt es sich, ein externes 5V-Netzteil für den Ansteuerungsstrom zu verwenden, da das Arduino-Board nicht genügend Spannung bereitstellen kann, vor allem nicht über USB. Ich habe den Ansteuerungsstrom über eine kleine Stromverteilerplatine verbunden. Da meine Relais etwa 70 mA pro Stück benötigen, ergibt sich bei 20 Relais (14 für Weichen und 6 für Licht) ein Strombedarf von ca. 1,4 A – deutlich zu viel für den Arduino. Die Steuerleitungen ziehen zwar ebenfalls Strom, belasten jedoch die Pins nur mit etwa 3–4 mA pro Relais. Wichtig: Der VCC und GND-Pin, welcher den Optokoppler und die LEDs des Relais steuert, muss trotzdem zusätzlich mit den 5V und GND-Pin des Arduino verbunden werden! Die externe Stromversorgung für die Spule wird am JD-VCC Pin angeschlossen und der Brückenstecker, welcher werkseitig den VCC mit dem JD-VCC-Pin verbindet wird entsprechend vorher entfernt.
Die Programmierung
Für die Programmierung gibt es so gesehen zwei Seiten. Einmal die grafische Oberfläche (Frontend) und der Arduino (Backend), der die Steuerbefehle vom Processing-Frontend empfängt und die Relais steuert. Hierzu nutze ich die cp5-Library um Buttons in die grafische Oberfläche einzufügen.
Auf der Processing Seite sieht ein Testcode so aus (schaltet testweise eine LED an und aus) -> Der entsprechende COM-Port, an dem der Arduino hängt kann man über die Arduino IDE auslesen.
import controlP5.*;
import processing.serial.*;
Serial arduino; // Serielles Objekt für die Kommunikation
ControlP5 cp5; // ControlP5-Objekt für die GUI
void setup() {
size(400, 200); // Fenstergröße
// Initialisiere serielle Kommunikation mit Arduino
arduino = new Serial(this, "COM3", 9600); // Ersetze "COM3" mit dem Port deines Arduino
// Initialisiere ControlP5
cp5 = new ControlP5(this);
// "Einschalten"-Button hinzufügen
cp5.addButton("Turn_ON")
.setPosition(50, 80) // Position des Buttons
.setSize(100, 40) // Größe des Buttons
.onClick(event -> sendCommand('a')); // Aktion: Sende Befehl 'a'
// "Ausschalten"-Button hinzufügen
cp5.addButton("Turn_OFF")
.setPosition(200, 80) // Position des Buttons
.setSize(100, 40) // Größe des Buttons
.onClick(event -> sendCommand('b')); // Aktion: Sende Befehl 'b'
}
void draw() {
background(200); // Hintergrundfarbe
textAlign(CENTER, CENTER); // Textausrichtung
textSize(16); // Schriftgröße
text("Arduino LED Steuerung", width / 2, 30); // Überschrift
}
// Funktion zum Senden von Befehlen an den Arduino
void sendCommand(char command) {
arduino.write(command); // Sende den Befehl über die serielle Schnittstelle
}
void setup() {
pinMode(13, OUTPUT); //set pin as output , blue led
Serial.begin(9600); //start serial communication @9600 bps
}
void loop(){
if(Serial.available()){ //id data is available to read
char val = Serial.read();
if(val == 'a'){ //if r received
digitalWrite(13, HIGH); //turn on red led
}
if(val == 'b'){ //if f received
digitalWrite(13, LOW); //turn off all led
}
}
}
Entsprechend dieser Prinzipien kann man nun die restlichen Buttons ergänzen und den Arduinocode darauf anpassen. Statt einer LED wird einfach das jeweilige Relais geschalten. Statt einem Schalter für rechts und links habe ich nur einen Button verwendet. Dies kann man über eine Variable, welche den jeweiligen aktuellen Status der Weiche enthält realisieren. Das senden des jeweiligen Befehls an den Arduino erfolgt mittels einem ternären Operator (Konditionale Zuweisung).
boolean W5 = false;
color greenColor = color(66, 161, 0); // Grün für geschaltete Strecke
color redColor = color(100, 0, 0, 255); // Rot mit Transparenz für gesperrte Strecke
//weiterer Code...
void setup() {
// Button für Weiche W5
cp5.addButton("W5")
.setPosition(650, 180) // Position
.setSize(60, 40) // Größe
.setFont(font)
.setLabel("W5");
//weiterer Code...
}
void draw() {
//weiterer Code...
}
//Weichenlinie zeichnen
if (W5) {
stroke(redColor); // Rot mit Transparenz
line(550, 200, 630, 200); // Rote Linie
stroke(greenColor); // Grün
line(630, 200, 560, 250); // Linie nach links neigen
}
// Funktion für die Weiche 5
void W5() {
W5 = !W5; //Status wird jeweils umgeschaltet
port.write(W5 ? "e" : "f"); //es wird je nach Richtung "e" oder "f" an den Arduino gesendet
updateLog("W5 nach " + (W5 ? "links" : "rechts"));
}
Natürlich kann die grafische Oberfläche noch ausgebaut werden, z.B. mit der Darstellung des Gleisplans und einer Animation der momentanen Richtung der Weiche. Den Großteil habe ich mit ganz normalen Linien realisiert.
color nLineColor = color(200, 200, 200); //Linienfarbe
void draw() {
strokeWeight(15);
strokeCap(SQUARE); //Endpunkt der Linie, z.B. auch ROUND möglich
stroke(nLineColor);
// line(X-start , Y-start, X-end, Y-end)
// arc(X-start , Y-start, width, height, start, stop);
// start Startwinkel des Bogens (in Radiant)
// end = Endwinkel des Bogens (in Radiant)
arc(350, 400, 600, 600, PI/2, PI*1.5);
arc(800, 400, 600, 600, -HALF_PI, HALF_PI);
line(350, 100, 800, 100);
// viele weitere Linien
}
Tipp: mit den folgenden Code lassen sich die Koordinaten des Mauszeigers im Canvas darstellen. Dies ist besonders hilfreich, um die Positionen der Linien und Buttons vor dem Eingeben grob zu bestimmen.
// Mauskoordinaten anzeigen
fill(255); //Textfarbe
textSize(15); //Textgröße
text("Mouse X: " + mouseX, 30, 50); // X-Koordinate anzeigen
text("Mouse Y: " + mouseY, 30, 70); // Y-Koordinate anzeigen
Hier kannst du den gesamten Processing-Code anschauen
import controlP5.*; // Import ControlP5 library
import processing.serial.*;
Serial port;
ControlP5 cp5; // ControlP5 object
PFont font;
boolean W12 = false;
boolean W34 = false;
boolean W5 = false;
boolean W6 = false;
boolean W7 = false;
boolean L1State = false;
boolean L2State = false;
boolean L3State = false;
boolean L4State = false;
boolean L5State = false;
boolean L6State = false;
color colorOn= color(0, 255, 0); // Grün für "an";
color colorOff= color(255, 0, 0); // Grau für "aus";
color greenColor = color(66, 161, 0); // Grün
color redColor = color(100, 0, 0, 255); // Rot mit Transparenz
color nLineColor = color(200, 200, 200);
color backColor = color(0, 0, 0);
String latestLog = ""; // Variable to hold the latest log message
void setup() {
background(backColor);
size(1366, 768); // Fenstergröße
println("Verfügbare serielle Ports:");
printArray(Serial.list()); // Druckt alle verfügbaren seriellen Ports
String portName = Serial.list()[1]; // Automatisch den ersten verfügbaren Port auswählen
port = new Serial(this, portName, 9600);
// GUI Setup
cp5 = new ControlP5(this);
font = createFont("calibri light bold", 20); // Benutzerdefinierte Schriftart
// Button für Weiche W5
cp5.addButton("W5")
.setPosition(650, 180) // Position
.setSize(60, 40) // Größe
.setFont(font)
.setLabel("W5");
// Button für Weiche W6
cp5.addButton("W6")
.setPosition(360, 360) // Position
.setSize(60, 40) // Größe
.setFont(font)
.setLabel("W6");
cp5.addButton("W12")
.setPosition(450, 580) // Position
.setSize(60, 40) // Größe
.setFont(font)
.setLabel("W1/2");
cp5.addButton("W34")
.setPosition(640, 580) // Position
.setSize(60, 40) // Größe
.setFont(font)
.setLabel("W3/4");
cp5.addButton("W7")
.setPosition(510, 330) // Position
.setSize(60, 40) // Größe
.setFont(font)
.setLabel("W7");
cp5.addButton("L1")
.setPosition(1150, 120) // Position
.setSize(180, 40) // Größe
.setFont(font)
.setLabel("Lichtmodul 1")
.setColorBackground(colorOff) // Hintergrundfarbe "aus" (grau)
.setColorLabel(color(0)); // Schriftfarbe Schwarz
cp5.addButton("L2")
.setPosition(1150, 180) // Position
.setSize(180, 40) // Größe
.setFont(font)
.setLabel("Lichtmodul 2")
.setColorBackground(colorOff) // Hintergrundfarbe "aus" (grau)
.setColorLabel(color(0)); // Schriftfarbe Schwarz
cp5.addButton("L3")
.setPosition(1150, 240) // Position
.setSize(180, 40) // Größe
.setFont(font)
.setLabel("Lichtmodul 3")
.setColorBackground(colorOff) // Hintergrundfarbe "aus" (grau)
.setColorLabel(color(0)); // Schriftfarbe Schwarz
cp5.addButton("L4")
.setPosition(1150, 300) // Position
.setSize(180, 40) // Größe
.setFont(font)
.setLabel("Lichtmodul 4")
.setColorBackground(colorOff) // Hintergrundfarbe "aus" (grau)
.setColorLabel(color(0)); // Schriftfarbe Schwarz
cp5.addButton("L5")
.setPosition(1150, 360) // Position
.setSize(180, 40) // Größe
.setFont(font)
.setLabel("Lichtmodul 5")
.setColorBackground(colorOff) // Hintergrundfarbe "aus" (grau)
.setColorLabel(color(0)); // Schriftfarbe Schwarz
cp5.addButton("L6")
.setPosition(1150, 420) // Position
.setSize(180, 40) // Größe
.setFont(font)
.setLabel("Lichtmodul 6")
.setColorBackground(colorOff) // Hintergrundfarbe "aus" (grau)
.setColorLabel(color(0)); // Schriftfarbe Schwarz
// Initialzustand senden, nach einer kurzen Verzögerung
delay(500); // 2 Sekunden Verzögerung, um die serielle Verbindung zu stabilisieren
println("Sende Initialzustände an Arduino...");
sendInitialState();
}
void draw() {
background(backColor); // Hintergrund für den gesamten Sketch neu zeichnen
drawEBUColorBars(1080, 570, 250); // EDU Color Bars bei (300, 300), Breite 300
// Mauskoordinaten anzeigen
fill(backColor);
fill(255);
textSize(15);
text("Mouse X: " + mouseX, 30, 50); // X-Koordinate anzeigen
text("Mouse Y: " + mouseY, 30, 70); // Y-Koordinate anzeigen
// Logs anzeigen
fill(backColor);
rect(0, 730, 1366, 38); // Bereich für Logs überdecken
fill(255);
text(latestLog, 30, 750); // Neuesten Log-Eintrag anzeigen
// Obere Leiste und Titel
fill(40, 40, 40);
rect(0, 0, 1366, 30);
fill(255);
textFont(font);
text("Stellwerk V3", 30, 23); // Titel des Fensters
text("Lichtsteuerung", 1150, 100);
text("Live Video", 1150, 550);
// Uhrzeit anzeigen
int h = hour();
int m = minute();
int s = second();
String time = nf(h, 2) + ":" + nf(m, 2) + ":" + nf(s, 2);
text(time, 1250, 23); // Uhrzeit anzeigen
// Konsolenausgabe anzeigen
// Grafik (Linien und Bögen) zeichnen
; // Textfarbe
smooth();
stroke(0);
noFill();
stroke(0, 0, 255); // Blaue Linie
strokeCap(ROUND);
if (W12) {
stroke(redColor); // Rot mit Transparenz
line(350, 600, 430, 600); // Gerade Linie
line(490, 700, 410, 700); // Gerade Linie
stroke(greenColor); // Grün
line(350, 600, 420, 650); // Linie nach links neigen
line(420, 650, 490, 700); // Linie nach links neigen
} else {
stroke(redColor); // Rot mit Transparenz
line(350, 600, 420, 650); // Linie nach links neigen
line(420, 650, 490, 700); // Linie nach links neigen
stroke(greenColor); // Grün
line(350, 600, 430, 600); // Gerade Linie
line(490, 700, 410, 700); // Gerade Linie
}
if (W34) {
stroke(redColor); // Rot mit Transparenz
line(800, 600, 720, 600); // Gerade Linie
line(660, 700, 740, 700); // Gerade Linie
stroke(greenColor); // Grün
line(800, 600, 730, 650); // Linie nach links neigen
line(730, 650, 660, 700); // Linie nach links neigen
} else {
stroke(redColor); // Rot mit Transparenz
line(800, 600, 730, 650); // Linie nach links neigen
line(730, 650, 660, 700); // Linie nach links neigen
stroke(greenColor); // Grün
line(800, 600, 720, 600); // Gerade Linie
line(660, 700, 740, 700); // Gerade Linie
}
if (W5) {
stroke(redColor); // Rot mit Transparenz
line(550, 200, 630, 200); // Rote Linie
stroke(greenColor); // Grün
line(630, 200, 560, 250); // Linie nach links neigen
} else {
stroke(redColor); // Rot mit Transparenz
line(630, 200, 560, 250); // Rote Linie
stroke(greenColor); // Grün
line(550, 200, 630, 200); // Gerade Linie
}
if (W6) {
stroke(redColor); // Rot mit Transparenz
line(490, 300, 420, 350); // Gerade Linie
stroke(greenColor); // Grün
line(420, 350, 500, 350); // Linie nach links neigen
} else {
stroke(redColor); // Rot mit Transparenz
line(420, 350, 500, 350); // Linie nach links neigen
stroke(greenColor); // Grün
line(490, 300, 420, 350); // Gerade Linie
}
if (W7) {
stroke(redColor); // Rot mit Transparenz
line(580, 350, 660, 350); // Gerade Linie
stroke(greenColor); // Grün
line(580, 350, 650, 400); // Linie nach links neigen
} else {
stroke(redColor); // Rot mit Transparenz
line(580, 350, 650, 400); // Linie nach links neigen
stroke(greenColor); // Grün
line(580, 350, 660, 350); // Gerade Linie
}
strokeWeight(15);
strokeCap(SQUARE);
stroke(nLineColor);
arc(350, 400, 600, 600, PI/2, PI*1.5);
arc(800, 400, 600, 600, -HALF_PI, HALF_PI);
line(350, 100, 800, 100);
arc(350, 400, 400, 400, PI/2, PI*1.5);
arc(800, 400, 400, 400, -HALF_PI, HALF_PI);
line(350, 200, 550, 200);
line(630, 200, 800, 200);
line(560, 250, 490, 300);
line(350, 700, 410, 700);
line(740, 700, 800, 700);
line(430, 600, 720, 600);
line(490, 700, 660, 700);
line(420, 350, 270, 460);
line(500, 350, 580, 350);
line(660, 350, 850, 350);
line(650, 400, 730, 460);
}
// Initiale Zustände an den Arduino senden
void sendInitialState() {
println("Betriebsbereit");
updateLog("Betriebsbereit");
}
// Log-Update Funktion
void updateLog(String message) {
latestLog = message;
}
// Funktion, um den Zustand von W1 zu wechseln
void W12() {
W12 = !W12;
port.write(W12 ? "a" : "b");
updateLog("W12 nach " + (W12 ? "links" : "rechts"));
}
void W34() {
W34 = !W34;
port.write(W34 ? "c" : "d");
updateLog("W34 nach " + (W34 ? "links" : "rechts"));
}
void W5() {
W5 = !W5;
port.write(W5 ? "e" : "f");
updateLog("W5 nach " + (W5 ? "links" : "rechts"));
}
void W6() {
W6 = !W6;
port.write(W6 ? "g" : "h");
updateLog("W6 nach " + (W6 ? "links" : "rechts"));
}
void W7() {
W7 = !W7;
port.write(W7 ? "i" : "j");
updateLog("W7 nach " + (W7 ? "links" : "rechts"));
}
void L1() { toggleLight(1, L1State = !L1State); }
void L2() { toggleLight(2, L2State = !L2State); }
void L3() { toggleLight(3, L3State = !L3State); }
void L4() { toggleLight(4, L4State = !L4State); }
void L5() { toggleLight(5, L5State = !L5State); }
void L6() { toggleLight(6, L6State = !L6State); }
void toggleLight(int index, boolean state) {
char onCommand = (char) ('o' + (index - 1) * 2); // Buchstabe für Ein
char offCommand = (char) ('p' + (index - 1) * 2); // Buchstabe für Aus
port.write(state ? onCommand : offCommand); // Entweder Ein- oder Aus-Befehl senden
updateLog("Lichtmodul " + index + (state ? " aktiviert" : " deaktiviert"));
cp5.getController("L" + index).setColorBackground(state ? colorOn : colorOff);
}
void drawEBUColorBars(int x, int y, int width) {
int height = int(width * 9.0 / 16.0); // Höhe basierend auf 16:9 berechnen
int barWidth = width / 7; // Breite jedes Farbblocks (7 Farben)
// Farben der EDU Color Bars
color[] colors = {
color(255, 255, 255), // Weiß
color(255, 255, 0), // Gelb
color(0, 255, 255), // Cyan
color(0, 255, 0), // Grün
color(255, 0, 255), // Magenta
color(255, 0, 0), // Rot
color(0, 0, 255) // Blau
};
// Zeichne die vertikalen Farbblöcke
for (int i = 0; i < 7; i++) {
fill(colors[i]);
noStroke();
rect(x + i * barWidth, y, barWidth, height); // Vertikale Balken
}
}
Hier kannst du den gesamten Arduino-Code anschauen
// Weichen
const int W1R = 52;
const int W1L = 53;
const int W2R = 50;
const int W2L = 51;
const int W3R = 48;
const int W3L = 49;
const int W4R = 46;
const int W4L = 47;
const int W5R = 44;
const int W5L = 45;
const int W6R = 42;
const int W6L = 43;
const int W7R = 40;
const int W7L = 41;
//Lichtmodule
const int L1 = 39;
const int L2 = 38;
const int L3 = 37;
const int L4 = 36;
const int L5 = 35;
const int L6 = 34;
const int schaltZeit = 500;
void setup() {
// Pins als Ausgang definieren
pinMode(W1R, OUTPUT);
pinMode(W1L, OUTPUT);
pinMode(W2R, OUTPUT);
pinMode(W2L, OUTPUT);
pinMode(W3R, OUTPUT);
pinMode(W3L, OUTPUT);
pinMode(W4R, OUTPUT);
pinMode(W4L, OUTPUT);
pinMode(W5R, OUTPUT);
pinMode(W5L, OUTPUT);
pinMode(W6R, OUTPUT);
pinMode(W6L, OUTPUT);
pinMode(W7R, OUTPUT);
pinMode(W7L, OUTPUT);
pinMode(L1, OUTPUT);
pinMode(L2, OUTPUT);
pinMode(L3, OUTPUT);
pinMode(L4, OUTPUT);
pinMode(L5, OUTPUT);
pinMode(L6, OUTPUT);
digitalWrite(W1R, HIGH);
digitalWrite(W1L, HIGH);
digitalWrite(W2R, HIGH);
digitalWrite(W2L, HIGH);
digitalWrite(W3R, HIGH);
digitalWrite(W3L, HIGH);
digitalWrite(W4R, HIGH);
digitalWrite(W4L, HIGH);
digitalWrite(W5R, HIGH);
digitalWrite(W5L, HIGH);
digitalWrite(W6R, HIGH);
digitalWrite(W6L, HIGH);
digitalWrite(W7R, HIGH);
digitalWrite(W7L, HIGH);
digitalWrite(L1, HIGH);
digitalWrite(L2, HIGH);
digitalWrite(L3, HIGH);
digitalWrite(L4, HIGH);
digitalWrite(L5, HIGH);
digitalWrite(L6, HIGH);
// Serielle Kommunikation starten
Serial.begin(9600);
}
void loop() {
// Prüfen, ob Daten verfügbar sind
if (Serial.available() > 0) {
char receivedChar = Serial.read(); // Empfangene Zeichen einlesen
//W und W2
if (receivedChar == 'a') {
digitalWrite(W1R, LOW);
digitalWrite(W2R, LOW);
delay(schaltZeit);
digitalWrite(W1R, HIGH);
digitalWrite(W2R, HIGH);
} else if (receivedChar == 'b') {
digitalWrite(W1L, LOW);
digitalWrite(W2L, LOW);
delay(schaltZeit);
digitalWrite(W1L, HIGH);
digitalWrite(W2L, HIGH);
} else if (receivedChar == 'c') {
digitalWrite(W3R, LOW);
digitalWrite(W4R, LOW);
delay(schaltZeit);
digitalWrite(W3R, HIGH);
digitalWrite(W4R, HIGH);
} else if (receivedChar == 'd') {
digitalWrite(W3L, LOW);
digitalWrite(W4L, LOW);
delay(schaltZeit);
digitalWrite(W3L, HIGH);
digitalWrite(W4L, HIGH);
} else if (receivedChar == 'e') {
digitalWrite(W5L, LOW);
delay(schaltZeit);
digitalWrite(W5L, HIGH);
} else if (receivedChar == 'f') {
digitalWrite(W5R, LOW);
delay(schaltZeit);
digitalWrite(W5R, HIGH);
} else if (receivedChar == 'g') {
digitalWrite(W6L, LOW);
delay(schaltZeit);
digitalWrite(W6L, HIGH);
} else if (receivedChar == 'h') {
digitalWrite(W6R, LOW);
delay(schaltZeit);
digitalWrite(W6R, HIGH);
} else if (receivedChar == 'i') {
digitalWrite(W7L, LOW);
delay(schaltZeit);
digitalWrite(W7L, HIGH);
}
else if (receivedChar == 'j') {
digitalWrite(W7R, LOW);
delay(schaltZeit);
digitalWrite(W7R, HIGH);
} else if (receivedChar == 'o') {
digitalWrite(L1, LOW);
} else if (receivedChar == 'p') {
digitalWrite(L1, HIGH);
} else if (receivedChar == 'q') {
digitalWrite(L2, LOW);
} else if (receivedChar == 'r') {
digitalWrite(L2, HIGH);
} else if (receivedChar == 's') {
digitalWrite(L3, LOW);
} else if (receivedChar == 't') {
digitalWrite(L3, HIGH);
} else if (receivedChar == 'u') {
digitalWrite(L4, LOW);
} else if (receivedChar == 'v') {
digitalWrite(L4, HIGH);
} else if (receivedChar == 'w') {
digitalWrite(L5, LOW);
} else if (receivedChar == 'x') {
digitalWrite(L5, HIGH);
} else if (receivedChar == 'y') {
digitalWrite(L6, LOW);
} else if (receivedChar == 'z') {
digitalWrite(L6, HIGH);
}
}
}
Fazit
Soweit zu meiner Weichensteuerung mit Arduino. Ich hoffe, diese Anleitung kann hilfreich sein und einen guten Ausgangspunkt für euere eigene Projekte bieten. Für mich war es eine spannende Sache, die Schaltung selbst zu entwickeln und die Software individuell anzupassen, um die Steuerung genau auf meine Bedürfnisse abzustimmen. Mit einem Arduino und ein paar gängigen Bauteilen ließ sich das Ganze einfach umsetzen, und nebenbei konnte ich noch viel mehr über das Zusammenspiel zwischen Arduino und Processing 4 lernen. Ich könnte an einigen Stellen noch weiter ins Detail gehen, aber vieles davon ist sehr spezifisch für meine Lösung und daher vielleicht nicht universell hilfreich.
Danke fürs Lesen!
Hi, das ist ein tolles Projekt. Ich bin auf die gleiche Idee gekommen, allerdings gab es bei mir ein physisches Stellpult.
Ich werde mal deine Code studieren. Viele Dank fürs Teilen.
Vielleicht magst du dir mein Projekt mal ansehen auf meinem Kanal?
https://youtu.be/5ymEzGcZVnA?si=CjtiGHHdTAkvWsg_
Viele Grüße