Jetzt steigen wir voll ein und steuern mit dem Wissen der ersten drei Teile einen Zug. Dazu bauen wir zunächst eine kleine Anlage auf und setzen dann unseren ESP32, einen L298N und ein Potentiometer ein, um den Zug fahren zu lassen.
Was Du für diesen Teil brauchst
- Schienen für einen geschlossenen Ring mit Stromanschluss (siehe unten)
- Gleichstromlok und gegebenfalls passende Wagons
- Oder ein komplettes Starterset für Gleichstrom analog
- Piko: z.B. Start-Set DB Cargo BR 218 (hier kaufen)
- Roco: z.B. Analog Start Set Rh 2045 (hier kaufen)
- L298N Motortreiber Modul (hier kaufen)
- 12V DC Netzteil mit passender Buchse, z.B. (hier kaufen)
Aufbau der Modelleisenbahn Anlage ohne Starterset
Sofern Du kein komplettes Starterset hast, müssen zunächst die Strecke geplant und passende Schienen besschafft werden. Für einen flexiblen Auf- und Abbau habe ich sehr gute Erfahrungen mit den Serien Rocoline mit Bettung und Piko A-Gleis mit Bettung gemacht. Für den Start ist natürlich ein klassisches Oval die einfachste Variante, dazu benötigst Du folgende Teile:
Rocoline mit Bettung | |
12x Kurvensegment R3, 30° | Art.-Nr. 42523 |
1x Gerade | Art.-Nr. 42520 |
1x Halbe Gerade | Art.-Nr. 42512 |
1x Halbe Gerade mit Stromanschluss | Art.-Nr. 42521 |
Piko A-Gleis mit Bettung | |
12x Kurvensegment | Art.-Nr. |
1x Gerade | Art.-Nr. |
1x Gerade mit Stromanschluss | Art.-Nr. |
Für komplexere Strecken eignet sich am besten eine Gleispanungs-Software. Etwas älter, aber durchaus gut und komplett frei ist Trackplanner (http://www.trackplanner.de). Moderner, mit 3D Ansicht und Landschaftsgestaltung ist das 3D-Modellbahn Studio (https://www.3d-modellbahn.de), das es auch kostenfrei in einer Basis-Version gibt. Beide Programme haben Gleisbibliotheken für die genannten Serien und können direkt eine Teile-Liste mit den Artikelnummern für die gewünschte Anlage ausgeben.
Aufbau der Elektronik (ESP32 und L298N)
Anpassung des Sketch
Als erstes integrieren wir eine Funktion zum Auslesen des Poti mit dem später der Zug gesteuert werden soll. Wir nutzen dazu einen in den ESP32 integrierten Analog-Digital-Converter (ADC), der an einem Pin anliegende Spannungen in Werte von 0 bis 4095 wandelt. Durch den Abgriff des Schiebers in der Mitte des Poti-Widerstands, soll die Null-Stellung entsprechend bei der Mitte der durch den ADC erzeugten Werte liegen, um später auch Vorwärts- und Rückwärtsfahrt zu ermöglichen.
Unterhalb der globalen Variablen aus dem Sketch aus Teil 2: PWM und MOSFET für eine einfache Motorsteuerung fügen wir ein:
Aktualisiert auf Version 3. Siehe dazu unter ESP32 Version 3.0 für Arduinio IDE
const int potiPin = 34; //A0;
const int potiMin = 0;
const int potiCenter = 1840;
const int potiMax = 4095;
const int minPwm = 0;
const int fwdPin = 32;
const int bckPin = 33;
void setCommonPwm() {
int pwmOutput = 0;
byte pwmDirection = 0; // +1 for FWD, -1 for REV
int potiPosition = analogRead(potiPin);
// SET COMMON MOTOR SPEED AND DIRECTION
if (potiPosition > potiCenter - 200 && potiPosition < potiCenter + 200) {
// Neutral
pwmOutput = 0;
if (pwmDirection != 0) {
pwmDirection = 0;
Serial.println("Poti 0");
digitalWrite(fwdPin, LOW);
digitalWrite(bckPin, LOW);
}
}
else {
if (potiPosition > potiCenter) {
// Forward
pwmOutput = map(potiPosition, potiCenter, potiMax, minPwm , 255);
if (pwmDirection != 1) {
pwmDirection = 1;
Serial.println("Poti FWD");
digitalWrite(fwdPin, HIGH);
digitalWrite(bckPin, LOW);
}
}
else {
// Back
pwmOutput = map(potiCenter - potiPosition, potiMin, potiCenter, minPwm , 255);
if (pwmDirection != -1) {
pwmDirection = -1;
Serial.println("Poti REV");
digitalWrite(fwdPin, LOW);
digitalWrite(bckPin, HIGH);
}
}
}
Serial.println(pwmOutput);
ledcWrite(enPin, pwmOutput);
}
Gehen wir Teile der Funktion im einzelnen durch.
int potiPosition = analogRead(potiPin);
Mit der Funktion analogRead() wird der durch das Poti regulierte Spannungswert am Eingangspin analog mithilfe des ADC ausgelesen.
if (potiPosition > potiCenter - 200 && potiPosition < potiCenter + 200) {
Zur Erkennung der Neutral-Position wird ein Wert von +/- 200 rund um den Mittelwert akzeptiert.
digitalWrite(fwdPin, LOW);
digitalWrite(bckPin, LOW);
Wie wir bereits im Teil 3: Motorsteuerung mit PWM und H-Brücke gesehen haben, wird der L298N Motortreiber für jede H-Brücke mit einem PWM-Signal am EN-Pin und HIGH/LOW an zwei IN-Pins für die Wahl der Laufrichtung angesteuert. Diese IN-Pins werden hier angesteuert – entsprechend der Position in der if-Bedingung, hier beide LOW, da neutrale Mittelposition.
pwmOutput = map(potiPosition, potiCenter, potiMax, minPwm , 255);
Außerhalb der Neutral-Position muss die Position des Poti, mit Werten von 0 bis 4095, auf den Bereich 0-255 für den Eingang in die PWM-Steuerung mit ledc umgerechnet werden. Das macht die Funktion map().
ledcWrite(enPin, pwmOutput);
Auch dieser Teil ist bereits bekannt: Wir nutzen das ledc-Modul des ESP32 zur Ausgabe des PWM-Signals.
Dann muss diese Funktion noch regelmäßig über loop() aufgerufen werden. Alle anderen Anweisungen aus loop(), die wir im zweiten Teil zum Testen genutzt haben, werden gelöscht. Der fertige Sketch sieht damit wie folgt aus:
Aktualisiert auf Version 3. Siehe dazu unter ESP32 Version 3.0 für Arduinio IDE
const int enPin = 27;
const int freq = 19531;
const int resolution = 8;
const int potiPin = 34; //A0;
const int potiMin = 0;
const int potiCenter = 1840;
const int potiMax = 4095;
const int minPwm = 0;
const int fwdPin = 32;
const int bckPin = 33;
void setCommonPwm() {
int pwmOutput = 0;
byte pwmDirection = 0; // +1 for FWD, -1 for REV
int potiPosition = analogRead(potiPin);
// SET COMMON MOTOR SPEED AND DIRECTION
if (potiPosition > potiCenter - 200 && potiPosition < potiCenter + 200) {
// Neutral
pwmOutput = 0;
if (pwmDirection != 0) {
pwmDirection = 0;
Serial.println("Poti 0");
digitalWrite(fwdPin, LOW);
digitalWrite(bckPin, LOW);
}
}
else {
if (potiPosition > potiCenter) {
// Forward
pwmOutput = map(potiPosition, potiCenter, potiMax, minPwm , 255);
if (pwmDirection != 1) {
pwmDirection = 1;
Serial.println("Poti FWD");
digitalWrite(fwdPin, HIGH);
digitalWrite(bckPin, LOW);
}
}
else {
// Back
pwmOutput = map(potiCenter - potiPosition, potiMin, potiCenter, minPwm , 255);
if (pwmDirection != -1) {
pwmDirection = -1;
Serial.println("Poti REV");
digitalWrite(fwdPin, LOW);
digitalWrite(bckPin, HIGH);
}
}
}
Serial.println(pwmOutput);
ledcWrite(enPin, pwmOutput);
}
void setup() {
// Start Serial
Serial.begin(115200);
// Set pin modes
pinMode(fwdPin, OUTPUT);
pinMode(bckPin, OUTPUT);
ledcAttach(enPin, freq, resolution);
}
void loop() {
setCommonPwm();
delay(100);
}
Zug aufgleisen und Los
Jetzt wird es Zeit, den Zug auf die Gleise zu stellen und eine erste Runde zu drehen.