Mehrere LED auf einem Streifen per Fastled ansteuern

Hallo Zusammen

Ich bin neu hier, und auch neu im Programmieren.
Ich versuche seit einigen Tagen schon mein neues Projekt zum laufen bringen. Aber irgendwie klappt es nicht, egal welche Varianten ich schon versucht habe. Mehrere Forumsbeispiele etc.

Hier eine Kurze Beschreibung was ich vor habe.
Einen LED Streifen mit Fade Funktion aufzufüllen (geklappt).
Nun will ich aber in diesem Streifen das ein paar LED's z.B die LED 3 und 4 gleichzeitig mit einem Fade aufleuchten.

Hier mein Code. Ist noch in der Entwicklung und nur zum Testen da.

#include <FastLED.h>

#define DATA_PIN 12  //Anschluss des Ledstreifens
#define NUM_LEDS 10  //Anzahl LEDs

CRGB leds[NUM_LEDS];

//----------------------------------------------------------------------------------


//----------------------------------------------------------------------------------

int Steps = 16;
int fadeAmount = -(256 / Steps);  // 256 / Steps
int brightness = 0;
byte factor = 0;
int myTime = 70;
int myTime2 = 50;

//----------------------------------------------------------------------------------

void LEDcontrol(int i) {
  for (int gr7 = 3; gr7 < 4; gr7++) {
    for (int j = 0; j < Steps; j++) {
      if (i == 0 or i == 1 or i == 2) leds[i] = CRGB::Blue;  // Gruppe 1
                                                             // Gruppe 2
                                                             // Gruppe 3
                                                             // Gruppe 4
                                                             // Gruppe 5
                                                             // Gruppe 6
      if (i == gr7) leds[i] = CRGB::Yellow;                  // Gruppe 7
      if (i == 5 or i == 7) leds[i] = CRGB::Red;             // Gruppe 8
      if (i == 9) leds[i] = CRGB::Blue;
      if (i > 9) leds[i] = CRGB::Blue;
      brightness = brightness + fadeAmount;
      leds[i].fadeLightBy(brightness);
      FastLED.show();
      delay(myTime);
    }
  }
}
//----------------------------------------------------------------------------------

void setup() {
  FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS);
}
//----------------------------------------------------------------------------------
void loop() {

  for (int i = 0; (NUM_LEDS); i++) {
    brightness = factor;
    LEDcontrol(i);
    delay(myTime2);
  }
  fadeAmount = -fadeAmount;
  factor = factor ^ 0xFF;
}

Was bis jetzt bei all meinen Versuchen geklappt hat das entweder die 3 oder 4 LED in Gelb aufgeleuchtet haben. Aber nie beide Zusammen.

Vielleicht kann mir hier irgendjemand helfen der sich in der Materie auskennt.

Vielen Herzlichen Dank für eure Hilfen.

MFG

steiger11

Was soll das genau machen??

Den Bereich Markieren welche LED zusammen leuchten sollten. Dachte ich zumindest. :grin:. Nach dem 10ten versuch was ich so gefunden habe war das meine letzte hoffnung.

Das tut wohl nicht, was Du möchtest, habe ich daher mal geändert.

Bin mir unsicher, ob ich das richtig verstehe, aber mal ein Versuch:

#include <FastLED.h>

#define DATA_PIN 12  //Anschluss des Ledstreifens
#define NUM_LEDS 10  //Anzahl LEDs

CRGB leds[NUM_LEDS];

//----------------------------------------------------------------------------------


//----------------------------------------------------------------------------------

int Steps = 16;
int fadeAmount = -(256 / Steps);  // 256 / Steps
int brightness = 0;
byte factor = 0;
int myTime = 70;
int myTime2 = 50;

//----------------------------------------------------------------------------------

