Fastled Lauflicht Theater Chase - Fragen

Guten Tag!
Ich weiß - es ist wahrscheinlich das Millionste Fastled-Lauflicht Topic; ich muss aber trotzden fragen, weil ich als Einsteiger nicht weiterkomme und trotz langer Suche nichts Befriedigendes gefunden habe.

  1. Mein Ziel ist ein Lauflicht vom Stil Theater-Chase. Allerdings möchte ich, dass immer eine Gruppe von mehreren Leds durchläuft. Im unten stehenden Code habe ich das mit 3 Leds am Stück schon hinbekommen - allerdings gefällt mir eines nicht: Am Anfang des Strips leuchet immer gleich die ganze Dreier-Gruppe auf einmal - ich hätte es aber lieber, wenn diese Gruppe auch am Anfang des Strips “einläuft”, also eine nach der anderen Led angeht. Hier bitte ich um Eure Ideen.

  2. Sollte dies funktionieren, ist mein weiteres Ziel, 3 Strips an drei verschiedenen Arduino-Pins laufen zu lassen. Alle mit dem gleichen Lauflicht, nur immer um ein Pixel vesetzt. Also folgendermaßen:
    …xxx…xxx…xxx…
    …xxx…xxx…xxx…
    …xxx…xxx…xxx…
    Soweit ich das überblicke, müsste das ja möglich sein - über Multiple Arrays?

Hier aber erst mal der Code:

#include "FastLED.h"


#define NUM_LEDS 150
#define DATA_PIN 3
#define BRIGHTNESS 50


CRGB leds[NUM_LEDS];



void setup() { 
  FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS);
  LEDS.setBrightness(BRIGHTNESS);
}


void loop() {


theaterChase(CRGB::Red,10,200,CRGB::Black);

}

void theaterChase(CRGB c, int cycles, int speed, CRGB h){ 

  for (int j=0; j<cycles; j++) {  
    for (int q=0; q < 6; q++) {
      for (int i=0; i < NUM_LEDS; i=i+6) {
        int pos = i+q;
        
        
        leds[pos] = c;
        leds[pos+1] = c;
        leds[pos+2] = c;
      
        }

      FastLED.show();

      delay(speed);

      for (int i=0; i < NUM_LEDS; i=i+6) {
        int pos = i+q;
        
        
        leds[pos] = h;
        leds[pos+1] = h;
        leds[pos+2] = h
      }

     }
  }
}

Schon mal danke für Eure Hilfe!

Vielleicht geht so ein Lauflicht am einfachsten, wenn Du die Pixel ohne Bibliothek selbst rausschiebst. Dann brauchst Du nur ein const Array für das Muster, und nicht für alle LEDs.

DrDiettrich: Vielleicht geht so ein Lauflicht am einfachsten, wenn Du die Pixel ohne Bibliothek selbst rausschiebst. Dann brauchst Du nur ein const Array für das Muster, und nicht für alle LEDs.

Bei WS2812 ist das kein guter Ratschlag. Grüße Uwe

Amiga: ... Multiple Arrays?

Was meinst Du damit?

Wenn ich mir das Muster ansehe, fällt mir maximal ein Array ein - das halt zwei Dimensionen hat.

Gruß

Gregor

Danke für Eure Antworten. Mit multiple Array hab ich mich vielleicht etwas undeutlich ausgedrückt. Das was ich meinte - 3 Strips an 3 Pins mit vesetzter (also unterschiedlicher Ausgabe) ist im Fastled-Wiki unter der Überschrift "Multiple led arrays" beschrieben. https://github.com/FastLED/FastLED/wiki/Multiple-Controller-Examples

Ich müsste aber das Ganze eh erst mal auf einem Strip zum Laufen bekommen. Ich hab da schon einiges probiert, komme aber nicht weiter. Mir fehlt da die Programmier-Erfahrung...

Amiga: Mir fehlt da die Programmier-Erfahrung...

Na, dann machma :-)

Wenn Du noch Programmier-Anfänger bist: Lies das hier. Gut formatierter Code ist bei der Fehlersuche Gold wert. Naja, Erfahrung hilft auch - wie gesagt: machma.

