Arduino RailFX Raumbeleuchtung RGB RGBW Strip Modellbahn

RailFX-Raumbeleuchtung: Tag und Nacht für die Modellbahn

Dieses Modul des RailFX-Systems steuert die Raumbeleuchtung der Modellbahn-Anlage. Dazu wird ein RGBW-LED-Strip als Lichtquelle verwendet. Natürlich ist auch dieses Modul vom Miniatur-Wunderland inspiriert :-)

Schaltplan

RailFX-Raumbeleuchtung Modellbahn Modellbau Lichtsystem Arduino RGB RGBW

Der LED-Strip besteht aus vier Parallelschaltungen von LEDs (Rot, Grün, Blau, Weiß). Bei meinem Strip sind Rot, Grün und Blau in einem LED-Gehäuse zusammengefasst, während die weiße LED ein Extra-Bauteil ist. Alle LEDs teilen sich die Anode (Plus-Pol). Man nennt sie Common-Anode (gemeinsame Anode).

Beim Kauf muss man also auf den Verbindungsstellen der LED-Stemente irgendwo einen Hinweis finden, z.B. ein +, ein 5V+ oder ein 12V+.


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


Arduino RGBW-LED Strip Common Anode

Mein LED-Strip hatte Female-Pinheader als Anschluss, die sehr leicht mit Patch-Kabeln verbinden ließen.

Wie im Schaltplan zu sehen, muss der GND des externen Netzteils mit dem GND des Arduino-Boards verbunden werden. Der Plus darf dagegen nur mit dem LED-Strip verbunden werden!

Gesteuert werden die LEDs nun durch N-Channel MOS-FET-Transistoren. Ich verwende hierfür die IRF630N Transistoren. Sie benötigen im Gegensatz zu normalen Transistoren keine Vorwiderstände. Die Beinchen heißen Gate, Drain und Source. Der Source-Anschluss wird mit dem GND verbunden. Der Drain-Anschluss ist mit der jeweiligen LED-Farbe verbunden und würd über das Gate gesteuert. Das Gate ist mit den PWM-Pins des Arduino-Nano-Boards verbunden (D6 – Blau, D9 – Grün, D10 – Rot, D11 – Weiß).

Achtung: Am Pin A4 ist wird das Control-Signal des RailFX Control-Moduls angelegt. Es steuert die Tageszeit und ist zwingend erforderlich.

Bauteile

Einstellungen im Code

Es werden vier Phasen des Raumlichts durchlaufen: Sonnenaufgang, Tag, Sonnenuntergang, Nacht. Im Code lassen sich mehrere Einstellungen vornehmen. Diese sind in dem Code-Abschnitt näher erläutert. Es handelt sich um die Lichtfarben der jeweiligen Phasen und die Geschwindigkeit des Übergangs (frameSpeed).

/* ***** ***** Einstellungen ***** ***** */
int frameSpeed = 100;                    // Verzögerung der Lichtübergänge (je höher, je langsamer)
float lichtFarben[4][4] = {
  {200.0, 50.0, 0.0, 0.0},               // Sonnenaufgang
  {0.0 , 0.0 , 0.0, 255.0},              // Tag
  {150.0, 0.0, 60.0, 50.0},              // Sonnenuntergang
  {0.0 , 0.0 , 60.0, 0.0}                // Nacht
};

Beim Upload muss man darauf achten, dass das richtige Board im Arduino-Menü ausgewählt ist. Dazu muss ebenfalls im Werkzeugemenü im Unterpunkt Prozessor »ATmega328P (Old Bootlaoder)« ausgewählt sein.

Der folgende Programmcode kann mit den oben erwähnten Änderungen einfach kopiert und auf das Arduino-Nano geladen werden.

Code für das Modul: RailFX-Raumbeleuchtung

/*
    Rail-FX Raumbeleuchtung
    StartHardware.org
*/

