Teil 4: Wir steuern einen Zug mit dem ESP32

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
  • 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 GeradeArt.-Nr. 42520
1x Halbe GeradeArt.-Nr. 42512
1x Halbe Gerade mit StromanschlussArt.-Nr. 42521
Piko A-Gleis mit Bettung
12x KurvensegmentArt.-Nr.
1x GeradeArt.-Nr.
1x Gerade mit StromanschlussArt.-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:

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(0, 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(0, 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:

const int enPin = 27;
const int freq = 19531;
const int ledChannel = 0;
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(0, pwmOutput);
}

void setup() {
  // Start Serial
  Serial.begin(115200);

  // Set pin modes
  pinMode(fwdPin, OUTPUT);
  pinMode(bckPin, OUTPUT);

  ledcSetup(0, freq, resolution);
  ledcAttachPin(enPin, 0);
}
 
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.

Kommentar verfassen

WordPress Cookie Plugin von Real Cookie Banner