Gruß

Gregor

Versuche mal diesen Ansatz:

void loop() {
  theaterChase(CRGB::Red, 500, CRGB::Green);
}

void theaterChase(CRGB c, int speed, CRGB h) {
  for (int q = 0; q < 6; q++) {
    for (int i = -5; i < NUM_LEDS; i = i + 6) {
      int pos = i + q;
      if (pos >= 0 && pos < NUM_LEDS) leds[pos] = c;
      if (pos + 1 >= 0 && pos + 1 < NUM_LEDS) leds[pos + 1] = c;
      if (pos + 2 >= 0 && pos + 2 < NUM_LEDS) leds[pos + 2] = c;
      if (pos + 3 >= 0 && pos + 3 < NUM_LEDS) leds[pos + 3] = h;
      if (pos + 4 >= 0 && pos + 4 < NUM_LEDS) leds[pos + 4] = h;
      if (pos + 5 >= 0 && pos + 5 < NUM_LEDS) leds[pos + 5] = h;
    }
    FastLED.show();
    delay(speed);
  }
}

Wow, das läuft prima!

Ganz herzlichen Dank für die Mühe. Das Wochenende ist gerettet :)

So, dank der tollen Vorarbeit habe ich ein bisschen weitergetestet und habe nun das, was ich wollte.
Habe (jetzt erst mal) zwei Strips ans zwei Pins hängen, die um ein Pixel versetzt das Gleiche machen.

…xxx…xxx…xxx…
…xxx…xxx…xxx…

Ich weiß, dass meine Lösung nicht ganz sauber ist, weil ich beim zweiten Strip die Position einfach ins Negative verschiebe und ich so den Strip ein Pixel länger definieren muss, als er wirklich ist. Für meinen Zweck ist das aber egal.

#include "FastLED.h"


#define NUM_LEDS_PER_STRIP 31
#define BRIGHTNESS 50
#define DATA_PIN1 3
#define DATA_PIN2 6


CRGB Reihe1[NUM_LEDS_PER_STRIP];
CRGB Reihe2[NUM_LEDS_PER_STRIP];

void setup() { 
  FastLED.addLeds<WS2812, DATA_PIN1, GRB>(Reihe1, NUM_LEDS_PER_STRIP);
  FastLED.addLeds<WS2812, DATA_PIN2, GRB>(Reihe2, NUM_LEDS_PER_STRIP);
  LEDS.setBrightness(BRIGHTNESS);
}

void loop() {
  theaterChase(CRGB::Red, 200, CRGB::Black);
}

void theaterChase(CRGB c, int speed, CRGB h) {
  for (int q = 0; q < 8; q++) {
    for (int i = -7; i < NUM_LEDS_PER_STRIP; i = i + 8) {
      int pos = i + q;
      if (pos >= 0 && pos < NUM_LEDS_PER_STRIP) Reihe1[pos] = c;
      if (pos + 1 >= 0 && pos + 1 < NUM_LEDS_PER_STRIP) Reihe1[pos + 1] = c;
      if (pos + 2 >= 0 && pos + 2 < NUM_LEDS_PER_STRIP) Reihe1[pos + 2] = c;
      if (pos + 3 >= 0 && pos + 3 < NUM_LEDS_PER_STRIP) Reihe1[pos + 3] = h;
      if (pos + 4 >= 0 && pos + 4 < NUM_LEDS_PER_STRIP) Reihe1[pos + 4] = h;
      if (pos + 5 >= 0 && pos + 5 < NUM_LEDS_PER_STRIP) Reihe1[pos + 5] = h;
      if (pos + 6 >= 0 && pos + 6 < NUM_LEDS_PER_STRIP) Reihe1[pos + 6] = h;
      if (pos + 7 >= 0 && pos + 7 < NUM_LEDS_PER_STRIP) Reihe1[pos + 7] = h;

      int pos2 = i + q;
      if (pos2 >= 0 && pos2 < NUM_LEDS_PER_STRIP) Reihe2[pos2-1] = c;
      if (pos2 + 1 >= 0 && pos2 + 1 < NUM_LEDS_PER_STRIP) Reihe2[pos2 + 0] = c;
      if (pos2 + 2 >= 0 && pos2 + 2 < NUM_LEDS_PER_STRIP) Reihe2[pos2 + 1] = c;
      if (pos2 + 3 >= 0 && pos2 + 3 < NUM_LEDS_PER_STRIP) Reihe2[pos2 + 2] = h;
      if (pos2 + 4 >= 0 && pos2 + 4 < NUM_LEDS_PER_STRIP) Reihe2[pos2 + 3] = h;
      if (pos2 + 5 >= 0 && pos2 + 5 < NUM_LEDS_PER_STRIP) Reihe2[pos2 + 4] = h;
      if (pos2 + 6 >= 0 && pos2 + 6 < NUM_LEDS_PER_STRIP) Reihe2[pos2 + 5] = h;
      if (pos2 + 7 >= 0 && pos2 + 7 < NUM_LEDS_PER_STRIP) Reihe2[pos2 + 6] = h;
    }
    FastLED.show();
    delay(speed);
  }
}

