Mehrfach-Abläufe ohne delay steuern?

Hallo liebe Fachleute,

für die Beleuchtung der zahlreichen LEDs an Modell-Einsatzfahrzeugen habe ich mich seit zwei, drei Tagen intensiv mit der Ablaufsteuerung ohne delay auseinandergesetzt und unten stehenden Sketch geschrieben, der auch so funktioniert wie er soll. Ist bestimmt nicht sehr komfortabel und schlank, aber er läuft prima, freu.

Die dort implementierten Blinkfunktionen für blaulicht und rotlicht laufen parallel, jedoch mit unterschiedlicher Blinkfrequenz und Leuchtdauer, um das Ganze so realistisch wie möglich zu haben, wobei ein Sensor die unterschiedlichen Schaltzustände erkennt und umsetzt.

Nun möchte ich aber gerne noch einbauen, dass sowohl rotlicht als auch blaulicht nicht nur einmal aufblitzen, sondern sogar zwei- bis dreimal hintereinander. Die unterschiedlichen Blinkfrequenzen und dauer sollen dabei erhalten bleiben.

Also quasi so: blau - blau - blau - - - - - - - - - - blau - blau - blau - - - - - - - - - - usw.
Parallel dazu: rot-rot-----------rot-rot------------ usw.

Vor lauter Rumprobieren mit currentMillis und previousMillis seh' ich den Wald vor Bäumen nicht mehr und surfe mir schon die Finger wund – wie bekomme ich dieses Mehrfachblitzen hin?? Das muss doch auch mit den Millis-Variablen gehen, nur ich komme nicht drauf wie... :confused: Die Threads zu blinkwithoutdelay oder Wie zeitliche Abläufe ohne delay() einfach gestalten? - Deutsch - Arduino Forum und andere habe ich schon durchforstet.

Könnt Ihr mir bitte helfen? Ich hoffe, ich konnte alles so verständlich wie möglich beschreiben, auch den Sketch.

Viele Grüße Chris

// blinksketch fuer einsatzfahrzeuge modellbahn

const int sensor1Pin = A2;                    // sensor 1 pin
const int frontlichtPin = 3;                  // abblendlicht
const int ruecklichtPin = 4;                  // ruecklicht
const int bremslichtPin = 5;                  // bremslicht
const int lichtgiraffePin = 6;                // lichtgiraffe
const int strahlerPin = 7;                    // strahler
const int blaulichtPin = 8;                   // blaue blinklichter lichtleiste
const int rotlichtPin = 9;                    // rote blinklichter lichtleiste

int blaulichtState = LOW;
int rotlichtState = LOW;

int blaulichtintervalon = 80;                 // intervall ein blaulicht
int blaulichtintervaloff = 500;               // intervall aus blaulicht
int rotlichtintervalon = 75;                  // intervall ein rotlicht
int rotlichtintervaloff = 670;                // intervall aus rotlicht
   
unsigned long blaulichtpreviousMillis;        // blaulichtzaehler millis letzter
unsigned long rotlichtpreviousMillis;         // rotlichtzaehler millis letzter

int sensor1 = 230;                            // sensor 1 wert
int helligkeit = 255;                         // grundhelligkeit


void setup() {
  
   pinMode(sensor1Pin, INPUT);                // sensor 1 input
   pinMode(frontlichtPin, OUTPUT);            // scheinwerfer output an transistor 1
   pinMode(ruecklichtPin, OUTPUT);            // ruecklichter output an transistor 2
   pinMode(bremslichtPin, OUTPUT);            // bremslichter output an transistor 3
   pinMode(lichtgiraffePin, OUTPUT);          // lichtgiraffe output an transistor 4
   pinMode(strahlerPin, OUTPUT);              // strahler output
   pinMode(blaulichtPin, OUTPUT);             // blaulicht output
   pinMode(rotlichtPin, OUTPUT);              // rotlicht output

   digitalWrite(frontlichtPin, helligkeit);   // scheinwerfer immer an
   digitalWrite(ruecklichtPin, helligkeit);   // ruecklichter immer an
}