void LEDcontrol(int i) {
    for (int j = 0; j < Steps; j++) {
      if (i == 0 or i == 1 or i == 2) leds[i] = CRGB::Blue;  // Gruppe 1
                                                             // Gruppe 2
                                                             // Gruppe 3
                                                             // Gruppe 4
                                                             // Gruppe 5
                                                             // Gruppe 6
      if (i == 5 or i == 7) leds[i] = CRGB::Red;             // Gruppe 8
      if (i == 6 or i == 7) leds[i] = CRGB::Yellow;
      if (i == 8) leds[i] = CRGB::Blue;
      if (i == 9) leds[i] = CRGB::Blue;
      brightness = brightness + fadeAmount;
      leds[i].fadeLightBy(brightness);
      leds[3] = leds[1];
      leds[4] = leds[9];
      FastLED.show();
      delay(myTime);
    }
}
//----------------------------------------------------------------------------------

void setup() {
  FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS);
  FastLED.show();
}
//----------------------------------------------------------------------------------
void loop() {

  for (int i = 0; i < NUM_LEDS; i++) {
    brightness = factor;
    LEDcontrol(i);
    delay(myTime2);
  }
  fadeAmount = -fadeAmount;
  factor = factor ^ 0xFF;
}

kannst du das ausführlicher beschreiben?
sprich

  • 8 LEDs sollen was machen? Was heißt "auffüllen" ... Sollen die Schrittweise eine LED nach der anderen auf volles blau eingeschaltet werden oder alle gleichzeitig "langsam" einschalten?
  • LED 3 und LED 4 sollen langsam von schwarz auf gelb gefadet werden
  • Wie schnell schnell soll das Faden von LED3/LED4 sein, wie schnell das "auffüllen" der 8 anderen LEDs?

Die 8 LED's sollen schrittweise langsam auf volles Blau eingeschaltet werden. Jetzt im Testfall sollen die 3 und 4 gleichzeitig langsam auf volles Gelb geschaltet werden. Also zuerst LED 0-2 und danach 3+4 gleichzeitig danach wieder 5 - ..... .
Die Fade Funktion ist im Code jetzt in 16 Schritten unterteilt, also von 0 - 256 in 16 Teilen. Die Schnelligkeit kann ich mit Time definieren.

Das widerspricht sich!

Noch ein Vorschlag:

#include <FastLED.h>

#define DATA_PIN 12  //Anschluss des Ledstreifens
#define NUM_LEDS 10  //Anzahl LEDs

CRGB leds[NUM_LEDS];

int Steps = 16;
int fadeAmount = -(256 / Steps);  // 256 / Steps
int brightness = 0;
byte factor = 0;
int myTime = 70;
int myTime2 = 50;

//----------------------------------------------------------------------------------

void LEDcontrol(int i) {
  for (int j = 0; j < Steps; j++) {
    if (i == 3) {
      leds[3] = CRGB::Yellow;
    } else {
      leds[i] = CRGB::Blue;
    }
    brightness = brightness + fadeAmount;
    leds[i].fadeLightBy(brightness);
    leds[4] = leds[3];
    FastLED.show();
    delay(myTime);
  }
}
//----------------------------------------------------------------------------------

void setup() {
  FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS);
  FastLED.show();
}
//----------------------------------------------------------------------------------
void loop() {

  for (int i = 0; i < NUM_LEDS; i++) {
    if (i == 4) i++;
    brightness = factor;
    LEDcontrol(i);
    delay(myTime2);
  }
  fadeAmount = -fadeAmount;
  factor = factor ^ 0xFF;
}

Dieses Programm hat Optimierungspotential!

Danke Dir viel mal Agmue.
Sowas habe ich mir vorgestellt.
Wie oben beschrieben habe ich leider noch nicht wirklich viel Ahnung vom programmieren.
Kannst du mir bitte sagen wieso und wie dies funktioniert, damit ich es erweitern kann. Also noch mehr unterschiedliche LED Blöcke etc.
Denn mein End Projekt besteht etwa aus 30 unterschiedlichen Blöcken mit unterschiedlichen Anzahl an LED's.

Danke Dir schon im voraus für deine Bemühungen.

MFG Steiger11

Grundsätzlich werden alle LEDs auf Blau gebracht, nur bei 3 gibt es eine Ausnahme, da ist es Gelb. LED 4 bekommt den selben Wert wie 3 und wird daher in loop übergangen.