Nochmals Danke für die Hilfe!

Bei pos2 müssen die Berechnungen vorne bei den Vergleichen mit denen hinten übereinstimmen!

Danke; ich glaube, ganz langsam steige ich dahinter…

Jetzt schaut die Sache auch gleich viel sauberer aus und läuft prima:

#include "FastLED.h"

#define NUM_LEDS_PER_STRIP 30
#define BRIGHTNESS 50
#define DATA_PIN1 3
#define DATA_PIN2 6


CRGB Reihe1[NUM_LEDS_PER_STRIP];
CRGB Reihe2[NUM_LEDS_PER_STRIP];

void setup() { 
  FastLED.addLeds<WS2812, DATA_PIN1, GRB>(Reihe1, NUM_LEDS_PER_STRIP);
  FastLED.addLeds<WS2812, DATA_PIN2, GRB>(Reihe2, NUM_LEDS_PER_STRIP);
  LEDS.setBrightness(BRIGHTNESS);
}

void loop() {
  theaterChase(CRGB::Red, 500, CRGB::Black);
}

void theaterChase(CRGB c, int speed, CRGB h) {
  for (int q = 0; q < 8; q++) {
    for (int i = -7; i < NUM_LEDS_PER_STRIP; i = i + 8) {
      int pos = i + q;
      if (pos >= 0 && pos < NUM_LEDS_PER_STRIP) Reihe1[pos] = c;
      if (pos + 1 >= 0 && pos + 1 < NUM_LEDS_PER_STRIP) Reihe1[pos + 1] = c;
      if (pos + 2 >= 0 && pos + 2 < NUM_LEDS_PER_STRIP) Reihe1[pos + 2] = c;
      if (pos + 3 >= 0 && pos + 3 < NUM_LEDS_PER_STRIP) Reihe1[pos + 3] = h;
      if (pos + 4 >= 0 && pos + 4 < NUM_LEDS_PER_STRIP) Reihe1[pos + 4] = h;
      if (pos + 5 >= 0 && pos + 5 < NUM_LEDS_PER_STRIP) Reihe1[pos + 5] = h;
      if (pos + 6 >= 0 && pos + 6 < NUM_LEDS_PER_STRIP) Reihe1[pos + 6] = h;
      if (pos + 7 >= 0 && pos + 7 < NUM_LEDS_PER_STRIP) Reihe1[pos + 7] = h;

      int pos2 = i + q - 1;
      if (pos2 >= 0 && pos2 < NUM_LEDS_PER_STRIP) Reihe2[pos2] = c;            
      if (pos2 + 1 >= 0 && pos2 + 1 < NUM_LEDS_PER_STRIP) Reihe2[pos2 + 1] = c;
      if (pos2 + 2 >= 0 && pos2 + 2 < NUM_LEDS_PER_STRIP) Reihe2[pos2 + 2] = c;
      if (pos2 + 3 >= 0 && pos2 + 3 < NUM_LEDS_PER_STRIP) Reihe2[pos2 + 3] = h;
      if (pos2 + 4 >= 0 && pos2 + 4 < NUM_LEDS_PER_STRIP) Reihe2[pos2 + 4] = h;
      if (pos2 + 5 >= 0 && pos2 + 5 < NUM_LEDS_PER_STRIP) Reihe2[pos2 + 5] = h;
      if (pos2 + 6 >= 0 && pos2 + 6 < NUM_LEDS_PER_STRIP) Reihe2[pos2 + 6] = h;
      if (pos2 + 7 >= 0 && pos2 + 7 < NUM_LEDS_PER_STRIP) Reihe2[pos2 + 7] = h;
    }
    FastLED.show();
    delay(speed);
  }
}