void loop() {                                         // loop auf
  
sensor1 = analogRead(sensor1Pin);                     // sensor 1 readout

  unsigned long blaulichtcurrentMillis = millis();    // blaulichtzaehler millis aktuell
  unsigned long rotlichtcurrentMillis = millis();     // rotlichtzaehler millis aktuell 
  
  if((sensor1 < 100 || sensor1 > 190) && blaulichtState == HIGH && blaulichtcurrentMillis - blaulichtpreviousMillis > blaulichtintervalon)  {
    blaulichtpreviousMillis = blaulichtcurrentMillis;
    blaulichtState = LOW;
    digitalWrite(blaulichtPin, blaulichtState);       // blaulicht einschalten
  }
  
  if((sensor1 < 100 || sensor1 > 190)  && blaulichtState == LOW && blaulichtcurrentMillis - blaulichtpreviousMillis > blaulichtintervaloff)  {
    blaulichtpreviousMillis = blaulichtcurrentMillis;
    blaulichtState = HIGH;
    digitalWrite(blaulichtPin, blaulichtState);       // blaulicht ausschalten
  }
  
  if(sensor1 < 100 && rotlichtState == HIGH && rotlichtcurrentMillis - rotlichtpreviousMillis > rotlichtintervalon)  {
    rotlichtpreviousMillis = rotlichtcurrentMillis;
    rotlichtState = LOW;
    digitalWrite(rotlichtPin, rotlichtState);         // rotlicht einschalten
  }
  
  if(sensor1 < 100 && rotlichtState == LOW && rotlichtcurrentMillis - rotlichtpreviousMillis > rotlichtintervaloff)  {
    rotlichtpreviousMillis = rotlichtcurrentMillis;
    rotlichtState = HIGH;
    digitalWrite(rotlichtPin, rotlichtState);         // rotlicht ausschalten
  }
  
  if(sensor1 > 100 && sensor1 < 190)   {              // Sensor 2.5V
    digitalWrite(bremslichtPin, HIGH);
    digitalWrite(lichtgiraffePin, LOW);
    digitalWrite(strahlerPin, HIGH);
  }
  
  if(sensor1 > 190)   {                               // Sensor 5V
    digitalWrite(bremslichtPin, LOW);
    digitalWrite(lichtgiraffePin, HIGH);
    digitalWrite(strahlerPin, HIGH);
  }
  
  if(sensor1 < 100)   {                               // Sensor 0V
    digitalWrite(bremslichtPin, HIGH);
    digitalWrite(lichtgiraffePin, LOW);
    digitalWrite(strahlerPin, LOW);
  }
}                                                     // loop zu

einsatz.ino (4.01 KB)

setze es bitte in code-tags. das symbol </> oben. kanns sonst nicht lesen...

// blinksketch fuer einsatzfahrzeuge modellbahn

const int sensor1Pin = A2;                    // sensor 1 pin
const int frontlichtPin = 3;                  // abblendlicht
const int ruecklichtPin = 4;                  // ruecklicht
const int bremslichtPin = 5;                  // bremslicht
const int lichtgiraffePin = 6;                // lichtgiraffe
const int strahlerPin = 7;                    // strahler
const int blaulichtPin = 8;                   // blaue blinklichter lichtleiste
const int rotlichtPin = 9;                    // rote blinklichter lichtleiste

int blaulichtState = LOW;
int rotlichtState = LOW;

int blaulichtintervalon = 80;                 // intervall ein blaulicht
int blaulichtintervaloff = 500;               // intervall aus blaulicht
int rotlichtintervalon = 75;                  // intervall ein rotlicht
int rotlichtintervaloff = 670;                // intervall aus rotlicht
   
unsigned long blaulichtpreviousMillis;        // blaulichtzaehler millis letzter
unsigned long rotlichtpreviousMillis;         // rotlichtzaehler millis letzter

int sensor1 = 230;                            // sensor 1 wert
int helligkeit = 255;                         // grundhelligkeit


void setup() {
  
   pinMode(sensor1Pin, INPUT);                // sensor 1 input
   pinMode(frontlichtPin, OUTPUT);            // scheinwerfer output an transistor 1
   pinMode(ruecklichtPin, OUTPUT);            // ruecklichter output an transistor 2
   pinMode(bremslichtPin, OUTPUT);            // bremslichter output an transistor 3
   pinMode(lichtgiraffePin, OUTPUT);          // lichtgiraffe output an transistor 4
   pinMode(strahlerPin, OUTPUT);              // strahler output
   pinMode(blaulichtPin, OUTPUT);             // blaulicht output
   pinMode(rotlichtPin, OUTPUT);              // rotlicht output

   digitalWrite(frontlichtPin, helligkeit);   // scheinwerfer immer an
   digitalWrite(ruecklichtPin, helligkeit);   // ruecklichter immer an
}


