Interrupt oder andere Möglichkeit?

Hallo,
ich möchte für mein Projekt bei der ein DC Motor permanent in unterschiedlichen und zufälligen Geschwindigkeiten gedreht wird, eine Aktion hinzufügen welche die Farben von LED’s wechselt. Die Aufgabe hat also nichts mit der des Motors gemeinsam. Die Möglichkeit mit dem Interrupt funktioniert auch soweit, jedoch benötige ich ein delay(150) welches bei Interrupts bekanntlich nicht so einfach möglich ist.
Kann in das nötige delay einfach in eine Methode verschieben welche vom Interrupt aufgerufen wird?

Ich lade einfach mal meinen Alpha Code hoch. Verbesserungsvorschläge sind gern gesehen, beachtet bitte jedoch, das es nur die Alpha Version ist um meine Funktionen zu testen.

#include "FastLED.h"

int pinA = 7;
int pinB = 8;
int pinPWM = 9;

int randSpeed[10] = {65,70,75,80,85,90,95,100,105,180};

long randNumber;
long randTime;

#define NUM_LEDS 8 				  // Anzahl LEDS
#define DATA_PIN 3 				  // NeoPixel Pin
CRGB leds[NUM_LEDS]; 				  // Array leds erstellen

#define NUMPLAYERS 8 				  // Anzahl Spieler
byte players[NUMPLAYERS]; 			  // Array player erstellen

void mixPlayers() 				  // Methode zum Mischen
{
  randomSeed(micros());  
    					          // Startwert für Zufallsgenerator initialisieren
  for(int i=0; i < NUMPLAYERS; i++) 		  // entsprechend der Anzahl der Spieler
  {
    byte r = random(NUMPLAYERS-i);  		  // einen Spieler zufällig wählen
    byte temp = players[NUMPLAYERS-i-1];          // den Spieler am Ende der Auswahl merken
    players[NUMPLAYERS-i-1] = players[r]; 	  // am Ende der Auswahl den zufällig gewählten Spieler einfügen
    players[r] = temp;		                  // und den gemerkten Spieler an die Stelle des ausgewählten Spielers setzen
  }
}

void showColors()
{
	leds[players[0]] = CRGB::Red;
	leds[players[1]] = CRGB::Red;
	leds[players[2]] = CRGB::Yellow;
	leds[players[3]] = CRGB::Yellow;
	leds[players[4]] = CRGB::Green;
	leds[players[5]] = CRGB::Green;
	leds[players[6]] = CRGB::Blue;
	leds[players[7]] = CRGB::Blue;
	FastLED.show();
}

void ColorChange()
{
  for(int i=0; i < 10; i++)
    {
    mixPlayers();
    showColors();
    delay(150);   <----- dieses delay evtl. in ShowColor() verschieben?!
    }
}

void setup(){
  Serial.begin(9600);
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);

  pinMode(2, INPUT_PULLUP);                 // Analoger Eingang für Taster (wenn nicht gedrückt, Zustand HIGH)

	
  int i = 0;
  while(i < NUMPLAYERS {
    i++;
    players[i] = i;
    }

  pinMode(pinA, OUTPUT);
  pinMode(pinB, OUTPUT);
  randomSeed(analogRead(0));
  attachInterrupt(0, ColorChange, RISING);
}

void loop(){
  randNumber = random(1, 10);
  randTime = random(2000, 5000);
  
  digitalWrite(pinA, HIGH);
  digitalWrite(pinB, LOW);
  analogWrite(pinPWM, randSpeed[randNumber]);
  delay(randTime);
}

Gibt es andere elegantere Möglichkeiten bei der mehrere Tasks vom Arduino ordentlich verarbeitet werden können?

ph3nomic: Kann in das nötige delay einfach in eine Methode verschieben welche vom Interrupt aufgerufen wird?

Nein. Die Interrupts werden erst wieder freigegeben wenn die ISR beendet wird. Egal was du dazwischen machst.

Du kannst aber in der ISR einfach nur ein Flag setzen (volatile bool) und dann in loop() ständig darauf abfragen. Die ISR meldet dann nur dass was gemacht werden soll, aber das erledigt man dann Außerhalb wo die Interrupts wieder aktiviert sind.

Wofür überhaupt die ISR? Lerne ohne delay - auch in der loop - auszukommen. Das Problem tritt hier im Forum fast jeden Tag mehrfach auf.

volatile byte isr_flag = 0;

void ColorChange()
{
isr_flag++; // oder isr_flag = 1;
}

void loop()
{
if(isr_flag) {isr_flag = 0; /* mache was anderes */}

}

Edit: Stefan war schneller :(

Okay, wie kann ich aber ein delay von 2000 bsp. anders bewerkstelligen?

Ich habe jetzt den Code folgendermaßen angepasst, ist mein Gedankengang soweit richtig oder liege ich komplett daneben?

#include "FastLED.h"

int pinA = 7;
int pinB = 8;
int pinPWM = 9;

int randSpeed[10] = {65,70,75,80,85,90,95,100,105,180};

long randNumber;
long randTime;

volatile byte isr_flag = 0;

#define NUM_LEDS 8 							// Anzahl LEDS
#define DATA_PIN 3 							// NeoPixel Pin
CRGB leds[NUM_LEDS]; 						// Array leds erstellen

#define NUMPLAYERS 8 						// Anzahl Spieler
byte players[NUMPLAYERS]; 			// Array player erstellen

void mixPlayers() 							// Methode zum Mischen
{
  randomSeed(micros());  
    					        // Startwert für Zufallsgenerator initialisieren
  for(int i=0; i < NUMPLAYERS; i++) 		    // entsprechend der Anzahl der Spieler
  {
    byte r = random(NUMPLAYERS-i);  		    // einen Spieler zufällig wählen
    byte temp = players[NUMPLAYERS-i-1];      // den Spieler am Ende der Auswahl merken
    players[NUMPLAYERS-i-1] = players[r]; 	  // am Ende der Auswahl den zufällig gewählten Spieler einfügen
    players[r] = temp;						            // und den gemerkten Spieler an die Stelle des ausgewählten Spielers setzen
  }
}

void showColors()
{
	leds[players[0]] = CRGB::Red;
	leds[players[1]] = CRGB::Red;
	leds[players[2]] = CRGB::Yellow;
	leds[players[3]] = CRGB::Yellow;
	leds[players[4]] = CRGB::Green;
	leds[players[5]] = CRGB::Green;
	leds[players[6]] = CRGB::Blue;
	leds[players[7]] = CRGB::Blue;
	FastLED.show();
}

void ColorChange()
{
  for(int i=0; i < 10; i++)
    {
    mixPlayers();
    showColors();
    delay(150);
    }
}

void setup(){
  Serial.begin(9600);
	FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
	
  int i = 0;
  while(i < NUMPLAYERS {
    i++;
    players[i] = i;
    }

  pinMode(pinA, OUTPUT);
  pinMode(pinB, OUTPUT);
  randomSeed(analogRead(0));
  attachInterrupt(0, ColorChange, RISING);
}

void loop(){
  randNumber = random(1, 10);
  randTime = random(2000, 5000);

  if(isr_flag == 0) {
    digitalWrite(pinA, HIGH);
    digitalWrite(pinB, LOW);
    analogWrite(pinPWM, randSpeed[randNumber]);
    delay(randTime);
    isr_flag = 0;
  }
  else {
    ColorChange();
    isr_flag = 0;
  }
}
}

Lass das delay weg. Sowohl im Interrupt als auch in der loop! Google -> BlinkWithoutDelay