Ich fände eine weitere Zusammenfassung übersichtlicher.

#include <FastLED.h>

#define NUM_LEDS_PER_STRIP 30
#define BRIGHTNESS 50
#define DATA_PIN1 3
#define DATA_PIN2 6

CRGB Reihe1[NUM_LEDS_PER_STRIP];
CRGB Reihe2[NUM_LEDS_PER_STRIP];

void setup() {
  FastLED.addLeds<WS2812, DATA_PIN1, GRB>(Reihe1, NUM_LEDS_PER_STRIP);
  FastLED.addLeds<WS2812, DATA_PIN2, GRB>(Reihe2, NUM_LEDS_PER_STRIP);
  LEDS.setBrightness(BRIGHTNESS);
}

void loop() {
  theaterChase(CRGB::Red, 500, CRGB::Black);
}

void theaterChase(CRGB c, int speed, CRGB h) {
  for (int q = 0; q < 8; q++) {
    for (int i = -7; i < NUM_LEDS_PER_STRIP; i += 8) {
      achtLeds(Reihe1, i + q, c, h);
      achtLeds(Reihe2, i + q - 1, c, h);
    }
    FastLED.show();
    delay(speed);
  }
}

void achtLeds(CRGB* strip, int pos, CRGB c, CRGB h) {
  setIfValidPos(strip, pos + 0, c);
  setIfValidPos(strip, pos + 1, c);
  setIfValidPos(strip, pos + 2, c);
  setIfValidPos(strip, pos + 3, h);
  setIfValidPos(strip, pos + 4, h);
  setIfValidPos(strip, pos + 5, h);
  setIfValidPos(strip, pos + 6, h);
  setIfValidPos(strip, pos + 7, h);
}

void setIfValidPos(CRGB* strip, int pos, CRGB color) {
  if (pos >= 0 && pos < NUM_LEDS_PER_STRIP) {
    strip[pos] = color;
  }
}

Man könnte auch noch die Funktion achtLeds mit einem for schreiben,
aber das wäre deutlich unflexibler was das Muster angeht.

void achtLeds(CRGB* strip, int pos, CRGB c, CRGB h) {
  for (byte i = 0; i < 8; i++) {
    setIfValidPos(strip, pos + i, i < 3 ? c : h);
  }
}

Die Funktion setIfValidPos ist natürlich das Sahnehäubchen und gehört eigentlich in fast jede FastLED-Anwendung. Die Adafruit-Bibliothek hat es eingebaut.

Wow, das ist ja toll! Ich hab seit gestern echt was gelernt und danke Euch ganz herzlich für Eure Mühe!

Ich habe noch eine Verständnisfrage: Mir ist nicht ganz klar, wie (CRGB* strip) funktioniert. Was bewirkt hier der Operator * ?

Das Sternchen gibt an, es handelt sich um einen Zeiger. Dadurch wird keine Kopie des Objektes erstellt, sondern das originale verwendet. Eine Kopie würde am Ende der Funktion weggeworfen.

Auch wenn es nicht C++ ist, ich habe hier gelesen: Zeiger (Pointer) und dort auch "Zeiger als Funktionsparameter"

Kannst du auf zwei Arten lesen

*strip ist vom Datentyp CRGB

strip ist ein Zeiger auf CRGB,

Wegen der engen Verwandschaft von Zeigern und Arrays in C:
strip kann übrigens auch ein Array von CRGB sein.

Im Funktionsrumpf wäre strip[0] dasselbe wie *strip.

Wenn du jetzt verwirrt bist: daran gewöhnt man sich :wink:

Danke für die schnellen Antworten!