Zum Inhalt springen
Arduino Projekt Leuchtturm Leuchtfeuer Tonne Modellbahn

Leuchtturm und Leuchttonnen mit Arduino

Ich hab eine Nutzerfrage von Falk bekommen. Wie kann man eine LED ein- und ausfaden, während gleichzeitig zwei andere LEDs in unterschiedlichen Geschwindigkeiten blinken? In diesem Projekt geht es darum, einen Leuchtturm und zwei Leuchttonnen für eine Modelleisenbahn zu betreiben. Man nennt diese Signale in der Seefahrt übrigens Befeuerung. Sehen wir uns das genauer an.

Bauteile

Schaltplan

Die Schaltung besteht aus der Teilschaltungen, die sich jeweils aus einem Vorwiderstand von 220 Ohm (rot-rot-braun, bzw. rot-rot-schwarz-schwarz) und einer LED zusammensetzen.

Code: Leuchtturm und Leuchttonnen mit Arduino

Sehen wir uns erst einmal den Code für eine einzelne LED an. Zuerst müssen wir doch eine ganze Menge an Hilfsvariablen deklarieren. Neben dem Pin, an dem die LED angeschlossen ist, legen wir das Array led1Timeout an. Es speichert die Dauer der einzelnen Leuchtphasen. Die erste Phase soll 500, die zweite 1000 Millisekunden dauern. Die Phasen repräsentieren abwechselnd leuchten und nicht leuchten. Da es in der Arduino-Sprache C keine Methode gibt, um die Länge eines Arrays zuverlässig zu erfragen, legen wir eine Variable an, die die Länge des Arrays speichert: led1Phases.


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


Die Variable led1Phase speichert die aktuelle Phase der LED, d.h. also in diesem Fall entweder 0 oder 1. Die Variable led1State wird bei jedem Phasenwechsel umgekehrt und im späteren Programmverlauf verwendet, um die LED ein- oder auszuschalten. Als letzte Variable benötigen wir led1Timer. Sie wird für die Timer-Funktion benötigt. Was Timer funktionieren habe ich hier für dich zusammengefasst: Timer mit Arduino – Alternative zu Delays.

int led1Pin = 2;                  // LED Pin für Tonne 1 (rote LED)
int led1Timeout[] = {500,1000};   // Phasendauer Led 1
int led1Phases = 2;               // speichert die Anzahl der Phasen
int led1Phase = 0;                // aktuelle Phase der LED 
int led1State = 1;                // LED Zustand 1 = an, -1 = aus
long led1Timer = 0;               // LED timer 

In der setup()-Methode konfigurieren wir den led1Pin als OUTPUT und starten den Timer.

void setup() {
  pinMode(led1Pin, OUTPUT);   // Pin wird als Output deklariert
  led1Timer = millis();       // Start des Timers
}

Im Loop prüfen wir erstmal den Timer. Wenn er abgelaufen ist, wird die Phase der LED erhöht: led1Phase++. Nun müssen wir prüfen, ob es überhaupt so viele LED-Phasen gibt. Wenn nicht, wird led1Phase auf 0 gesetzt. Die Variable led1State wird mit -1 multipliziert, was zu einer Wertumkehrung führt. Diese nutzen wir, um die LED ein- oder auszuschalten, je nachdem, ob led1State größer oder kleiner 0 ist.

void loop() {
  // LED 1 Handling
  if (millis()>led1Timer+led1Timeout[led1Phase]){     // prüft den Timer
      led1Phase++;                                    // erhöht die Leuchtphase um 1
      if (led1Phase>led1Phases-1){                    // falls Leuchtphasenmaximum überschritten
        led1Phase = 0;                                // Leuchtphase zurücksetzen
      }
      led1Timer = millis();                           // Timer resetten
      led1State *= (-1);                              // LED Zustand wird umgekehrt 
      if (led1State>0) digitalWrite(led1Pin, HIGH);   // wenn LED Zustand > 0, schalte LED ein
      else digitalWrite(led1Pin, LOW);                // wenn LED Zustand < 0, schalte LED aus
  }

  delay(20);                                          // kurze Pause
}

Hier nochmal der zusammenhängende Code für eine LED:

