Zum Inhalt springen
Arduino Bahnhof RailFX OLED

RailFX: Arduino Bahnhof

    Dieses Modul des RailFX-Systems steuert einen Arduino Bahnhof für die Modellbahn. Zu den Funktionen zählten:

    • OLED-Abfahrtsanzeiger mit wechselnden Inhalten
    • Zufalls- oder sensorgesteuerte Umschaltung des Displays
    • Sound-Modul mit Ansagen der »Blechelse«
    • Bahnhofsbeleuchtung mit Leuchtstoffröhren-Einschalteffekt

    Schaltplan

    RailFX, Arduino Bahnhof Modul mit Sound, MP3 und OLED-Display
    • D2, D3: DFPlayer MP3 Modul
    • D4 – D12: LEDs als Leuchtstoffröhren
    • A0 (D14) und A1 (D15) Lichtschranken für Zugdetektion
    • A3: Anschluss des Zeitsignals des Conrol-Moduls
    • A4, A5: I2C Verbindung zum OLED-Display

    Achtung: Am Pin A3 (normalerweise A4, aber hier A3) wird das Control-Signal des RailFX Control-Moduls angelegt. Es steuert die Tageszeit und ist zwingend erforderlich.

    Bauteile Arduino Bahnhof

    Einstellungen im Code

    Auch dieses Modul bietet eine Reihe von Einstellmöglichkeiten. Die Beleuchtung des Bahnhofes kann beim Einschalten wie Leuchtstoffröhren flackern. Die Zeit, die alle Lampen zum Einschalten kann man mit der Variable flackerzeitLeuchten einstellen. Je höher der Wert ist, desto länger flackern die Leuchten. Wie heftig sie flackern lässt sich mit der Variable flackerGeschwindigkeit einstellen.


    Sieh dir jetzt meinen neuen Arduino-Videokurs an: Jetzt ansehen!


    Die Anzeigen auf dem OLED-Display wechseln sich entweder per Zufall oder per Lichtschranken, je nachdem, ob man die Methode anzeigeTafelAutomatisch() oder anzeigeTafelSensor() im Loop anspricht. Im Lichtschranken-Modus wechselt sich die Anzeigt, sobald beide Sensoren freigegeben werden, also, wenn sich kein Zug mehr auf dem Gleis befindet.

    Im automatischen Modus kann man die folgenden Einstellungen vornehmen: Die minimale Dauer pro Anzeige lässt sich mit der Variable anzeigenWechselMin einstellen. Zu ihr wird per Zufall eine Zeit zwischen 0 und dem in der Variable anzeigenwechselVariableZeit festgelegten Wert addiert.

    Die Texte auf dem Display werden im Array textSegments festgelegt. Es lässt sich durch weitere Texte erweitern. Dafür müssen die Dimensionen im Array und die Variable anzeigeAnzahl angepasst werden.

    Das Display zeigt automatisch beim Umschalten die aktuelle Modellbahnzeit an. Die Folgezüge werden im 30-Minuten-Takt angezeigt. Ist die aktuelle Zeit also 17:21, werden die Abfahrtszeiten der Folgezüge 17:51 und 18:21 angezeigt.

    Per Zufall zeigt das Display auch einen Hinweis an. Den Text kann man in der Variable hinweis anpassen.

    Für die Tonausgabe wird der DFPlayer Mini verwendet. Er spielt MP3- und WAV-Dateien von einer SD-Karte ab. Für die Nutzung muss die DFPlayer Mini Bibliothek eingebunden werden. Klicke dafür im Arduino-Menü auf Sketch>Bibliotheken einbinden>Bibliotheken verwalten und gib im Suchfeld »dfplayer mini« ein. Installiere die Bibliothek DFPlayer Mini MP3 by Makuna in der aktuellen Version.

    Die SD-Karte muss im FAT16 oder FAT32-Dateisystem formatiert sein. Darüber hinaus müssen sich die Dateien im Ordner »01« befinden und die Dateinamen müssen aufeinander folgend 001.mp3, 002.mp3, 003.mp3 usw. benannt sein. Wie erwähnt, dürfen auch WAV-Dateien verwendet werden: 001.mp3, 002.wav, 003.mp3 …

    Beispiel-Dateien können hier heruntergeladen werden:

    /* ***** ***** Einstellungen ***** ***** */
    int flackerzeitLeuchten = 1000;              // Je höher der Wert, desto mehr flackern die Leuchtstoffröhren beim Einschalten
    int flackerGeschwindigkeit = 100;            // Flackergeschwindigkeit der Leuchtstoffröhren
    int anzeigenWechselMin = 2000;               // Anzeigewechsel alle x Millisekunden
    int anzeigenwechselVariabeleZeit = 3000;     // Um diesen Wert (Millisekunden) variiert der Anzeigewechsel
    int mp3Anzahl = 10;                          // Menge der MP3 Dateien auf der SD-Karte
    int mp3Dauer[] = {16,16,15,17,17,18,19,18,19,9}; // Dauer der MP3 Dateien in Sekunden
    int mp3Wahrscheinlichkeit = 20;              // Wahrscheinlichkeit, mit der MP3s abgespielt werden, 10 oft, 100 selten
    int lautstaerke = 10;                        // Lautstärke des DFPlayers (0 – 30);
    /* Anzeigen */
    int anzeigeAnzahl = 6;                       // Muss so groß sein, wie die Anzahl der angezeigten Texte aus dem Array textSegments
    const char* textSegments[6][9] = {
      {"12", "", "Zugdurchfahrt", "17:08", "17:44", "RB31", "RB31", "Elsterw-Biehal", "von Coswig (b. Dresde"},
      {"12", "Leipzig Hbf - Halle (Saale)", "Hannover Hbf", "17:08", "17:44", "RB31", "RB31", "Elsterw-Biehal", "von Coswig (b. Dresde"},
      {"12", "Leipzig Hbf - Halle (Saale)", "Berlin Hbf", "17:08", "17:44", "RB31", "RB31", "Elsterw-Biehal", "von Coswig (b. Dresde"},
      {"12", "Leipzig Hbf - Halle (Saale)", "Dresden Hbf", "17:08", "17:44", "RB31", "RB31", "Elsterw-Biehal", "von Coswig (b. Dresde"},
      {"12", "Leipzig Hbf - Halle (Saale)", "Leipzig Hbf", "17:08", "17:44", "RB31", "RB31", "Elsterw-Biehal", "von Coswig (b. Dresde"},
      {"12", "Leipzig Hbf - Halle (Saale)", "Hamburg Hbf", "17:08", "17:44", "RB31", "RB31", "Elsterw-Biehal", "von Coswig (b. Dresde"}
    };
    const char* hinweis[] = {
      "Aufgrund einer Signalstorung ",
      "hat der ICE100 heute leider ca. 25 Minuten Verspatung. ",
      "Wir bitten um Ihr Verstandnis."
    };

    Code für das Modul: RailFX-Bahnhof

    Libraries

    Für dieses Projekt wird dieSSD1306Ascii Bibliothek von Bill Greiman benötigt. Man kann sie hinzufügen, indem man im Arduino Menü > Sketch > Bilbiothek hinzufügen > Bibliotheken verwalten nach »SSD1306Ascii« sucht und die aktuelle Version installiert.

    Darüber hinaus wird die Bibliothek DFRobotDFPlayerMini von DFRobot verwendet. Auch diese installiert man über Bibliotheken verwalten. Hier kann man einfach nach dfplayer suchen.

    Beim Upload muss man darauf achten, dass das richtige Board im Arduino-Menü ausgewählt ist. Dazu muss ebenfalls im Werkzeuge-Menü im Unterpunkt Prozessor »ATmega328P (Old Bootlaoder)« ausgewählt sein. Ansonsten kann man den folgenden Programmcode mit den oben erwähnten Änderungen einfach kopiert und auf das Arduino-Nano laden.

    #include <Wire.h>
    #include "SSD1306Ascii.h"
    #include "SSD1306AsciiWire.h"
    #include "SoftwareSerial.h"              // Wird für den DFPlayer benötigt
    #include "DFRobotDFPlayerMini.h"         // Wird für den DFPlayer benötigt
    /*
         Rail-FX Bahnhof
         StartHardware.org
    */
    
    /* ***** ***** Einstellungen ***** ***** ***** *****  ***** ***** ***** *****  ***** ***** ***** ***** */
    int flackerzeitLeuchten = 1000;              // Je höher der Wert, desto mehr flackern die Leuchtstoffröhren beim Einschalten
    int flackerGeschwindigkeit = 100;            // Flackergeschwindigkeit der Leuchtstoffröhren
    int anzeigenWechselMin = 2000;               // Anzeigewechsel alle x Millisekunden
    int anzeigenwechselVariabeleZeit = 3000;     // Um diesen Wert (Millisekunden) variiert der Anzeigewechsel
    int mp3Anzahl = 6;                           // Menge der MP3 Dateien auf der SD-Karte
    int mp3Dauer[] = {13, 16, 16, 10, 9, 9};     // Dauer der MP3 Dateien in Sekunden
    int mp3Wahrscheinlichkeit = 10;              // Wahrscheinlichkeit, mit der MP3s abgespielt werden, 10 oft, 100 selten
    int lautstaerke = 10;                        // Lautstärke des DFPlayers (0 – 30);
    int empfangsPuffer = 55;                     // Ändern der Anzeige kann das Empfangen des Zeitsignals verhindern. Deshalb werden ab dieser Modellbahn-Minute keine Displayänderungen ausgeführt (muss kleiner als 59 sein)
    
    /* Anzeigen */
    int anzeigeAnzahl = 6;                       // Muss so groß sein, wie die Anzahl der angezeigten Texte aus dem Array textSegments
    const char* textSegments[6][7] = {
      {"12", "", "Zugdurchfahrt", "RB31", "RB31", "Elsterw-Biehal", "von Coswig (b. Dresde"},
      {"12", "Leipzig Hbf - Halle (Saale)", "Hannover Hbf", "RB31", "RB31", "Elsterw-Biehal", "von Coswig (b. Dresde"},
      {"12", "Leipzig Hbf - Halle (Saale)", "Berlin Hbf", "RB31", "RB31", "Elsterw-Biehal", "von Coswig (b. Dresde"},
      {"12", "Leipzig Hbf - Halle (Saale)", "Dresden Hbf", "RB31", "RB31", "Elsterw-Biehal", "von Coswig (b. Dresde"},
      {"12", "Leipzig Hbf - Halle (Saale)", "Leipzig Hbf", "RB31", "RB31", "Elsterw-Biehal", "von Coswig (b. Dresde"},
      {"12", "Leipzig Hbf - Halle (Saale)", "Hamburg Hbf", "RB31", "RB31", "Elsterw-Biehal", "von Coswig (b. Dresde"}
    };
    const char* hinweis[] = {
      "Auf Grund einer Signalstorung ",
      "hat der ICE100 heute leider ca. 25 Minuten Verspatung. ",
      "Wir bitten um Ihr Verstandnis."
    };
    
    /* ***** ***** Ab hier beginnt der Programmcode, der nicht angepasst werden muss ***** ***** ***** ***** */
    // 0X3C+SA0 - 0x3C or 0x3D
    #define I2C_ADDRESS 0x3C
    uint32_t tickTime = 0;
    int tickerPosition = 0;
    #define RTN_CHECK 1
    int leuchtstoffroehrenPins[9] = {4, 5, 6, 7, 8, 9, 10, 11, 12};
    int sensorPin1 = 15;                      // an diesem Pin ist ein Abstandssensor angeschlossen (15 = A1)
    int sensorPin2 = 16;                      // an diesem Pin ist ein Abstandssensor angeschlossen (16 = A2)
    int sensor1Zustand = 0;                   // speichert den aktuellen Zustand des Sensors
    int sensor1ZustandAlt = 0;                // macht den Zustand des Sensors nach dem Neueinlesen verfügbar
    int sensor2Zustand = 0;                   // speichert den aktuellen Zustand des Sensors
    int sensor2ZustandAlt = 0;                // macht den Zustand des Sensors nach dem Neueinlesen verfügbar
    
    /* Speicher Variablen */
    int leuchtstoffroehrenZustand[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1};
    TickerState state;        // Speichert den aktuellen Text-Pointer des OLED-Tickers
    int verspaetung = 0;      // wird per Zufall ermittelt; 1=Verspätung, 0=keine Verspätung
    int anzeigenwechselVariabeleZeitHilfsvariable = 0;
    
    /* Timer Variablen */
    long leuchtstoffroehrenTimer[9];
    long anzeigeTimer;
    
    /* Variablen für das OLED */
    SSD1306AsciiWire oled;
    
    /* Variablen für den MP3 Player*/
    long soundTimer = 0;                     // Timer des DFPlayers
    long soundTimeout = 0;                   // Speichert die Abspieldauer des aktuellen MP3
    int soundState = 0;                      // Status des DFPlayers
    int soundRandom;
    int theSound;
    int soundPlaying = false;
    SoftwareSerial mySoftwareSerial(3, 2);   // RX, TX für den DFPlayer
    DFRobotDFPlayerMini myDFPlayer;          // DFPlayer Objekt
    
    /* Variablen vom Controlmodul um die Uhrzeit festzustellen*/
    boolean receive = false;
    boolean receiveStarted = false;
    int receiveTimeout = 10;
    long receiveTimer = 0;
    int receivedTime = 0;
    int receivePulse = 0;
    int lastReceivePulse = 0;
    int receivePin = 17;
    int myTime = 8;
    int myMinutes = 0;
    long lastTimeSignal;
    int timeToHour;
    #define PAYLOAD_SIZE 2                       // nötig für die Kommunikation zum Master
    int uhrzeit = 0;                             // speichert die uhrzeit vom Master-Modul (0 und 255)
    byte nodePayload[PAYLOAD_SIZE];              // speichert die Daten vom Master-Modul zwischen
    
    void setup() {
      Serial.begin(115200);                      // started die serielle Kommunikation
      pinMode(receivePin, INPUT);                // Empfangspin vom Control-Modul
      Wire.begin();                              // I2C Verbindung zum OLED
      Wire.setClock(400000L);                    // I2C Verbindung zum OLED
      mySoftwareSerial.begin(9600);              // started die serielle Kommunikation für den DFPlayer
      oled.begin(&Adafruit128x64, I2C_ADDRESS);  // Start des OLEDs
      for (int i = 0; i < 9; i++) {
        pinMode(leuchtstoffroehrenPins[i], OUTPUT);
        digitalWrite(leuchtstoffroehrenPins[i], HIGH);
      }
      randomSeed(A2);
      oled.tickerInit(&state, Adafruit5x7, 0, false, 27, 100);    // Ticker für die Anzeigetafel
      drawInfo(1);
      /* DFPlayer Setup */
      Serial.println(F("Initializing DFPlayer ... "));
      if (!myDFPlayer.begin(mySoftwareSerial, false)) { // nutze softwareSerial um mit dem DFPlayer zu sprechen
        Serial.println(F("Fehler: Prüfe Verbindung zum DFPlayer und SD-Karte"));
        /*while (true) {
          delay(0); // Code to compatible with ESP8266 watch dog.
          }*/
      }
      Serial.println(F("DFPlayer Mini online."));
      myDFPlayer.volume(lautstaerke);       // Lautstärke wird zugewiesen
      delay(1000);
      pinMode(sensorPin1, INPUT_PULLUP);
      pinMode(sensorPin2, INPUT_PULLUP);
    }
    
    void loop() {
      receiveFunction();                // Führe Anweisungen für Empfang aus
      if (receiveStarted == false) {    // Falls gerade keine Daten empfangen werden:
        if (myTime > 22) {              // ***** Später Abend *****
          leuchtstoffroehrenEin();      // Leuchtstoffröhren einschalten
          soundAn();                    // Sound An
        } else if (myTime > 18) {       // ***** Abend *****
          leuchtstoffroehrenEin();      // Leuchtstoffröhren einschalten
          soundAn();                    // Sound An
        } else if (myTime > 12) {       // ***** Nachmittag *****
          leuchtstoffroehrenAus();      // Leuchtstoffröhren ausschalten
          soundAn();                    // Sound An
        } else if (myTime > 9) {        // ***** Vormittag *****
          leuchtstoffroehrenAus();      // Leuchtstoffröhren ausschalten
          soundAn();                    // Sound An
        } else if (myTime > 7) {        // ***** Morgen *****
          leuchtstoffroehrenAus();      // Leuchtstoffröhren einschalten
          soundAn();                    // Sound An
        } else if (myTime > 0) {                     // ***** Nacht *****
          leuchtstoffroehrenEin();      // Leuchtstoffröhren einschalten
          soundAus();                    // Sound Aus
        }
        if (myMinutes < empfangsPuffer) {
          anzeigeTafelSensor(); // Anzeigetafel schaltet per Sensor um
          // anzeigeTafelAutomatisch(); // Anzeigetafel schaltet per Zufall um
        }
      }
    }
    
    void anzeigeTafelSensor() {
      sensor1Zustand = digitalRead(sensorPin1);
      sensor2Zustand = digitalRead(sensorPin2);
      //Serial.print("Sensor 1: ");Serial.print(sensor1Zustand);Serial.print("\t Sensor 2: ");Serial.println(sensor2Zustand);
      int i;
      if ((sensor1Zustand == 1) && (sensor2Zustand == 1)) { // Gleis leer
        if ((sensor1ZustandAlt == 0) || (sensor2ZustandAlt == 0)) { // Vorher Gleis besetzt
          i = random(anzeigeAnzahl);
          drawInfo(i);
          verspaetung = random(2);
        }
      }
      if ((verspaetung > 0) && (i != 0)) {
        if (tickTime <= millis()) {
          tickTime = millis() + 30;
          oled.setInvertMode(1);
          int8_t rtn = oled.tickerTick(&state);
          if (rtn <= RTN_CHECK) {
            oled.tickerText(&state, hinweis[(tickerPosition++) % 3]);
          }
        }
      }
      sensor1ZustandAlt = sensor1Zustand;
      sensor2ZustandAlt = sensor2Zustand;
    }
    
    void anzeigeTafelAutomatisch() {
      int i;
      if (anzeigeTimer + anzeigenWechselMin + anzeigenwechselVariabeleZeitHilfsvariable < millis()) { // der zweite Teil verhindert, dass ein Anzeigewechsel dem Empfang des Zeitsignals blockiert
        anzeigeTimer = millis();
        i = random(anzeigeAnzahl);
        drawInfo(i);
        verspaetung = random(2);
        anzeigenwechselVariabeleZeitHilfsvariable = random(anzeigenwechselVariabeleZeit);
      }
      if ((verspaetung > 0) && (i != 0)) {
        if (tickTime <= millis()) {
          tickTime = millis() + 30;
          oled.setInvertMode(1);
          int8_t rtn = oled.tickerTick(&state);
          if (rtn <= RTN_CHECK) {
            oled.tickerText(&state, hinweis[(tickerPosition++) % 3]);
          }
        }
      }
    }
    
    void drawInfo(int i) {      // OLED Ausgabe
      oled.clear();
      oled.setInvertMode(0);
      oled.setCursor(0 , 0);
      oled.setFont(Callibri15);
      oled.println(textSegments[i][0]);
      oled.clearToEOL();
      oled.setCursor(104 , 0);
      oled.setFont(Callibri10);
      oled.println(makeTime());
      oled.clearToEOL();
      oled.setFont(Callibri10);
      oled.setCursor(27 , 1);
      oled.println(textSegments[i][1]);
      oled.setFont(Callibri14);
      oled.setCursor(27 , 2);
      oled.println(textSegments[i][2]);
      oled.setFont(Callibri10);
      oled.setCursor(0 , 5);
      oled.println(makeTime1());
      oled.setCursor(0 , 6);
      oled.println(makeTime2());
      oled.setCursor(27 , 5);
      oled.println(textSegments[i][3]);
      oled.setCursor(27 , 6);
      oled.println(textSegments[i][4]);
      oled.setCursor(54 , 5);
      oled.println(textSegments[i][5]);
      oled.setCursor(54 , 6);
      oled.println(textSegments[i][6]);
    }
    
    String makeTime() {
      String myTimeString = "";
      int myHoursSub = myTime;
      int myMinutesSub = myMinutes;
      if (myHoursSub < 10) myTimeString = " " + String(myHoursSub);
      else myTimeString = String(myHoursSub);
      if (myMinutesSub < 10) myTimeString += ":0" + String(myMinutesSub);
      else myTimeString += ":" + String(myMinutesSub);
      return myTimeString;
    }
    
    String makeTime1() {
      // Nächster Zug
      String myTimeString = "";
      int myHoursSub = myTime;
      int myMinutesSub = myMinutes;
      //int myMinutesSub1=random(30);
      if (myMinutesSub > 29) {
        if (myHoursSub > 22) myHoursSub = 0;
        else myHoursSub++;
      } else {
        myMinutesSub += 30;
      }
      if (myHoursSub < 10) myTimeString = " " + String(myHoursSub);
      else myTimeString = String(myHoursSub);
      if (myMinutesSub < 10) myTimeString += ":0" + String(myMinutesSub);
      else myTimeString += ":" + String(myMinutesSub);
      return myTimeString;
    }
    
    String makeTime2() {
      // Übernächster Zug
      String myTimeString = "";
      int myHoursSub = myTime;
      int myMinutesSub = myMinutes;
      if (myHoursSub >= 23) myHoursSub = 0;
      else myHoursSub++;
      if (myHoursSub < 10) myTimeString = " " + String(myHoursSub);
      else myTimeString = String(myHoursSub);
      if (myMinutesSub < 10) myTimeString += ":0" + String(myMinutesSub);
      else myTimeString += ":" + String(myMinutesSub);
      return myTimeString;
    }
    
    void leuchtstoffroehrenEin() {
      for (int i = 0; i < 9; i++) {
        if (random(flackerzeitLeuchten) == 0) leuchtstoffroehrenZustand[i] = 0;
        if (leuchtstoffroehrenZustand[i] != 0) { // wenn die Röhre nicht eingeschaltet ist
          if (leuchtstoffroehrenZustand[i] + leuchtstoffroehrenTimer[i] < millis()) {
            leuchtstoffroehrenZustand[i] = random(flackerGeschwindigkeit) + 20; // erzeugt eine Timeout-Variable
            leuchtstoffroehrenTimer[i] = millis();
            int myOutput = random(2);
            digitalWrite(leuchtstoffroehrenPins[i], myOutput);
          }
        } else {
          digitalWrite(leuchtstoffroehrenPins[i], 0);
        }
      }
    }
    
    void leuchtstoffroehrenAus() {
      for (int i = 0; i < 9; i++) {
        leuchtstoffroehrenZustand[i] = 1;
        digitalWrite(leuchtstoffroehrenPins[i], HIGH);
      }
      /*if (random(ausschaltWahrscheinlichkeit) == 1) {   //  Einschalten der Leuchtstoffröhren per Zufall
        int thePin = random(10);
        digitalWrite(leuchtstoffroehrenPins[thePin], HIGH);
        leuchtstoffroehrenZustand[thePin] = 0;
        }*/
    }
    
    void soundAn() {
      switch (soundState) {
        case 0:
          Serial.println("soundTimer 0");
          soundRandom = random(mp3Wahrscheinlichkeit);
          if (soundRandom < 1) {
            soundState = 1;
            theSound = random(mp3Anzahl) + 1;
            soundTimer = millis();
            soundTimeout = mp3Dauer[theSound - 1] * 1000;
            Serial.print("Playsound: \t\t\t"); Serial.print(theSound); Serial.print("\t\t\t"); Serial.println(soundTimeout);
            myDFPlayer.playFolder(1, theSound); //play specific mp3 in SD:/15/004.mp3; Folder Name(1~99); File Name(1~255)
            soundPlaying = true;
          } else {
            soundTimer = millis();
            soundTimeout = 500;
            soundState = 1;
          }
          break;
        case 1:
          if (soundTimer + soundTimeout < millis()) {
            soundPlaying = false;
            soundState = 0;
          }
          break;
      }
    }
    
    void soundAus() {
      if (soundPlaying == true) {
        Serial.println(soundPlaying);
        myDFPlayer.pause();
        soundPlaying = false;
      }
    }
     
    void receiveFunction() {                      // Empfängt die Uhrzeit vom Control-Modul
      receivePulse = digitalRead(receivePin);     // Lies den Empfangspin aus
      if ((receiveTimer + receiveTimeout < millis()) && (receiveStarted == true)) {
        // Bei Timeout und aktivem Empfang
        receiveStarted = false;                   // beende aktiven Empfang
        myTime = receivedTime - 1;                // speichere die empfangene Zeit
        receivedTime = 0;                         // setze die Hilfsvariable zum Zeitempfang zurück
        timeToHour = millis() - lastTimeSignal;
        lastTimeSignal = millis();
      }
      // falls ein Puls am Empfangspin erfasst wird, der vorher nicht da war
      if ((receivePulse == 0) && (lastReceivePulse == 1)) {
        receiveTimer = millis();                  // starte Timer neu
        if (receiveStarted == false) receiveStarted = true;  // starte aktiven Empfang, wenn noch nicht geschehen
        receivedTime++;                           // es gab einen Puls, also erhöhe die Hilfsvariable zum Zeitempfang
      }
      lastReceivePulse = receivePulse;            // aktuellen Zustand am Pin für nächsten Durchlauf merken
      if (receiveStarted == false) {
        if (millis() % 100 < 2) {
          int myNewMinutes = map(millis() - lastTimeSignal, 0, timeToHour, 0, 59);
          myNewMinutes = constrain(myNewMinutes, 0, 59);
          if (myNewMinutes != myMinutes) {
            Serial.print(myTime); Serial.print(":"); Serial.print(myMinutes);
            Serial.print("\t"); Serial.println(myTime);
          }
          myMinutes = myNewMinutes;
        }
      }
    }

    Wenn dir das Projekt gefallen hat und du von weiteren interessanten Projekten inspiriert werden willst, sieh dir doch mal mein neues E-Book »Arduino Projekte Volume 1« an!

    • Die beliebtesten Arduino-Projekte von StartHardware
    • Inklusive Schaltplan, Beschreibung und Code
    • Arduino-Schnellstart-Kapitel
    • Kompakter Programmierkurs


    27 Gedanken zu „RailFX: Arduino Bahnhof“

    1. Hallo,
      kurze Nachfrage, bin in der Welt von Adruino und Programmieren noch ein Anfänger, aber besteht die Möglichkeit den freien A ( 0 ) oder A ( 2 ) für einen Taster oder Schalter zu verwenden? Und mit dieser Option Lichtschranke und Taster oder Schalter einen bestimmten Sound abzuspielen?
      Mit freundlichen Grüßen
      Martin

      1. Hi Martin, ja klar, das geht schon. Die analogen Inputs kann man auch als digitale Pins verwenden. A0 wäre dann Pin 14, A1 wäre Pin 15 usw. Liebe Grüße Stefan

        1. Hallo Stefan,
          danke für die Info, dann wäre ja somit eine “kleine Personalisierung ” für eine Gleis 1 oder X möglich, mit einem Sound-File.
          Denn ich habe bei meinem Eigenbau Bremsmodulen noch einen Schaltkontakt (Schließer) frei, und wenn der aktive wäre könnte der Sound X abgespielt wären.
          Gruß
          Martin

          1. Hallo Stefan,
            kurzer Nachtrag, Ihre “Sound Machine mit Arduino” wäre eigentlich schon die Lösung, man müsste nur die Eingänge vom Taster gegen ein Schalter Signal ändern?
            Gruß
            Martin

    2. Moin Stefan, habe das Rail fx system schon auf der neuen spur z platte in Angriff genommen, meine Frage kann man die lichtschranken vom bahnhofsmodul an 2 arduino anschließen wollte noch eine Geschwindigkeitmessstrecke im Tunnel verbauen und etwas Material einsparen Grüße Michel

      1. Hi Michel, das weiß ich nicht genau. Solange du alle GNDs verbindest, könnte es klappen. Wäre es aber nicht einfacher, die Geschwindigkeitsmessung zum RailFX Modul hinzuzufügen? Liebe Grüße Stefan

    Schreibe einen Kommentar

    Deine E-Mail-Adresse wird nicht veröffentlicht.

     

    Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.