/* ***** ***** Einstellungen ***** ***** ***** *****  ***** ***** ***** *****  ***** ***** ***** ***** */

int frameSpeed = 100;                    // Verzögerung der Lichtübergänge (je höher, je langsamer)
float lichtFarben[4][4] = {
  {200.0, 50.0, 0.0, 0.0},               // Sonnenaufgang
  {0.0 , 0.0 , 0.0, 255.0},              // Tag
  {150.0, 0.0, 60.0, 50.0},              // Sonnenuntergang
  {0.0 , 0.0 , 60.0, 0.0}                // Nacht
};

/* ***** ***** Ab hier beginnt der Programmcode, der nicht angepasst werden muss ***** ***** ***** ***** */

int bluePin = 6;                         // an diesem Pin ist der blaue Kanal der RGBW-LEDs angeschlossen
int greenPin = 9;                        // an diesem Pin ist der grüne Kanal der RGBW-LEDs angeschlossen
int redPin = 10;                         // an diesem Pin ist der rote Kanal der RGBW-LEDs angeschlossen
int whitePin = 11;                       // an diesem Pin ist der weiße Kanal der RGBW-LEDs angeschlossen

/* Variablen für Lichtfarben*/
float aktuelleFarbe[4];
float farbSchritte[4][4];
int samples = 255;

int frameNumber = 0;
long frameTimer = 0;

boolean transitionDone = false;

int phase = 3;