int led1Pin = 2;        // LED Pin für Tonne 1 (rote LED)
int led1Timeout[] = {500,1000};                  //  Phasendauer Led 1
int led1Phases = 2;     // speichert die Anzahl der Phasen
int led1Phase = 0;      // Aktuelle Phase der LED 
int led1State = 1;      // LED Zustand 1 = an, -1 = aus
long led1Timer = 0;     // LED timer 

void setup() {
  Serial.begin(115200);
  pinMode(led1Pin, OUTPUT);   // Pin wird als Output deklariert
  led1Timer = millis();       // Start des Timers
}

void loop() {
  // LED 1 Handling
  if (millis()>led1Timer+led1Timeout[led1Phase]){     // prüft den Timer
      led1Phase++;                                    // erhöht die Leuchtphase um 1
      if (led1Phase>led1Phases-1){                    // falls Leuchtphasenmaximum überschritten
        led1Phase = 0;                                // Leuchtphase zurücksetzen
      }
      led1Timer = millis();                           // Timer resetten
      led1State *= (-1);                              // LED Zustand wird umgekehrt 
      if (led1State>0) digitalWrite(led1Pin, HIGH);   // wenn LED Zustand > 0, schalte LED ein
      else digitalWrite(led1Pin, LOW);                // wenn LED Zustand < 0, schalte LED aus
  }

  delay(20);                                          // kurze Pause
}

Damit haben wir erstmal eine sehr komplizierte Version des Arduino-Blink-Beispiels erschaffen. Es ermöglicht uns aber, durch copy&paste mehr LEDs in unterschiedlichen Intervallen blinken zu lassen. Der folgende Code umfasst zwei unterschiedlich blinkende LEDs und eine ein- und ausfadende LED. Die fadende LED ist das Signalfeuer des Leuchtturms, die beiden blinkenden LEDs die der Tonnen.

int led1Pin = 2;        // LED Pin für Tonne 1 (rote LED)
int led2Pin = 3;        // LED Pin für Tonne 2 (grüne LED)
int led3Pin = 5;        // LED Pin für Leuchtturm

int led1Timeout[] = {500,1000};                  //  Phasendauer Led 1
int led2Timeout[] = {100,200,100,1500};          //  Phasendauer Led 2
int led3Timeout[] = {500,500,1500};              //  Phasendauer Led 3

int led1Phases = 2;     // speichert die Anzahl der Phasen
int led2Phases = 4;     // speichert die Anzahl der Phasen
int led3Phases = 3;     // speichert die Anzahl der Phasen

int led1Phase = 0;      // Aktuelle Phase der LED 
int led2Phase = 0;      // Aktuelle Phase der LED 
int led3Phase = 0;      // Aktuelle Phase der LED 

int led1State = 1;      // LED Zustand 1 = an, -1 = aus
int led2State = 1;      // LED Zustand 1 = an, -1 = aus
int led3State = 0;      // LED Zustand von 0 - 255 = Leuchtstärke

long led1Timer = 0;     // LED timer 
long led2Timer = 0;     // LED timer 
long led3Timer = 0;     // LED timer 

void setup() {
  Serial.begin(115200);
  pinMode(led1Pin, OUTPUT);   // Pin wird als Output deklariert
  pinMode(led2Pin, OUTPUT);   // Pin wird als Output deklariert
  led1Timer = millis();       // Start des Timers
  led2Timer = millis();       // Start des Timers
}