Ja?

Derzeit ist delay kein Problem, eventuell stößt Du aber später auf Schwierigkeiten, weshalb ich immer mit millis Zeiten messen würde. Mit Differenzen wie jetzt - vorhin >= intervall kannst Du Zeitabschnitte messen.

Der selbstoptimierende Compiler erkennt Möglichkeiten, wenn Du Konstanten mit const kennzeichnest.

Ich glaube habe es verstanden. Im Loop unten werden alle LED einzeln definiert welche zu einer Gruppe gehören sollten.
Und oben im Void LED Control kann ich dies so erweitern.

Habe hier mal ein Beispiel gemacht.

//----------------------------------------------------------------------------------

void LEDcontrol(int i) {
  for (int j = 0; j < Steps; j++) {
    if (i == 3) {                  
      leds[3] = CRGB::Yellow;       
    } else if (i == 7 or i == 8) {  
      leds[7] = CRGB::Yellow;       
    } else {
      leds[i] = CRGB::Blue;  
    }
    brightness = brightness + fadeAmount;
    leds[i].fadeLightBy(brightness);
    leds[4] = leds[3];  
    leds[8] = leds[7]; 
    leds[9] = leds[7];  
    FastLED.show();
    delay(myTime);
  }
}
//----------------------------------------------------------------------------------

void setup() {
  FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS);
  FastLED.show();
}
//----------------------------------------------------------------------------------
void loop() {

  for (int i = 0; (NUM_LEDS); i++) {
    if (i == 4) i++;  // Ende Gruppe 1
    if (i == 8) i++;  // Gruppe 2
    if (i == 9) i++;  // Gruppe 2
    brightness = factor;
    LEDcontrol(i);
    delay(myTime2);
  }
  fadeAmount = -fadeAmount;
  factor = factor ^ 0xFF;
}

Ist dies Korrekt oder geht es auch einfacher? Wenn ich mal z.B 10 oder mehr LED's in einer Gruppe habe.
Im Loop habe ich noch das < entfernt damit er im fertigen Projekt nicht wieder mit dem Dunkel werden beginnt.

"Ein Programm, das tut, was es soll, ist ein gutes Programm!" Dieses Zitat, das mir am Anfang hier im Forum gegeben wurde, reiche ich an Dich weiter.

Und die Einfachheit liegt im Auge des Betrachters. Beispielsweise @combie schreibt auf Datenflüsse konzentrierte, ästhetisch schöne Programme, die wunderbar einfach aussehen. Da ich sie aber leider nur so gerade eben, wenn überhaupt, verstehe, kann ich diese Einfachheit leider nur ausnahmsweise für mich nutzen.

Ein für Dich einfaches Programm ist also eines, dessen Komplexität Du gerade noch verstehst.

Ich danke dir für die Blumen!
Genau, weiß ich nicht was mich dazu treibt...
In mittelferner Vergangenheit wurde mir mal gesagt, dass meine Programme "Ameisenartig" arbeiten würden.
Dabei sind eigentlich die Bienen, bzw, der Bien, Paten meiner Programme.

Nach etwas mehr Grübeln bin ich auf die Idee gekommen, die Anzahl der Gruppenmitglieder und die Farbe in eine Datenstruktur zu packen. Nur mal, um die Idee zu zeigen:

#include <FastLED.h>

const byte DATA_PIN {12};  //Anschluss des Ledstreifens
const byte NUM_LEDS {10};  //Anzahl LEDs

CRGB leds[NUM_LEDS];

const int Steps {16};
const int fadeAmount {256 / Steps}; // 256 / Steps
const uint32_t myTime {70};
const uint32_t myTime2 {50};
byte led {0};