/* 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 = 18;
int myTime = 23;
int myOldTime = 0;

#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

  for (int i = 0; i < 4; i++) {
    if (phase != 3) {
      if (lichtFarben[phase][i] < lichtFarben[phase + 1][i]) {
        farbSchritte[phase][i] = (lichtFarben[phase + 1][i] - lichtFarben[phase][i]) / 255;
      } else if (lichtFarben[phase][i] > lichtFarben[phase + 1][i]) {
        farbSchritte[phase][i] = (lichtFarben[phase][i] - lichtFarben[phase + 1][i]) / -255;
      }
    } else {
      if (lichtFarben[phase][i] < lichtFarben[0][i]) {
        farbSchritte[phase][i] = (lichtFarben[0][i] - lichtFarben[phase][i]) / 255;
      } else if (lichtFarben[phase][i] > lichtFarben[0][i]) {
        farbSchritte[phase][i] = (lichtFarben[phase][i] - lichtFarben[0][i]) / -255;
      }

    }
    Serial.println(farbSchritte[phase][i]);
  }
}

void loop() {
  receiveFunction();                    // Führe Anweisungen für Empfang aus
  if (receiveStarted == false) {        // Falls gerade keine Daten empfangen werden:
    if (myTime == 20) {                 // ***** Sonnenuntergang *****
      if (myOldTime != myTime) {        // wenn die Stunde umschaltet
        phase = 1;                      // setzt Übergangsphase
        transitionDone = false;         // Übergangsphase wird ausgeführt
        Serial.println("Sonnenuntergang");
      }
    } else if (myTime == 6) {           // ***** Sonnenaufgang *****
      if (myOldTime != myTime) {        // wenn die Stunde umschaltet
        phase = 3;                      // setzt Übergangsphase
        transitionDone = false;         // Übergangsphase wird ausgeführt
        Serial.println("Sonnenaufgang");
      }
    }
  }

  if ((frameTimer + frameSpeed < millis()) && (transitionDone == false)) {

    for (int i = 0; i < 4; i++) {
      if (phase != 3) {
        aktuelleFarbe[i] = map(frameNumber, 0, 255, lichtFarben[phase][i], lichtFarben[phase + 1][i]);
      } else {
        aktuelleFarbe[i] = map(frameNumber, 0, 255, lichtFarben[phase][i], lichtFarben[0][i]);
      }
    }

    frameNumber++;
    if (frameNumber > samples) {
      frameNumber = 0; 
      if (phase == 3) {                       // Automatischer Übergang von Sonnenaufgang zu Tag
        phase = 0;
      } else if (phase == 1) {                // Automatischer Übergang von Sonnenuntergang zu Nacht
        phase = 2;
      } else {
        transitionDone = true;
      }
    }
    frameTimer = millis();
  }

  analogWrite(redPin, aktuelleFarbe[0]);      // Setzen der LED-Farbe
  analogWrite(greenPin, aktuelleFarbe[1]);    // Setzen der LED-Farbe
  analogWrite(bluePin, aktuelleFarbe[2]);     // Setzen der LED-Farbe
  analogWrite(whitePin, aktuelleFarbe[3]);    // Setzen der LED-Farbe

  myOldTime = myTime;
}

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
    Serial.println(myTime);                   // serielle Ausgabe
  }
  // 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
}


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


8 Gedanken zu „RailFX-Raumbeleuchtung: Tag und Nacht für die Modellbahn“

  1. Volker Tschirner

    Hallo Stefan, Schaltung läuft. Ich habe nur sehr lange daran gesessen, da Deine Schaltung falsch ist. Ich hatte erst Die Vermutung, dass das Programm falsch war, es ist aber die Schaltung. Ich habe mich entschlossen nur rot und weiß einzustellen, das kommt der Eisenbahn in Hamburg am nähesten.
    Gruß Volker

    1. Hi Volker,

      das ist ja merkwürdig. Ich hab die Schaltung gerade noch mal mit meiner abgeglichen und sie sind gleich. Die Schaltung vor mir läuft einwandfrei. Welche Transistoren hast du verwendet? Manchmal sind die unterschiedlich gedrahtet. Ich würde der Sache gern auf den Grund gehen.

      Liebe Grüße

      Stefan

      1. Volker Tschirner

        Hallo Stefan, wenn Du auf den Plan schaust, sind die Ausgänge D6, D9, D10 und D11 belegt. Dies stimmt aber nicht mit Deiner Schaltung überein. zusätzlich musste ich bei meinem Strip (den, den Du empfohlen hast) die Farben grün und blau tauschen.
        Dies ist zwar Peanuts zur Qualität der Schaltung, aber vielleicht hilft das diese Schaltung besser nach zu bauen.
        Gruß Volker

        1. Hi Volker, danke für die Info! Das hilft mir echt weiter. Die Pins sind tatsächlich durcheinander gekommen. Ich hab das jetzt in der Grafik angepasst. Klar, man braucht für das Dimmen natürlich PWM-Pins. Die Farbbelegung der Pins ist übrigens von Strip zu Strip unterschiedlich und die ändern sich selbst beim gleichen Produkt manchmal. Das kann man wahrscheinlich schnell im Code tauschen:

          int bluePin = 6; // an diesem Pin ist der blaue Kanal der RGBW-LEDs angeschlossen
          int greenPin = 9; // an diesem Pin ist der grüne Kanal der RGBW-LEDs angeschlossen
          int redPin = 10; // an diesem Pin ist der rote Kanal der RGBW-LEDs angeschlossen
          int whitePin = 11; // an diesem Pin ist der weiße Kanal der RGBW-LEDs angeschlossen

          Also, vielen Dank nochmal und hab ein schönes Wochenende. Liebe Grüße Stefan

      2. Volker Tschirner

        Hallo Stefan, ich bin begeistert, dass Du meine Anregung angenommen hast.. Teile sind bestellt und Ende der Woche werde ich das Ergebnis sehen.
        Das Einzige was jetzt noch fehlt ist eine Bahnsteig bzw. Busbahnhofanzeige mit einem 0.96 Oled Display. Ich habe dies schon mal programmiert, wenn da aber noch Leben reinkommen würde über da Controlmodul, wäre das der Hammer. Spreche ich Dich damit an?

          1. Volker Tschirner

            Hallo Stefan, wie geil ist das denn? Perfekt, Teile sind bestellt und wird sofort ausprobiert. Super, ich freue mich.
            Gruß Volker

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.