void loop() {                                         // loop auf
  
sensor1 = analogRead(sensor1Pin);                     // sensor 1 readout

  unsigned long blaulichtcurrentMillis = millis();    // blaulichtzaehler millis aktuell
  unsigned long rotlichtcurrentMillis = millis();     // rotlichtzaehler millis aktuell 
  
  if((sensor1 < 100 || sensor1 > 190) && blaulichtState == HIGH && blaulichtcurrentMillis - blaulichtpreviousMillis > blaulichtintervalon)  {
    blaulichtpreviousMillis = blaulichtcurrentMillis;
    blaulichtState = LOW;
    digitalWrite(blaulichtPin, blaulichtState);       // blaulicht einschalten
  }
  
  if((sensor1 < 100 || sensor1 > 190)  && blaulichtState == LOW && blaulichtcurrentMillis - blaulichtpreviousMillis > blaulichtintervaloff)  {
    blaulichtpreviousMillis = blaulichtcurrentMillis;
    blaulichtState = HIGH;
    digitalWrite(blaulichtPin, blaulichtState);       // blaulicht ausschalten
  }
  
  if(sensor1 < 100 && rotlichtState == HIGH && rotlichtcurrentMillis - rotlichtpreviousMillis > rotlichtintervalon)  {
    rotlichtpreviousMillis = rotlichtcurrentMillis;
    rotlichtState = LOW;
    digitalWrite(rotlichtPin, rotlichtState);         // rotlicht einschalten
  }
  
  if(sensor1 < 100 && rotlichtState == LOW && rotlichtcurrentMillis - rotlichtpreviousMillis > rotlichtintervaloff)  {
    rotlichtpreviousMillis = rotlichtcurrentMillis;
    rotlichtState = HIGH;
    digitalWrite(rotlichtPin, rotlichtState);         // rotlicht ausschalten
  }
  
  if(sensor1 > 100 && sensor1 < 190)   {              // Sensor 2.5V
    digitalWrite(bremslichtPin, HIGH);
    digitalWrite(lichtgiraffePin, LOW);
    digitalWrite(strahlerPin, HIGH);
  }
  if(sensor1 > 190)   {                               // Sensor 5V
    digitalWrite(bremslichtPin, LOW);
    digitalWrite(lichtgiraffePin, HIGH);
    digitalWrite(strahlerPin, HIGH);
  }
    if(sensor1 < 100)   {                             // Sensor 0V
    digitalWrite(bremslichtPin, HIGH);
    digitalWrite(lichtgiraffePin, LOW);
    digitalWrite(strahlerPin, LOW);
  }
}                                                     // loop zu

Oh sorry, du hast recht, Sketch hängt jetzt oben dran :slight_smile:

Oops, du hast den Sketch ja auch reingesetzt...

Also quasi so: blau - blau - blau - - - - - - - - - - blau - blau - blau - - - - - - - - - - usw.
Parallel dazu: rot-rot-----------rot-rot------------ usw.

Zeichne das Ganze erstmal in ein einheitliches Zeitraster, z.B. so:

Rot : 10101000 00000000 10101000
Blau: 10100000 10100000 10100000

Könnte man z.B. in 2 Arrays speichern.

byte RotSequenz[16]  = {1, 0, 1, 0, 1, 0, usw. };
byte BlauSequenz[16] = {1, 0, 1, 0, 0, 0, usw. };

Als nächstes definierst Du ein Zeitintervall für die Schrittlänge - oder auch 2, wenn die Rotsequenz unabhängig von der Blausequenz laufen soll. Die Sequenzen können natürlich auch verschiedenen Längen haben.

Jedesmal, wenn das Zeitintervall abgelaufen ist, liest Du den nächsten Wert aus dem Array und schaltest entsprechend die betreffende LED in Anhängigkeit vom gelesenen Wert an oder aus.

Du hast also nur noch ein Intervall pro Farbe, keine getrennte On-/Offzeit mehr. Das machst Du jetzt wie bei einem Stepsequenzer und trägst Dein Timing ins Array ein. Du kannst auch eine sehr kleine Intervalllänge wählen und eine lange Sequenz haben, um praktische beliebige On-/Offzeiten hinzubekommen. Ausgedrückt als Vielfache des Intervalls.

Wenn Du am Ende des Arrays angekommen bist (im Beispiel Index 15 (also der 16. Eintrag)) setzt Du den Indexzähler wieder auf 0.

Verständlich?

Gruß,

Helmuth

Hallo Helmut, danke für deine Antwort.

Öhm, mit Arrays hab ich noch keine Erfahrungen, aber ich verstehe zumindest, wie du das Array vom Zeitraster ausgehend definiert hast. Die Array-Abfrage geschieht ja auch im Loop-Teil, aber wie genau frage ich den nächsten Arrayschritt ab und macht das die ganzen Millis-Vergleiche überflüssig?

Chris

Mal als Pseudocode für angenommene 16 Schritte im Array:

byte RotSequenz[16]  = {1, 0, 1, 0, 1, 0, usw. };
byte BlauSequenz[16] = {1, 0, 1, 0, 0, 0, usw. };

byte rotindex = 0;
byte blauindex = 0;

loop()  {

Ist Rotintervall abgelaufen?
Ja: byte RotZustand = RotSequenz[rotindex]
    rotindex++
    if rotindex > 15 rotindex = 0

Das Gleiche für Blau

if RotZustand == 0 Rot aus, sonst Rot an
if BlauZustand == 0 Blau aus, sonst Blau an
}

macht das die ganzen Millis-Vergleiche überflüssig?

Nein, nur einen Teil davon.

Hammer!!! Funktioniert!!! Dankääää, Helmut :slight_smile: :smiley:

Gerne.