class Gruppe
{
    const byte anzahl;
    const uint32_t farbe;
  public:
    Gruppe (const byte anzahl, const uint32_t farbe)
      : anzahl(anzahl), farbe(farbe)
    {}
    void animation()
    {
      Serial.print(led);
      Serial.print('\t');
      Serial.print(anzahl);
      Serial.print('\t');
      Serial.println(fadeAmount);
      for (int b = fadeAmount; b <= 255; b += fadeAmount)
      {
        for (byte l = 0; l < anzahl; l++)
        {
          leds[led + l] = farbe;
          leds[led + l].nscale8_video(b);
        }
        FastLED.show();
        delay(myTime);
      }
      led += anzahl;
      delay(myTime2);
    }
};

Gruppe gruppe[] =
{ // anzahl, farbe
  {1, CRGB::Blue},
  {1, CRGB::Blue},
  {1, CRGB::Blue},
  {2, CRGB::Yellow},
  {1, CRGB::Blue},
  {1, CRGB::Blue},
  {3, CRGB::Yellow}
};

//----------------------------------------------------------------------------------

void setup() {
  Serial.begin(9600);
  Serial.println("\nStart");
  delay(500);
  FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS);
  FastLED.show();
}
//----------------------------------------------------------------------------------
void loop() {
  if (led < NUM_LEDS)
  {
    for (Gruppe &g : gruppe) g.animation();
  }
}

Ich fände dies bei vielen Gruppen übersichtlicher. Und Du?

Oh wow ja das sieht viel übersichtlicher aus. Vielen Dank für deine Ratschläge.
Viele Wege führen nach Rom sagt man doch so, und das gilt demnach auch beim Programmieren :slight_smile:
Jetzt muss ich nur noch das ganze verstehen. Also den ganzen Code in Arduino aufspielen und nachverfolgen was genau gemacht wird. Denn nur so lernt man von andern. Kopieren kann jeder.

MFG Steiger11

1 Like

Also ich hätte da einen etwas anderen Vorschlag. Es wurde eine Klasse definiert, deren Methode mit globalen Variablen arbeitet. Das widerspricht ja eigentlich der Kapselung bei der Objektorientierung.

Alle angelegten Objekte sind, abgesehen von Farbe und Anzahl, identisch. Außerdem kann die Klasse bis zum "Absturz" initialisiert werden. Es wird keinerlei Prüfung vorgenommen, ob die Summe (Anzahl) der LEDs nicht überschritten wird. Ändert man die Initialisierung z.B. in der Form, dass bei der ersten gelben Gruppe die Anzahl 6 statt 2 angegeben wird, kommt es zu fleißigen Reboots.

Ich würde hier gar keine Klasse verwenden, sondern die Methode "animation()" zu einer Funktion machen und dieser, strukturierte Daten als Parameter übergeben:

#include <FastLED.h>

struct AnimationsParameter {
  const int fadeAmount;
  const uint32_t timeFade;
  const uint32_t timeSwitch;
};

struct Gruppe {
  const byte anzahl;
  const unsigned long farbe;
  const AnimationsParameter &ap;
};

const byte DATA_PIN {12};   // Anschluss des Ledstreifens
const byte NUM_LEDS {10};   // Anzahl LEDs
const byte Steps {256 / 16};

CRGB leds[NUM_LEDS];
byte ledZaehler {0};

AnimationsParameter aParams {Steps, 70, 50};

Gruppe gruppe[] = {
  // anzahl, farbe
    {1, CRGB::Blue,   aParams},
    {1, CRGB::Blue,   aParams},
    {1, CRGB::Blue,   aParams},
    {2, CRGB::Yellow, aParams},
    {1, CRGB::Blue,   aParams},
    {1, CRGB::Blue,   aParams},
    {5, CRGB::Yellow, aParams}
};

//----------------------------------------------------------------------------------