void loop() {
  // LED 1 Handling
  if (millis()>led1Timer+led1Timeout[led1Phase]){     // prüft den Timer
      led1Phase++;                                    // erhöht die Leuchtphase um 1
      if (led1Phase>led1Phases-1){                    // falls Leuchtphasenmaximum überschritten
        led1Phase = 0;                                // Leuchtphase zurücksetzen
      }
      led1Timer = millis();                           // Timer resetten
      led1State *= (-1);                              // LED Zustand wird umgekehrt 
      if (led1State>0) digitalWrite(led1Pin, HIGH);   // wenn LED Zustand > 0, schalte LED ein
      else digitalWrite(led1Pin, LOW);                // wenn LED Zustand < 0, schalte LED aus
  }

  // LED 2 Handling
  if (millis()>led2Timer+led2Timeout[led2Phase]){     // prüft den Timer
      led2Phase++;                                    // erhöht die Leuchtphase um 1
      if (led2Phase>led2Phases-1){                    // falls Leuchtphasenmaximum überschritten
        led2Phase = 0;                                // Leuchtphase zurücksetzen
      }
      led2Timer = millis();                           // Timer resetten
      led2State *= (-1);                              // LED Zustand wird umgekehrt 
      if (led2State>0) digitalWrite(led2Pin, HIGH);   // wenn LED Zustand > 0, schalte LED ein
      else digitalWrite(led2Pin, LOW);                // wenn LED Zustand < 0, schalte LED aus
  }

  // LED 3 Handling Fading
  if (millis()>led3Timer+led3Timeout[led3Phase]){     // prüft den Timer
      led3Phase++;                                    // erhöht die Leuchtphase um 1
      if (led3Phase>led3Phases-1){                    // falls Leuchtphasenmaximum überschritten
        led3Phase = 0;                                // Leuchtphase zurücksetzen
      }
      led3Timer = millis();                           // Timer resetten
  }

  if (led3Phase==0) {                                 // wenn led3State == 0, dann einfaden
    analogWrite(led3Pin, map(millis()-led3Timer,0,led3Timeout[0],0,255));
  } else if (led3Phase==1) {                          // wenn led3State == 1, dann ausfaden
    analogWrite(led3Pin, 255-map(millis()-led3Timer,0,led3Timeout[0],0,255));
  } else if (led3Phase==2){                           // wenn led3State == 1, dann ausschalten
    analogWrite(led3Pin, 0);  
  }

  delay(20);                                          // kurze Pause
}

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


5 1 vote
Article Rating
Abonnieren
Benachrichtige mich bei

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

7 Comments
Newest
Oldest Most Voted
Inline Feedbacks
Alle Kommentare anzeigen
Heinz Riechmann
6 Monate zuvor

Hi Stefan,

vielen lieben Dank für diesen sehr umfangreichen und dennoch verständlichen Script, den ich für meinen „Rote Sand Leuchtturm” ein wenig abgeändert habe. Ich benutze einen WATTUINO NANITE 85 mit Bootloader. Die blinkende weiße LED (1250-1250-1250-4000ms) wird von PinPB0 direkt angesteuert; über PinPB1 steuere ich die Basis eines NPN-237B (5000-10000) an als zusätzlichen 70mA-Verbrenner für meine Powerbank, damit diese sich nicht immer wieder nach 30sec abschaltet. Es funktioniert alles im Dauerbetrieb, so wie ich es mir gewünscht habe. Nochmals Danke.

Eine letzte Frage hätte ich jedoch noch: Wozu dient das am Ende stehende delay(20)//kurze Pause?
Ist diese Pause zwingende notwendig?

Stephan Götz
3 Jahre zuvor

Guten Tag allerseits,

Gibt es die Möglichkeit den vollständigen Code zu erhalten.

Grüße

Stephan Götz
Antworte an  Stefan Hermann
3 Jahre zuvor

Hi Stefan,

Ich hab das jetzt mal in die Software kopiert! leider gibt es in Zeile 26 eine Fehlermeldung. Ich verwende einen Nano, da ich unzählige rumliegen habe…

