Fastled und unabhängige Animation

Hi, bin gerade dabei an 4 Strips zu jeweils 24 Led´s, unabhängig von den Anderen Strips Animationen Durchzuschicken, an einem Funktioniert das wunderbar, aber hab leider keine Idee wie ich andere Animationen an die Anderen Strips aktiviere

Die Beispiele sind von https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/
vielleicht kann mir da jemmand weiterhelfen

#include "FastLED.h"

#include <EEPROM.h>
#define NUM_LEDS 24

CRGB leds1[NUM_LEDS];
CRGB leds2[NUM_LEDS];
CRGB leds3[NUM_LEDS];
CRGB leds4[NUM_LEDS];

#define PIN1 14
#define PIN2 15
#define PIN3 16
#define PIN4 17

const int addr = 0;

void setup()
{
  FastLED.addLeds<WS2812, PIN1, GRB>(leds1, NUM_LEDS).setCorrection( TypicalLEDStrip );
  FastLED.addLeds<WS2812, PIN2, GRB>(leds2, NUM_LEDS).setCorrection( TypicalLEDStrip );
  FastLED.addLeds<WS2812, PIN3, GRB>(leds3, NUM_LEDS).setCorrection( TypicalLEDStrip );
  FastLED.addLeds<WS2812, PIN4, GRB>(leds4, NUM_LEDS).setCorrection( TypicalLEDStrip );
  Serial.begin(9600);
}

void serialEvent()
{
  char effekt = Serial.read();
  if (isalpha(effekt)) EEPROM[addr] = effekt;
}

void loop() {

  switch ((char)EEPROM[addr]) {
    case 'a'  : {
        FadeInOut(255, 0, 0);
        break;
      }
    case 'b'  : {
        Sparkle(255, 255, 255, 10);
        break;
      }
  }
}

void FadeInOut(byte red, byte green, byte blue) {
  float r, g, b;

  for (int k = 100; k < 256; k = k + 1) {
    r = (k / 256.0) * red;
    g = (k / 256.0) * green;
    b = (k / 256.0) * blue;
    setAll(r, g, b);
    showStrip();
  }

  for (int k = 256; k >= 100; k = k - 0.01) {
    r = (k / 256.0) * red;
    g = (k / 256.0) * green;
    b = (k / 256.0) * blue;
    setAll(r, g, b);
    showStrip();
  }
}


void Sparkle(byte red, byte green, byte blue, int SpeedDelay) {
  int Pixel = random(NUM_LEDS);
  setPixel(Pixel, red, green, blue);
  showStrip();
  delay(SpeedDelay);
  setPixel(Pixel, 0, 0, 0);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////

void showStrip() {
#ifdef ADAFRUIT_NEOPIXEL_H
  // NeoPixel
  strip.show();
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
  // FastLED
  FastLED.show();
#endif
}

void setPixel(int Pixel, byte red, byte green, byte blue) {
#ifdef ADAFRUIT_NEOPIXEL_H
  // NeoPixel
  strip.setPixelColor(Pixel, strip.Color(red, green, blue));
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
  // FastLED
  leds1[Pixel].r = red;
  leds1[Pixel].g = green;
  leds1[Pixel].b = blue;
#endif
}

void setAll(byte red, byte green, byte blue) {
  for (int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue);
  }
  showStrip();
}

Hi

Bis auf das eine delay() sieht Das doch gar nicht so schlecht aus - zugegeben: Viel machen die einzelnen Funktionen nicht, somit brauchen Die auch kaum Zeit.

Wenn Du nun eine Funktion hast, Die z.B. laaangsam hoch dimmen soll, musst Du ja nur alle zig Durchläufe wirklich was am Stripe ändern - in der Zwischenzeit machst Du ... Nichts :slight_smile:
Ganz ohne delay() - einfach Nichts machen, wenn Nichts gemacht werden muß.

Für Abläufe, Die Zeit brauchen, musst Du Dir merken, WANN Du zuletzt was damit gemacht hast - und WAS Du Da gemacht hast.
Beim Hoch-Dimmen-Beispiel musst Du Dir z.B. merken, DAS Du hochdimmen willst, WO Du gerade bist (... 30%) und wann Du zuletzt die Helligkeit angepasst hast (Uhrzeit) - damit Du erkennen kannst, WANN die Zeit um ist, um hier weiter zu machen.

Combie hat dazu eine schöne Liste bezüglich State-Maschine/Endlicher Automat - gerne Mal durchforsten.

MmfG

Edit
Die Liste: Ablaufsteuerung
Combie's Standardantwort zu Ablaufsteuerungen

Edit 2
Bei den ganzen Animationen, Die Dort erstellt werden, musst Du 'nur' vom delay() weg kommen und Dir, bis zum nächsten Aufruf, merken, WO Du warst.
Dann kannst Du locker die 4 Stripes mit verschiedenen Animationen beglücken, ohne, daß Die Sich gegenseitig stören.

Wenn Du EINEN Stripe nutzt, statt Vier (also elektrisch Einer und daher nur eine Instanz im Sketch) kann man auch 'nur' den Bereich des Einzel-Stripe umfärben.
Also 0...23 Stripe 1, 24...47 Stripe 2, ...
Mit mehreren Instanzen musst Du den Animationen ja auch noch mitgeben, um welche Instanz sich die Funktion gerade kümmern soll - ist aber ebenso möglich.

Naja vielleicht hab ich mich falsch ausgedrückt, der code ist weitestgehend iO, was ich zu Realisieren versuch ist, unamhängige animationen an den 4 Strips, eigentlich sind es Ringe, ich stell mir das so vor, über serial z.b. kommt der buchstabe a, dann laufen unterschiedliche animationen a 4 ausgänge, beim buchstaben B, kommen wiederum andere unterschiedliche animationen, das ganze soll schrittweise so aufgebaut sein das man damit auch blinken kann, oder beim Starten des fahrzeuges, langsam die Ringe gedimmt werden, das ganze ist für ein Fahrzeug gedacht,
aber erstmal eins nach dem anderen

Hi

... wird aber kein VW sein, oder? :wink:

Sofern das Fahrzeug nicht in öffentlichem Raum bewegt wird (gehen wir Mal ganz einfach von aus!!), kein Problem - wenn doch, könnte die Zulassung erlöschen - blöd.

Sofern die Animationen nicht Alle die gleiche Zeit und die gleichen Zwischenzeiten haben, musst Du eh in Einzelschritte umdenken.
Auch ein Blitzen ist ja 'nur' Warten, Licht an, Warten, Licht aus, warten.

Die 4 Ringe kannst Du in Reihe löten - also elektrisch zu Einem machen - Das vereinfacht zumindest das Ansprechen der 'verschiedenen Stripes' aka Ringe.
Universeller wird's, wenn wir die Ringe einzeln lassen und den Funktionen die Instanz mit übergeben, in Der die Änderung statt finden soll.

MfG

nene, der ist mir zu Kostbar das er im Öffentlichen Raum bewegt wird, es ist ein 32 jahre alter BMW E30 Cabrio, das nur hin und wieder zu events aufm Hänger kommt,

sowas ähnliches hab ich mir vorgestellt, nur halt auch mit der möglichkeit wie ein strobo z.b. anwählen zu können, hätte aber gerne auch komplexe Animationen eingepflegt

Verdammt


Hätte jetzt ja auf einen Audi getippt :slight_smile:

Wie gesagt - wenn die Stripes separat sind, wird's komplizierter, aber dafür universeller einsetzbar (eben AUCH mit nur einem Stripe).

Du musst nur definieren, wo welche Gruppe liegt - und dann der Gruppe 'sagen',. Was Sie machen soll.
Wenn die Stripes einzelne Instanzen sind, dann wird eben diese Instanz und 0 bis Anzahl an Pixel übergeben.

Den Rest - dafür hast Du Dir einen Arduino angeschafft, Der soll ja auch was schaffen!

Im Grunde dachte ich, daß wir die Animationen so umbauen, daß wir Denen die Instanz und den 'Schritt' mitgeben.
Ob die Funktion die Zeit macht, oder wir im Sketch ... weiß ich noch nicht, die Funktion 'wüsste', welche zeiten wann zu warten wären - vll. als Return-Wert, damit wir 'erst dann wieder' weiter machen ...

Möglichkeiten viele Es gibt, junger Caravan-Schüler :slight_smile:

MfG

Ist doch auch ein Schönes Auto :slight_smile:
Ja wenn man das wissen hat, gibt es bestimmt fast unendliche möglichkeiten

Hi

Die bietet Dir Arduino auch so - von 'Das Wissen' bin ich auch noch 'etwas' entfernt - hier haben eine ganze Menge Leute 'den Arsch deutlich höher, als ich'.

Denke auch, daß sich diese Leute hier ebenfalls einfinden :wink:
Die verlinkten Animationen finde ich schon Mal echt nicht schlecht - halt teilweise blockierend.
Die müssen wir 'nur' auf eine der Instanzen der Stripes und in Einzelschritte runterbrechen.

Denke, es wird ein gangbarer Weg, wenn die aufgerufene Funktion (mit Instanz und 'Nummer' der Animation) als Rückgabe die Wartezeit zurück gibt, wann der nächste Schritt geplant ist.
So müssten wir in loop() nur prüfen, ob für diese Animation 'die Zeit um ist' - und dann erneut aufrufen.
Ggf. eine negative Zeit, wenn die Animation beendet ist - aber so weit sind wir noch nicht.

MfG

Am Abend kann ich mir derzeit nicht oder nur schleppend anmelden, daher kann ich leider nur antworten, wenn die Amis pennen :frowning:

In setup hast Du vier Objekte leds1 bis leds4 festgelegt, also für jeden Ring eins. Also mußt Du zuerst einen Ring auswählen und dann die Animation dafür gestalten und an den Ring schicken. Dein Beispiel ist ganz gut gewählt, weil diese Objekte nur in der Funktion setPixel angesprochen werden. Die Funktion kann leicht durch einen Parameter für den Ring erweitert werden (ungetestet):

void setPixel(byte ring, int Pixel, byte red, byte green, byte blue) {
  if (ring == 1 || ring == 0)
  {
    leds1[Pixel].r = red;
    leds1[Pixel].g = green;
    leds1[Pixel].b = blue;
  }
  if (ring == 2 || ring == 0)
  {
    leds2[Pixel].r = red;
    leds2[Pixel].g = green;
    leds2[Pixel].b = blue;
  }
  if (ring == 3 || ring == 0)
  {
    leds3[Pixel].r = red;
    leds3[Pixel].g = green;
    leds3[Pixel].b = blue;
  }
  if (ring == 4 || ring == 0)
  {
    leds4[Pixel].r = red;
    leds4[Pixel].g = green;
    leds4[Pixel].b = blue;
  }
}

Jeder Aufruf der Funktion muß auf fünf Parameter erweitert werden, da ja der Ring ergänzt wurde:

setPixel(ring, Pixel, red, green, blue);

Bei ring == 0 werden alle Ringe animiert.

Daß delay() in einer quasi parallelen Verarbeitung mehrerer Animationen keinen Platz hat, wurde schon erwähnt.

Die Datenausgabe erfolgt mit FastLED.show(); an alle Ringe.

Hi

Man kann sich das dauernde .show() sparen, wenn man sich merkt, ob was verändert wurde.
Jedes .show(); braucht Zeit - und wenn sich keiner der Pixel geändert hat, ist Das unnötig.
Dazu reicht ein globales Flag, Typ bool.

...
bool pixelchange=false;
...
void showStrip() {
  if (pixelchange) {
    pixelchange = false;
#ifdef ADAFRUIT_NEOPIXEL_H
    // NeoPixel
    strip.show();
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
    // FastLED
    FastLED.show();
#endif
  }
}
...
void setPixel(int Pixel, byte red, byte green, byte blue) {
  pixelchange = true;
#ifdef ADAFRUIT_NEOPIXEL_H
  // NeoPixel
  strip.setPixelColor(Pixel, strip.Color(red, green, blue));
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
  // FastLED
  leds1[Pixel].r = red;
  leds1[Pixel].g = green;
  leds1[Pixel].b = blue;
#endif
}

Man ruft zwar die Funktion auf, Die die Daten zum Stripe schicken soll, Die macht Das aber nur, wenn was in den Stripe geschrieben wurde (kann auch die gleiche Farbe dieses Pixel gewesen sein).
Damit dürften aber schon einige .show(); weg sein, da die Animationen, zumindest für den Arduino, grotten lahm sind.

Dann müssen 'nur noch' die Blockaden raus :slight_smile:

MfG

Ich hab das ganze vorerstmal auf 2 Ringe reduziert, damit ich den überblick behalte, bekomm aber bei ring ein fehler, ring was not declared

#include "FastLED.h"
#define NUM_LEDS 24
CRGB leds1[NUM_LEDS];
CRGB leds2[NUM_LEDS];
#include <EEPROM.h>
const int addr = 0;

void setup() {
  FastLED.addLeds<WS2812, 14>(leds1, NUM_LEDS).setCorrection( TypicalLEDStrip );
  FastLED.addLeds<WS2812, 15>(leds2, NUM_LEDS).setCorrection( TypicalLEDStrip );
  Serial.begin(9600);
}

void serialEvent()
{
  char effekt = Serial.read();
  if (isalpha(effekt)) EEPROM[addr] = effekt;
}


void loop() {
  switch ((char)EEPROM[addr]) {
    case 'a'  : {
        FadeInOut(255, 0, 0);
        break;
      }
    case 'b'  : {
        Sparkle(255, 255, 255, 40);
        break;
      }
  }
}

void FadeInOut(byte red, byte green, byte blue) {
  float r, g, b;

  for (int k = 100; k < 256; k = k + 1) {
    r = (k / 256.0) * red;
    g = (k / 256.0) * green;
    b = (k / 256.0) * blue;
    setAll(ring, r, g, b);
    showStrip();
  }
}



void Sparkle(byte red, byte green, byte blue, int SpeedDelay) {
  int Pixel = random(NUM_LEDS);
  setPixel(ring, Pixel, red, green, blue);
  showStrip();
  delay(SpeedDelay);
  setPixel(ring, Pixel, 0, 0, 0);
}
}


void showStrip() {
#ifdef ADAFRUIT_NEOPIXEL_H
  // NeoPixel
  strip.show();
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
  // FastLED
  FastLED.show();
#endif
}

void setPixel(byte ring, int Pixel, byte red, byte green, byte blue) {
  if (ring == 1 || ring == 0)
  {
    leds1[Pixel].r = red;
    leds1[Pixel].g = green;
    leds1[Pixel].b = blue;
  }
  if (ring == 2 || ring == 0)
  {
    leds2[Pixel].r = red;
    leds2[Pixel].g = green;
    leds2[Pixel].b = blue;
  }
}

void setAll(byte red, byte green, byte blue) {
  for (int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue);
  }
  showStrip();
}

Hi

'ring' taucht in der Funktion Sparkle ja auch plötzlich auf - eine Zeilennummer, WO der Fehler auftrat, wäre übrigens nicht zu Viel verlangt gewesen, oder?

Wenn Du von dieser Funktion aus nur diesen einen Ring ansteuern willst, kannst Du 'ring' beim Aufruf auch sturr durch eine Zahl ersetzen - sinnvoller wäre Es, wenn schon der Funktion Sparkle() die Ring-Nummer mit übergeben wird - dann wäre 'ring' auch schon bekannt.
void Sparkle(byte red, byte green, byte blue, int SpeedDelay) {
-->
void Sparkle(byte ring, byte red, byte green, byte blue, int SpeedDelay) {

(dann natürlich im Aufruf von Sparkle() diese Zusatzzahl ebenfalls einbringen)

MfG

jetzt meckert er noch ganz am ende, kom aber leider nicht drauf

Hi

Auch Das ist eine Fehlerbeschreibung, wie beim Arzt 'Aua'.
Auch das 'hinten rum' hilft hier weniger, als beim Arzt.

MfG

Also, so funktioniert es, ich kann 2 Animationen auf die jeweiligen pins lege, jedoch behindern sich die beiden gegeneinander, was nicht geht ist die Animationen untereinannder zu tauschen

#include "FastLED.h"
#define NUM_LEDS 24
CRGB leds1[NUM_LEDS];
CRGB leds2[NUM_LEDS];
#include <EEPROM.h>
const int addr = 0;

void setup() {
  FastLED.addLeds<WS2812, 14>(leds1, NUM_LEDS).setCorrection( TypicalLEDStrip );
  FastLED.addLeds<WS2812, 15>(leds2, NUM_LEDS).setCorrection( TypicalLEDStrip );
  Serial.begin(9600);
}

void serialEvent()
{
  char effekt = Serial.read();
  if (isalpha(effekt)) EEPROM[addr] = effekt;
}


void loop() {
  switch ((char)EEPROM[addr]) {
    case 'a'  : {
        FadeInOut(1, 255, 0, 0);
        Sparkle(2, 255, 255, 255, 40);
        break;
      }
    case 'b'  : {
        FadeInOut(2, 255, 0, 0);
        Sparkle(1, 255, 255, 255, 40);
        break;
      }
  }
}

void FadeInOut(byte ring, byte red, byte green, byte blue) {
  float r, g, b;

  for (int k = 100; k < 256; k = k + 1) {
    r = (k / 256.0) * red;
    g = (k / 256.0) * green;
    b = (k / 256.0) * blue;
    setAll(r, g, b);
    showStrip();
  }
}



void Sparkle(byte ring, byte red, byte green, byte blue, int SpeedDelay) {
  int Pixel = random(NUM_LEDS);
  setPixel(ring, Pixel, red, green, blue);
  showStrip();
  delay(SpeedDelay);
  setPixel(ring, Pixel, 0, 0, 0);
}



void showStrip() {
#ifdef ADAFRUIT_NEOPIXEL_H
  // NeoPixel
  strip.show();
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
  // FastLED
  FastLED.show();
#endif
}

void setPixel(byte ring, int Pixel, byte red, byte green, byte blue) {
  if (ring == 1 || ring == 0)
  {
    leds1[Pixel].r = red;
    leds1[Pixel].g = green;
    leds1[Pixel].b = blue;
  }
  if (ring == 2 || ring == 0)
  {
    leds2[Pixel].r = red;
    leds2[Pixel].g = green;
    leds2[Pixel].b = blue;
  }
}

void setAll(byte red, byte green, byte blue) {
  for (int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(1, i, red, green, blue);
  }
  showStrip();
}

Eine weitere möglichkeit wäre doch einfach 4 attiny´s, jedes für ein ring und dann das ganze über serial einzeln ansteuern, das wäre doch auch eine möglichkeit wie hier beschrieben Winterground Fairlands - A World Of Funmagineering!: Daisy Chaining Serial Connections

Ist nicht die schönste art, ich weis, aber das ganze projekt übersteigt einfach meinen wissenstand und würde wahrscheinlich auch sehr viel Zeit in anspruch nehmen

Hi,

Wenn du wirklich komplexe Animationen haben willst aber Probleme dabei hast sie zu animieren, dann benutz
GLEDdiator.

Damit kannst du Animationen erstellen und sie separat auf einer SD Karte Speichern und dann vom Arduino mit Neopixel abspielen.

MFG GG

ArduGabi:
Hi,

Wenn du wirklich komplexe Animationen haben willst aber Probleme dabei hast sie zu animieren, dann benutz
GLEDdiator.

Damit kannst du Animationen erstellen und sie separat auf einer SD Karte Speichern und dann vom Arduino mit Neopixel abspielen.

MFG GG

Animationen sind schon da, nur wie gesagt möchte ich das ganze auf 4 kanälen unabhängig anwählbar machen
hast ein link zum glediator ???

Ein wahres meisterstück von Tool. Man kann schier unendlich viele Animationen schon auf ne 500MB SD Karte Laden und mit dem Simplen befehl "read bites" eine menge Zeit sparen. Habe allerdings noch nie sowas ausprobiert wie du es vor hast. Ist auf jeden Fall mal 'nen Blick wert .

Viel Spaß damit,
GG