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. 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 herunter geladen 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[] = {
  "Auf Grund 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 = 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);

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
  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)) {  // 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

  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(sensor1Zustand);Serial.print("\t");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:
      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()) {
        myDFPlayer.pause();
        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


7 Gedanken zu „RailFX: Arduino Bahnhof“

  1. Volker Tschirner

    Hallo Stefan, ich bin jetzt bei dem Bahnhof bei und finde die Datei “SSD1306AsciiWire.h” nicht. Kannst Du mir sagen wo ich die finde?
    Eine Frage zur Schaltung, ist es nicht möglich die Anzeige über einen externen Kontakt weiter zu schalten? Immer wenn ein Zug den Bahnhof verlässt, schaltet er einen weiter? Kannst Du mir da einen Tipp geben?

  2. Hi Volker, die Datei SSD1306AsciiWire.h ist eine Bibliothek, die eingebunden werden muss. Oben unter dem Punkt Libraries hab ich beschrieben, wie das geht. Hast du das schon probiert? Das mit dem Kontakt ist eine gute Idee. Ich würde das mit den Sensoren aus dem Bahnübergangsmodul machen: https://starthardware.org/railfx-bahnuebergang/ Ich werd die Tage mal eine Version damit entwickeln. Danke für die Anregung.

    Liebe Grüße Stefan

    1. Volker Tschirner

      Ich bin gespannt auf die Neuerung. Der Sensor ist perfekt!!
      Das habe ich gemacht, aber ich finde die Bibliothek nicht, alle anderen sind da. Es geht trotzdem, finde ich nur komisch.
      Gruß Volker

      1. volker Tschirner

        Ich habe noch einen Nachtrag, vielleicht kann mit einem zweiten Sensor noch bei der Einfahrt ertönen lassen “Bitte zurücktreten von der Bahnsteigkante, Achtung bei Einfahrt des Zuges” oder so.
        Gruß Volker

  3. Volker Tschirner

    Halo Stefan, kannst Du mir eine Bezugsquelle für Modellbahnsounds in de Qualität wie Du sie hier zum Download bereitstellt nennen? Auch für die Deine Einsatzstelle finde ich nur Blechdosensounds. Bin auch gern bereits dafür zu bezahlen.

  4. Erst einmal vielen Dank für das tolle Projekt. Ich bin zwar kein Modelleisenbahnbauer, suchte aber ein Geburtstagsgeschenk für einen Freund und wurde hier fündig.
    Ich glaube, dass sich bei der Erweiterung für die Lichtschranken im Fritzing ein Fehler eingeschlichen hat.
    Für mich sieht es so aus, als ob die Lichtschranken an A2 und A1 angeschlossen sind.
    Im Code werden die Pins A1 und A0 verwendet.

    1. Hi Ralf, vielen Dank für den Hinweis! Da war tatsächlich noch ein Fehler drin. Ich hab es im Code geändert :-) Jetzt sollte es funktionieren.
      Liebe Grüße
      Stefan

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

 

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