template <size_t N> void animation(CRGB (&ledArr)[N], byte &index, const Gruppe &gp) {
  Serial.print(index);
  Serial.print('\t');
  Serial.print(gp.anzahl);
  Serial.print('\t');
  Serial.println(gp.ap.fadeAmount);

  // wenn beim Initialisieren mehr LEDs angegeben wurden, als vorhanden sind, wird die Anzahl hier begrenzt.
  if (index < N) {
    if (index + gp.anzahl > N) {                    // Prüfung ob index + Anzahl noch im erlabuten Bereich liegt.
      byte *tmp = const_cast<byte *>(&gp.anzahl);   // eigentlich böse - const wird umgangen.
      *tmp = N - index;
    }
    for (int b = gp.ap.fadeAmount; b <= 255; b += gp.ap.fadeAmount) {
      for (byte l = 0; l < gp.anzahl; l++) {
        ledArr[index + l] = gp.farbe;
        ledArr[index + l].nscale8_video(b);
      }
      FastLED.show();
      delay(gp.ap.timeFade);
    }
    index += gp.anzahl;
    delay(gp.ap.timeSwitch);
  }
}

//----------------------------------------------------------------------------------

void setup() {
  Serial.begin(115200);
  Serial.println("\nStart");
  delay(500);
  FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS);
  FastLED.show();
}
//----------------------------------------------------------------------------------
void loop() {
  if (ledZaehler < NUM_LEDS) {
    for (Gruppe &g : gruppe) animation(leds, ledZaehler, g);
  }
}

So kann auch jede Gruppe unterschiedlich animiert werden, je nachdem, mit welchen Animationsparametern sie initialisiert wird.

Es könnte auch noch überlegt werden, ob man beim "faden" nicht etwas logarithmischer vorgeht:
https://www.mikrocontroller.net/articles/LED-Fading

Das ist richtig. Leider wollte der Compiler meine frühere Lösung mit einer globalen static Variablen innerhalb der Klasse nicht mehr gutheißen. Die von mir gefundene Alternative erschien mir zu kompliziert, weshalb ich dann die einfache und funktionierende Lösung gewählt habe, da dieser Punkt für den TO derzeit gänzlich irrelevant ist.

Deinen Vorschlag finde ich gut, da er vermutlich für den TO einfacher zu verstehen sein könnte :wink:

Meinst Du so?

#include <FastLED.h>

const byte DATA_PIN {12};    // Anschluss des Ledstreifens
const byte NUM_LEDS {10};   // Anzahl LEDs

CRGB ledStripe[NUM_LEDS];
const int steps {16};
byte ledNum {0};

class Gruppe {
  static const byte fadeAmount;
  static const unsigned long timeFade;
  static const unsigned long timeSwitch;

  const byte anzahl;
  const uint32_t farbe;

public:
  Gruppe(const byte anzahl, const uint32_t farbe) : anzahl(anzahl), farbe(farbe) {}
  template <size_t N> void animation(CRGB (&leds)[N], byte &index) {
    Serial.print(index);
    Serial.print('\t');
    Serial.print(anzahl);
    Serial.print('\t');
    Serial.println(fadeAmount);
    if (index < N) {
      for (int b = fadeAmount; b <= 255; b += fadeAmount) {
        for (byte l = 0; l < anzahl; l++) {
          leds[index + l] = farbe;
          leds[index + l].nscale8_video(b);
        }
        FastLED.show();
        delay(timeFade);
      }
    }
    index += anzahl;
    delay(timeSwitch);
  }
};
const byte Gruppe::fadeAmount {256 / steps};
const unsigned long Gruppe::timeFade {70};
const unsigned long Gruppe::timeSwitch {60};

Gruppe gruppe[] = {
  // anzahl, farbe
    {1, CRGB::Blue  },
    {1, CRGB::Blue  },
    {1, CRGB::Blue  },
    {2, CRGB::Yellow},
    {1, CRGB::Blue  },
    {1, CRGB::Blue  },
    {3, CRGB::Yellow}
};

//----------------------------------------------------------------------------------

void setup() {
  Serial.begin(115200);
  Serial.println("\nStart");
  delay(500);
  FastLED.addLeds<WS2812, DATA_PIN, GRB>(ledStripe, NUM_LEDS);
  FastLED.show();
}
//----------------------------------------------------------------------------------
void loop() {
  if (ledNum < NUM_LEDS) {
    for (Gruppe &g : gruppe) g.animation(ledStripe, ledNum);
  }
}

Du machst aus meinen Ideen noch richtiges OOP :wink:

Hallo Miteinander

Vielen vielen Dank für eure super Hilfen. Es funktioniert so wie es sollte. Leider habe ich noch nicht ganz den zusammenhang aller einzelnen funktionen begriffen. Da bin ich aber dran um es zu verstehen. Learning by doing ist angesagt :slight_smile:

MFG Steiger11

So. Ich habe mich mal in den Millis versucht wie es Agmue und diverse Beispiele empfohlen haben.
Nur funktioniert es irgendwie nicht. Stehe glaube ich grausam auf dem Schlauch. Soweit ich es verstanden habe ersetzt ja Millis die Delay Funktion durch eine nennen wir sie mal Millis IF Funktion. Bei allen Beispielen die ich gefunden habe wird diese "Funktion" im Loop hinzugefügt. Nur bei den von euch Programmierten Programmen ist ja nicht viel im Loop drin. Somit habe ich ein bisschen überall versucht die Millis Funktion unter zu bringen. Leider kein Erfolg. Kann mir jemand von euch auf die Sprüngen helfen wo in diesem Code ich die Funktion einfügen müsste:

#include <FastLED.h>

unsigned long Millisend;
unsigned long Millisstart = 0;

const byte DATA_PIN{ 12 };  //Anschluss des Ledstreifens
const byte NUM_LEDS{ 10 };  //Anzahl LEDs

CRGB leds[NUM_LEDS];

const int Steps{ 16 };
const int fadeAmount{ 256 / Steps };        // 256 / Steps
const uint32_t myTime{ Millisend >= 70 };   // Fadegeschwindigkeit / Geringer gleich Schneller
const uint32_t myTime2{ Millisend >= 50 };  // Durchlaufgeschwindigkeit zwischen den einzelnen LED's/ Geringer gleich Schneller
byte led{ 0 };

class Gruppe {
  const byte anzahl;
  const uint32_t farbe;
public:
  Gruppe(const byte anzahl, const uint32_t farbe)
    : anzahl(anzahl), farbe(farbe) {}
  void animation() {
    Serial.print(led);
    Serial.print('\t');
    Serial.print(anzahl);
    Serial.print('\t');
    Serial.println(fadeAmount);
    for (int b = fadeAmount; b <= 255; b += fadeAmount) {
      for (byte l = 0; l < anzahl; l++) {
        leds[led + l] = farbe;
        leds[led + l].nscale8_video(b);
      }
      if (Millisend >= myTime) {
        FastLED.show();
        //delay(myTime);
      }
      if (Millisend >= myTime2) {
        led += anzahl;
        //delay(myTime2);
        Millisstart = millis();
      }
    }
  }
};

Gruppe gruppe[] = {
  // anzahl, farbe
  { 1, CRGB::Blue },    //Gruppe 1 LED Nr.0
  { 1, CRGB::Blue },    //Gruppe 2 LED Nr.1
  { 1, CRGB::Blue },    //Gruppe 3 LED Nr.2
  { 2, CRGB::Yellow },  //Gruppe 4 LED Nr.3, 4
  { 1, CRGB::Blue },    //Gruppe 5 LED Nr.5
  { 1, CRGB::Blue },    //Gruppe 6 LED Nr.6
  { 3, CRGB::Yellow }   //Gruppe 7 LED Nr.7, 8, 9
};

//----------------------------------------------------------------------------------

void setup() {
  Serial.begin(9600);
  Serial.println("\nStart");
  delay(500);
  FastLED.addLeds<WS2812, DATA_PIN, GRB>(leds, NUM_LEDS);
  FastLED.show();
}
//----------------------------------------------------------------------------------
void loop() {
  Millisend = (millis() - Millisstart);

  if (led < NUM_LEDS) {
    for (Gruppe &g : gruppe) g.animation();
  }
}

Diese Milli Funktion funktioniert nicht. Habe ich getestet. Ich frage ist wo müssten die 2 Delay Ersatz Funktionen untergebracht werden, und sorry für vielleicht doofe fragen.

Danke euch für eure Antworten.