int led1Pin = 2; // LED Pin für Tonne 1 (rote LED)
int led1Timeout[] = {500,1000}; // Phasendauer Led 1
int led1Phases = 2; // speichert die Anzahl der Phasen
int led1Phase = 0; // aktuelle Phase der LED
int led1State = 1; // LED Zustand 1 = an, -1 = aus
long led1Timer = 0; // LED timer
void setup() {
pinMode(led1Pin, OUTPUT); // Pin wird als Output deklariert
led1Timer = millis(); // Start des Timers
}
void loop() {
// LED 1 Handling
if (millis()>led1Timer+led1Timeout[led1Phase]){ // prüft den Timer
led1Phase++; // erhöht die Leuchtphase um 1
if (led1Phase>led1Phases-1){ // falls Leuchtphasenmaximum überschritten
led1Phase = 0; // Leuchtphase zurücksetzen
}
led1Timer = millis(); // Timer resetten
led1State *= (-1); // LED Zustand wird umgekehrt
if (led1State>0) digitalWrite(led1Pin, HIGH); // wenn LED Zustand > 0, schalte LED ein
else digitalWrite(led1Pin, LOW); // wenn LED Zustand led1Timer+led1Timeout[led1Phase]){ // prüft den Timer
led1Phase++; // erhöht die Leuchtphase um 1
if (led1Phase>led1Phases-1){ // falls Leuchtphasenmaximum überschritten
led1Phase = 0; // Leuchtphase zurücksetzen
}
led1Timer = millis(); // Timer resetten
led1State *= (-1); // LED Zustand wird umgekehrt
if (led1State>0) digitalWrite(led1Pin, HIGH); // wenn LED Zustand > 0, schalte LED ein
else digitalWrite(led1Pin, LOW); // wenn LED Zustand led2Timer+led2Timeout[led2Phase]){ // prüft den Timer
led2Phase++; // erhöht die Leuchtphase um 1
if (led2Phase>led2Phases-1){ // falls Leuchtphasenmaximum überschritten
led2Phase = 0; // Leuchtphase zurücksetzen
}
led2Timer = millis(); // Timer resetten
led2State *= (-1); // LED Zustand wird umgekehrt
if (led2State>0) digitalWrite(led2Pin, HIGH); // wenn LED Zustand > 0, schalte LED ein
else digitalWrite(led2Pin, LOW); // wenn LED Zustand led3Timer+led3Timeout[led3Phase]){ // prüft den Timer
led3Phase++; // erhöht die Leuchtphase um 1
if (led3Phase>led3Phases-1){ // falls Leuchtphasenmaximum überschritten
led3Phase = 0; // Leuchtphase zurücksetzen
}
led3Timer = millis(); // Timer resetten
}

if (led3Phase==0) { // wenn led3State == 0, dann einfaden
analogWrite(led3Pin, map(millis()-led3Timer,0,led3Timeout[0],0,255));
} else if (led3Phase==1) { // wenn led3State == 1, dann ausfaden
analogWrite(led3Pin, 255-map(millis()-led3Timer,0,led3Timeout[0],0,255));
} else if (led3Phase==2){ // wenn led3State == 1, dann ausschalten
analogWrite(led3Pin, 0);
}

delay(20); // kurze Pause
}

Hartmut
4 Jahre zuvor

Danke,
Ich habe von deinem Script „Leuchtturm-Tonne“ das Programmteil vom Leuchtturm für mein Programm Modellflugzeugbeleuchtung verwendet. Ich verwende dazu einen Arduino Pro Min mit zusätzlicher kleiner Verstärkerplatine. Geschaltet werden die Positionslichter (rot/grün/weiß) Landescheinwerfer, Doppelblitz an den Tragflächen und einfach Blitz an der Rumpfober- und Unterseite. Das ganze Script habe ich mir aus Programmen im Internet zusammen gesucht und zusammen gestellt. Was ich nicht geschafft habe, war ein Programmteil für ein auf- und abschwellendes Licht für das Seitenruder oben. Jetzt funktioniert alles so wie ich mir das vorstelle. Vielen Dank.
LG Hartmut

7
0
Ich würde mich über deine Meinung freuen.x
Datenschutz
Stefan Hermann, Inhaber: Stefan Hermann (Firmensitz: Deutschland), würde gerne mit externen Diensten personenbezogene Daten verarbeiten. Dies ist für die Nutzung der Website nicht notwendig, ermöglicht aber eine noch engere Interaktion mit Ihnen. Falls gewünscht, treffen Sie bitte eine Auswahl:
Datenschutz
Stefan Hermann, Inhaber: Stefan Hermann (Firmensitz: Deutschland), würde gerne mit externen Diensten personenbezogene Daten verarbeiten. Dies ist für die Nutzung der Website nicht notwendig, ermöglicht aber eine noch engere Interaktion mit Ihnen. Falls gewünscht, treffen Sie bitte eine Auswahl: