LED Fader unterbrechen

Hi,
aktuell bin ich gerade dabei einen Fuß für ein kleines Modell mit LEDs auszustatten. Statt einfach nur "AN" und "AUS" hätte ich gerne ein paar Effekte dazu...und zwar zwei Fade-Effekte.
Es sind 4 LEDs, die im "Kreis" angeordnet sind.

Im Modus 1 (circle()) sollen die LEDs quasi im Kreis faden, sodass das Modell einmal kurz von jeder Seite angestrahlt wird.
Im Modus 2 (fader()) sollen die LEDs alle gemeinsam ein und aus faden.
Im Modus 3 (on()) sind die LEDs alle an, ohne Effekt.

Das ganze soll mit nur einem Taster (PULLUP) gesteuert werden.

An sich funktioniert es, bis auf eine nervige Sache:
Ich bekomme die beiden Fader-Modi nicht sofort unterbrochen, sondern nur genau dann, wenn die Sequenz beendet wurde.

Hat jemand eine Idee, wie ich diese Fade-Schleifen sofort beim Tastendruck unterbrechen kann und der Arduino den Modus wechselt?

Hier mein Sketch:

int ledPin1 = 3;    // LED connected to digital pin 9
int ledPin2 = 5;
int ledPin3 = 6;
int ledPin4 = 9;
int buttonPin = 2;
int buttonState = 0;
byte buttonPressCount = 0;
byte cycle = 0;
int circleRun = 0;
int faderRun = 0;
int onRun = 0;
int offRun = 0;
int fadeValue = 0;

void setup()  { 
  pinMode(buttonPin, INPUT_PULLUP);
  Serial.begin(9600);
  digitalWrite(buttonPin, HIGH);
} 

void circle() {
  // fade in from min to max in increments of 5 points:
  for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) { 
    // sets the value (range from 0 to 255):
    analogWrite(ledPin1, fadeValue);   
    // wait for 30 milliseconds to see the dimming effect    
    delay(10);                            
  } 

  // fade out from max to min in increments of 5 points:
  for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) { 
    // sets the value (range from 0 to 255):
    analogWrite(ledPin1, fadeValue);    
    // wait for 30 milliseconds to see the dimming effect    
    delay(10);                            
  } 

for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) { 
    // sets the value (range from 0 to 255):
    analogWrite(ledPin2, fadeValue);   
    // wait for 30 milliseconds to see the dimming effect    
    delay(10);                            
  } 

  // fade out from max to min in increments of 5 points:
  for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) { 
    // sets the value (range from 0 to 255):
    analogWrite(ledPin2, fadeValue);    
    // wait for 30 milliseconds to see the dimming effect    
    delay(10);                            
  } 

for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) { 
    // sets the value (range from 0 to 255):
    analogWrite(ledPin3, fadeValue);   
    // wait for 30 milliseconds to see the dimming effect    
    delay(10);                            
  } 

  // fade out from max to min in increments of 5 points:
  for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) { 
    // sets the value (range from 0 to 255):
    analogWrite(ledPin3, fadeValue);    
    // wait for 30 milliseconds to see the dimming effect    
    delay(10);                            
  } 

for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) { 
    // sets the value (range from 0 to 255):
    analogWrite(ledPin4, fadeValue);   
    // wait for 30 milliseconds to see the dimming effect    
    delay(10);                            
  } 

  // fade out from max to min in increments of 5 points:
  for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) { 
    // sets the value (range from 0 to 255):
    analogWrite(ledPin4, fadeValue);    
    // wait for 30 milliseconds to see the dimming effect    
    delay(10);                            
  }
  
}

void fader() {
  for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=1) {
    analogWrite(ledPin1, fadeValue);
    analogWrite(ledPin2, fadeValue);
    analogWrite(ledPin3, fadeValue);
    analogWrite(ledPin4, fadeValue);
    delay(10);
  }
  for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=1) {
    analogWrite(ledPin1, fadeValue);
    analogWrite(ledPin2, fadeValue);
    analogWrite(ledPin3, fadeValue);
    analogWrite(ledPin4, fadeValue);
    delay(10);
  }
}

void on() {
  digitalWrite(ledPin1, HIGH);
  digitalWrite(ledPin2, HIGH);
  digitalWrite(ledPin3, HIGH);
  digitalWrite(ledPin4, HIGH);
}

void off() {
  digitalWrite(ledPin1, LOW);
  digitalWrite(ledPin2, LOW);
  digitalWrite(ledPin3, LOW);
  digitalWrite(ledPin4, LOW);
  buttonPressCount = 0;
}

void loop()  { 
  buttonState = digitalRead(buttonPin);
  if (buttonState == LOW) {
  if (buttonPressCount == 1) {
    Serial.println("1 - Circle");
    cycle = 1;
  }
  if (buttonPressCount == 2) {
    Serial.println("2 - Fader");
    cycle = 2;
  }
  if (buttonPressCount == 3) {
    Serial.println("3 - ON");
    cycle = 3;
  }
  if (buttonPressCount == 4) {
    Serial.println("4 - OFF");
    cycle= 0;
    Serial.println("0");
  }
  buttonPressCount++;
  delay(300);
}

switch (cycle) {
  case 0:
    off();
    break;

  case 1:
    circle(); 
    break;

  case 2:
    fader();
    break;

  case 3:
    on();
    break;
  }

}

Ich habe bereits versucht, circle() und fader() mit einem "while(buttonState != LOW)" zu versehen - ohne Erfolg, das gleiche gilt für eine if-Bedingung der gleichen Art.

Soweit ich das verstehe, muss der Arduino (Pro Micro übrigens) den ganzen Fade-Kram zu ende machen, bevor er etwas anderes wahrnehmen kann...oder liege ich da falsch?

Gruß,
Jannomag

Du kannst doch innerhalb deiner "for-Schleifen" einen Variable Taster auswerten, nach der du aus der Schleife rausspringst oder eben nicht.

Solange Du blockierend mit eigenen Schleifen arbeitest, kann der MC dazwischen keine Taster auslesen.
Du hast doch schon eine Schleife: loop. Da brauchst Du keine weiteren.
Dann klappt das auch mit der Unterbrechung.

Gruß Tommy

@Tommy:
Du meinst die for-Schleifen?
Habe keine andere Lösung gefunden, die LEDs in einer Squenz zu faden...bin allerdings auch niemand, der von selbst auf sowas kommt, ich bediene mich da immer an Foren-Beiträgen oder Tutorials.

Die Funktionen habe ich jetzt mal komplett entfernt und alles in die cases gesetzt...gleiches verhalten.

solange Du doe for-Schleifen drin hast (und in denen als Motlösung keine Tasterabfrage zum Abbruch hast) wird sich da auch nichts ändern.
Deine Beschreibung sagt uns nicht wirklich, wie der neue Code aussieht.

Gruß Tommy

Dein Problem ist hier im Forum schon zig mal besprochen worden. Lies dich mal blockierungsfreies Programmieren ein.

Stichworte: Nachtwächter Erklärung; endlicher Zustandsautomat, wait/blink without delay,

Man kann for-Schleifen auch auflösen und durch if-Abfragen in loop() ersetzen. Pro loop() Durchlauf ein Schritt und dann halt selbst mitzählen wie weit man schon ist

Serenifly:
Pro loop() Durchlauf ein Schritt und dann halt selbst mitzählen wie weit man schon ist

ich würde eher sagen, pro loop Durchlauf einmal nachschauen, ob schon wieder ein Schritt fällig ist. Sonst sieht man kein Faden bei 256 loops in wenigen ms.

Das mit den for-Schleifen habe ich verstanden und werde für das nächste Mal daran denken. Dann bin ich aber auf JLed gestoßen, bzw. habe mich wieder daran erinnert.
Damit konnte ich es recht einfach lösen und alles funktioniert, wie es soll:

#include <jled.h>

int led1 = 3;
int led2 = 5;
int led3 = 6;
int led4 = 9;
int button = 2;
int buttonState = 0;
byte pressCount = 0;
int lastbuttonState = 0;



JLed circle[] = {
  JLed(3).Breathe(2000).Repeat(1),
  JLed(5).Breathe(2000).Repeat(1),
  JLed(6).Breathe(2000).Repeat(1),
  JLed(9).Breathe(2000).Repeat(1)
};

JLed fade[] = {
  JLed(3).Breathe(2000).Repeat(1),
  JLed(5).Breathe(2000).Repeat(1),
  JLed(6).Breathe(2000).Repeat(1),
  JLed(9).Breathe(2000).Repeat(1)
};



JLedSequence circle_sequence(JLedSequence::eMode::SEQUENCE, circle);
JLedSequence fade_sequence(JLedSequence::eMode::PARALLEL, fade);


void setup() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(button, INPUT_PULLUP);
  Serial.begin(9600);

}

void loop() {
  static byte lastCount = 0;
  
  buttonState = digitalRead(button);
  if (buttonState != lastbuttonState) {
    if (buttonState == LOW) {
      pressCount++;
      delay(400);
      }
  }
  
    Serial.println(pressCount);
    switch (pressCount)
    {
      case 0:
        digitalWrite(led1, LOW);
        digitalWrite(led2, LOW);
        digitalWrite(led3, LOW);
        digitalWrite(led4, LOW);
        break;
      case 1:
        circle_sequence.Update();
        if(circle_sequence.Update() == false) {
          circle_sequence.Reset();
        }
        break;
      case 2:
        if(circle_sequence.Update() == true) {
          circle_sequence.Stop();
        }
        fade_sequence.Update();
        if(fade_sequence.Update() == false) {
          fade_sequence.Reset();
        }
        break;
      case 3:
        digitalWrite(led1, HIGH);
        digitalWrite(led2, HIGH);
        digitalWrite(led3, HIGH);
        digitalWrite(led4, HIGH);
        break;
     }
    if(pressCount == 4) {
      pressCount = 0;
    }
    lastbuttonState = buttonState;

}