Ansteurung von WS2815 LED Strips mit mehr als 450 LEDs

Hallo,

ich habe ein bisschen mit einem Uno R3 rumgebastelt und wollte mit dem eigentlich 2 Stränge mit 900LEDs (oder 450 LEDs bin mir da noch nicht sicher) schalten. Für das Vorhaben wollte ich WS2815 12V Streifen nutzen, mit 3x5m und das dann zweimal.
Hab jetzt mal auf einem Uno getestet, mit ein paar einzelnen RGB LEDs. Das hat klappt soweit ganz gut.

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h>
#endif

#define BUTTON_PIN2   2
#define BUTTON_PIN3   3

#define PIXEL_PIN9     9
#define PIXEL_PIN10   10
#define PIXEL_COUNT    6

Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN9, NEO_GRBW + NEO_KHZ800);
Adafruit_NeoPixel strip1(PIXEL_COUNT, PIXEL_PIN10, NEO_GRBW + NEO_KHZ800);

boolean oldState = HIGH;
int     mode     = 0;

void setup() {
  pinMode(BUTTON_PIN2, INPUT_PULLUP);
  pinMode(BUTTON_PIN3, INPUT_PULLUP);
  strip.begin();
  strip.show();
  strip1.begin();
  strip1.show();
}

void loop() {
 
  boolean newState_red = digitalRead(BUTTON_PIN2);

  if((newState_red == LOW) && (oldState == HIGH)) {
    delay(20);
    newState_red = digitalRead(BUTTON_PIN2);
    if(newState_red == LOW) {
      if(++mode > 8) mode = 0;
      switch(mode) {
        case 0:
          colorWipe(strip.Color(50,   0,   0), 50);    // Red
          colorWipe(strip1.Color(50,   0,   0), 50);    // Red
          break;
      }
    }
  }
  boolean newState_green = digitalRead(BUTTON_PIN3);

  if((newState_green == LOW) && (oldState == HIGH)) {
    delay(20);
    newState_green = digitalRead(BUTTON_PIN3);
    if(newState_green == LOW) {
      if(++mode > 8) mode = 0;
      switch(mode) {
        case 0:
          colorWipe(strip.Color(0,   50,   0), 50);    // Green
          colorWipe(strip1.Color(0,   50,   0), 50);    // Green
          break;
      }
    }
  }
}

void colorWipe(uint32_t color, int wait) {
  for (int j = 0; j < (strip.numPixels() / 2); j++) {
    strip.setPixelColor((strip.numPixels() / 2) + j, color);
    strip.setPixelColor((strip.numPixels() / 2) - 1 - j, color);
    strip1.setPixelColor((strip.numPixels() / 2) + j, color);
    strip1.setPixelColor((strip.numPixels() / 2) - 1 - j, color);
    strip.show();
    strip1.show();
    delay(100);
  }
}

Ich wollte mit den zwei Eingängen nur zwei unterschiedlich Farben schalten. Mehr wollte ich damit gar nicht machen. Die zwei Data PINs wollte ich nutzen um die Stränge aufzuteilen.
Leider schaft der Uno das ja nun nicht. Habt ihr vielleicht eine Empfehlung was man für den UNO nimmt und läuft der Code dann noch oder muss der umgeschrieben werden. War schon glücklich das so funktioniert. :grin:

nimm einen MEGA - der hat mehr Speicher.

Okay vielen Dank.

Ich hab im Code mal den Pixel_Count auf 200 gesetzt, habe aber nur 6 LEDs angeschlossen.
Nur dauert das starten das Animation sehr lang, wenn ich zwischen PIN2 und PIN3 umschalte.
Liegt das an den fehlenden LEDs oder dauert die Berechnung für den Code der an die LEDs geschickt werden soll so lange?

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h>
#endif

#define BUTTON_PIN2   2
#define BUTTON_PIN3   3

#define PIXEL_PIN9        9
#define PIXEL_PIN10    10
#define PIXEL_COUNT  200

Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN9, NEO_GRBW + NEO_KHZ800);
Adafruit_NeoPixel strip1(PIXEL_COUNT, PIXEL_PIN10, NEO_GRBW + NEO_KHZ800);

boolean oldState = HIGH;
int     mode     = 0; 
void setup() {
  pinMode(BUTTON_PIN2, INPUT_PULLUP);
  pinMode(BUTTON_PIN3, INPUT_PULLUP);
  strip.begin();
  strip1.begin();
  strip.show();
  strip1.show();
}

void loop() {
 boolean newState_red = digitalRead(BUTTON_PIN2);

  if((newState_red == LOW) && (oldState == HIGH)) {
    delay(20);
    newState_red = digitalRead(BUTTON_PIN2);
    if(newState_red == LOW) { 
      if(++mode > 8) mode = 0;
      switch(mode) {           
        case 0:
          colorWipe(strip.Color(50,   0,   0), 50);
          colorWipe(strip1.Color(50,   0,   0), 50);
          break;
      }
    }
  }
  boolean newState_green = digitalRead(BUTTON_PIN3);

  if((newState_green == LOW) && (oldState == HIGH)) {
    delay(20);
    newState_green = digitalRead(BUTTON_PIN3);
    if(newState_green == LOW) {  
      if(++mode > 8) mode = 0;
      switch(mode) { 
        case 0:
          colorWipe(strip.Color(0,   50,   0), 50); 
          colorWipe(strip1.Color(0,   50,   0), 50);
          break;
      }
    }
  }
}

void colorWipe(uint32_t color, int wait) {
  for(int i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, color);
    strip1.setPixelColor(i, color);
    strip.show();
    strip1.show();
    delay(50);
  }
}

Das sind 200 * 50 ms! + PixelTime für 2 Stripe!!

Das ist komplett vermurkst.
Wenn Du ein Lauflicht willst, musst Du das Blockadefrei machen.
Keine Schleifen.

Ich wollte gerne einen Weg beleuchten und das mit zwei Stripes. Ich hatte mir gedacht ich benutze zwei Daten PINs, damit jeder Strip extra versorgt ist. Eigentlich sollen die ja beide das gleiche anzeigen. Von daher reicht wohl auch der eine PIN.

Ja ich wollte eigentlich gerne einmal ein Lauflicht realisieren.
Also eine LED geht nach der anderen an und dann bleiben alle an.
Und als zweites ein Lauflicht von beiden Enden zur Mitte hin. Mit den beiden Eingängen wollte ich nur zwischen zwei Farben hin und her schalten (aber immer als Lauflicht). Dazu wollte ich einfach Wechsler nutzen. Es ist also immer nur ein Eingang auf Masse geschaltet.
Soweit funktionieren ja beide Sachen ganz gut nur das Delay blockiert mich.
Hab jetzt gelesen das ich eigentlich mit millis arbeiten müsste. Wie ich das auf eine einzelne LED (Ausgang) anwende habe ich verstanden. Aber irgendwie hab ich keine Idee wie ich das auf den Strip anwenden kann. Ich müsste das ja irgendwie in eine Variable einbauen.

Schau mal hier: Neopixel Brightnessfade
Da wurde ein delay durch millis ersetzt.

Ich schau mal, ob ich deinen code verwursteln kann. Sollte ich irgendwas habe , meld ich mich evtl. Freitag.

@wwerner
Danke

@my_xy_projekt
Das wäre toll auch schonmal ein Danke dafür. Ein bisschen bin ich auch vorran gekommen. Es sieht schon ganz gut aus mit der Umstellung auf millis. Leider wechselt die LED die Farbe jetzt an einer undefinierten Stelle wenn ich die Farbe wechsel. Also das Lauflicht sollte immer bei ersten LED anfangen. Das andere funktioniert schon.

#include <Adafruit_NeoPixel.h>

#define BUTTON_GREEN   2
#define BUTTON_RED     3
#define NUM_PIXELS     6

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXELS, 9, NEO_GRBW + NEO_KHZ800);

boolean oldState = HIGH;
int     mode     = 0;

unsigned long interval=500;
unsigned long previousMillis=0;

uint16_t currentPixel = 0;

void setup() {
  currentPixel = 0;
  strip.setBrightness(50);
  pinMode(BUTTON_GREEN, INPUT_PULLUP);
  pinMode(BUTTON_RED, INPUT_PULLUP);
  strip.begin();
  strip.show();
}

void loop() {
  boolean newState_green = digitalRead(BUTTON_GREEN);
  if((newState_green == LOW) && (oldState == HIGH)) {
    delay(20);
    newState_green = digitalRead(BUTTON_GREEN);
    if(newState_green == LOW) {
      if(++mode > 8) mode = 0;
      switch(mode) {
        case 0:
         if ((unsigned long)(millis() - previousMillis) >= interval) {
           previousMillis = millis();{
             colorWipeGREEN();
             break;
          }
        }
      }
    }
  }
  boolean newState_red = digitalRead(BUTTON_RED);
  if((newState_red == LOW) && (oldState == HIGH)) {
    delay(20);
    newState_red = digitalRead(BUTTON_RED);
    if(newState_red == LOW) {
      if(++mode > 8) mode = 0;
      switch(mode) {
        case 0:
         if ((unsigned long)(millis() - previousMillis) >= interval) {
           previousMillis = millis();{
             colorWipeRED();
             break;
          }
        }
      }
    }
  }
}

void colorWipeGREEN() {
  strip.setPixelColor(currentPixel, 0, 255, 0);
  strip.show();
  currentPixel++;
  if (currentPixel == NUM_PIXELS) {
    currentPixel = 0;
  }
}
void colorWipeRED() {
  strip.setPixelColor(currentPixel, 255, 0, 0);
  strip.show();
  currentPixel++;
  if (currentPixel == NUM_PIXELS) {
    currentPixel = 0;
  }
}

"Grün Rot Blau Weiß" paßt nicht zu WS2815, da ist Weiß nicht enthalten.

Ich habe mal den Quatsch mit

entfernt. Und noch viel mehr quatsch von ChatGPT.

Teste es mal so:

#include <Adafruit_NeoPixel.h>

#define BUTTON_GREEN   2
#define BUTTON_RED     3
#define NUM_PIXELS     6

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXELS, 9, NEO_GRB + NEO_KHZ800);

int     mode     = 0;

unsigned long interval = 500;
unsigned long previousMillis = 0;

uint16_t currentPixel = 0;

void setup() {
  currentPixel = 0;
  strip.setBrightness(50);
  pinMode(BUTTON_GREEN, INPUT_PULLUP);
  pinMode(BUTTON_RED, INPUT_PULLUP);
  strip.begin();
  strip.show();
}

void loop() {
  if (digitalRead(BUTTON_GREEN) == LOW) {
    mode = 1;
    currentPixel = 0;
    strip.clear();
  } else if (digitalRead(BUTTON_RED) == LOW) {
    mode = 2;
    currentPixel = 0;
    strip.clear();
  }

  switch (mode) {
    case 0:
      strip.clear();
      strip.show();
      break;
    case 1:
      if ((millis() - previousMillis) >= interval) {
        previousMillis = millis();
        colorWipeGREEN();
        break;
      }
    case 2:
      if ((millis() - previousMillis) >= interval) {
        previousMillis = millis();
        colorWipeRED();
        break;
      }
  }
}

void colorWipeGREEN() {
  strip.setPixelColor(currentPixel, 0, 255, 0);
  strip.show();
  currentPixel++;
  if (currentPixel == NUM_PIXELS) {
    currentPixel = 0;
  }
}

void colorWipeRED() {
  strip.setPixelColor(currentPixel, 255, 0, 0);
  strip.show();
  currentPixel++;
  if (currentPixel == NUM_PIXELS) {
    currentPixel = 0;
  }
}

Dein Programm erzeugt eine Warnung:

42:7: warning: this statement may fall through [-Wimplicit-fallthrough=]
       if ((millis() - previousMillis) >= interval) {
       ^~

Mit zwei break; hinter der Klammer, ist der Compiler glücklich.

Wer es etwas kürzer mag:

#include <Adafruit_NeoPixel.h>

#define BUTTON_GREEN   2
#define BUTTON_RED     3
#define NUM_PIXELS     6

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXELS, 9, NEO_GRB + NEO_KHZ800);

uint32_t farbe = 0;

unsigned long interval = 500;
unsigned long previousMillis = 0;

uint16_t currentPixel = 0;

void setup() {
  currentPixel = 0;
  strip.setBrightness(50);
  pinMode(BUTTON_GREEN, INPUT_PULLUP);
  pinMode(BUTTON_RED, INPUT_PULLUP);
  strip.begin();
  strip.show();
}

void loop() {
  if (digitalRead(BUTTON_GREEN) == LOW) {
    farbe = 0x00FF00;  // Grün
    currentPixel = 0;
    strip.clear();
  } else if (digitalRead(BUTTON_RED) == LOW) {
    farbe = 0xFF0000;  // Rot
    currentPixel = 0;
    strip.clear();
  }
  colorWipe();
}

void colorWipe() {
  if ( ((millis() - previousMillis) >= interval) && (currentPixel < NUM_PIXELS)) {
    previousMillis = millis();
    strip.setPixelColor(currentPixel, farbe);
    strip.show();
    currentPixel++;
  }
}
1 Like

Erstmal ein großes Dankeschön an alle für eure Hilfe und eure kostbare Zeit.

@wwerner

Chat GPT hatte ich nicht genutzt. Hatte mich an einigen Beispielen so durch gehangelt.
Ist ja auch das erste Projekt und hab noch sehr viel zu lernen.

Bei deinem Code bekomm ich keine Fehlermeldung. Eingänge der Schalter können nicht gesetzt bleiben (code funktioniert nur mit Tastern). Grün läuft komplett durch und dann leuchtet immer eine LED an verschiedenen Stellen rot und wechselt wieder auf grün. Rot funktioniert ohne Probleme.

@agmue

Das mit den NEO_GRBW weiß ich. Ich hatte die liegen und teste damit. Die Stripes sind noch unterwegs.

Dein Code funktioniert nur das ich die Eingänge der Schalter nicht gesetzt lassen kann. Wenn ich die Eingänge taste funktioniert der Code. Ich wollte mit einem Wechselschalter die Masse zwischen den beide Eingängen hin und her schalten. Kann man wahrscheinlich auch auch nur mit einem Eingang lösen weil man ja wieso den Status abfragt.

Ist es eigentlich mit millis auch möglich das Licht von der Mitte nach beiden Seiten gleichzeitig nach aussen laufen zu lassen. Oder von beiden Seiten zur Mitte und dann bleibt es an?

Mit Delay hatte ich das ja hinbekommen.

So hatte ich Dich verstanden, so wollte ich das.

Ja, ist es. Es gibt unzählige Animationen, die möglich sind!

Bei mir hat es eine ganze Zeit gedauert, bis der Knoten bezogen auf die Verwendung von millis geplatzt ist, aber dann erscheint es plötzlich ganz einfach.

Eventuell hilft Dir meine Anleitung: Endlicher Automat mit millis() .

Sorry, dann hatte ich mich wegen der Schallter falsch ausgedrückt.

Endlicher Automat schau ich mir mal an.

In der SW Entwicklung muss man ganz genau beschreiben, was hat, und was man will. Also: hat man Schalter oder Taster. Was soll wann passieren? Und in meinem Code waren 2 breaks an der falschen Stelle.

Ich habe einen Wechsel Schalter. Mit dem wollte ich die Masse vom Arduino wieder auf die Eingänge schalten. Der Schalter sollte an PIN2 und 3 angeschlossen werden. Arduino wird eingeschaltet PIN2 ist auf Masse, Lauflicht läuft in FarbA von LED1 nach LED6 alle LEDs bleiben an. Schalter wird betätigt PIN2 führt keine Masse mehr sondern PIN3. Lauflicht läuft in FarbeB von LED1 nach LED6.
Wenn der Schalter wieder betätigt wird das selbe von vorne.

Oder das Lauflicht von Mitte nach außen (LED3 nach LED1 und LED4 nach LED6 in FarbeA. Alle LEDs leuchten in FarbeA. Schalter wird betätigt Lauflicht von beiden Seiten außen nach innen (LED1 nach LED3 und LED6 nach LED4 in FarbeB. Alle LEDs leuchten in FarbeB.

Sowas wollte ich gerne mit millis lösen.

Mit ein paar Änderungen geht das:

#include <Adafruit_NeoPixel.h>

#define BUTTON_GREEN   2
#define BUTTON_RED     3
#define NUM_PIXELS     6

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXELS, 9, NEO_GRB + NEO_KHZ800);

uint32_t farbe = 0;
const unsigned long interval = 500;
unsigned long previousMillis = 0;

uint16_t currentPixel = 0;

void setup() 
{
  currentPixel = 0;
  strip.setBrightness(50);
  pinMode(BUTTON_GREEN, INPUT_PULLUP);
  pinMode(BUTTON_RED, INPUT_PULLUP);
  strip.begin();
  strip.show();
}

void loop() 
{
  if ( !digitalRead(BUTTON_GREEN) && (farbe != 0x00FF00) ) 
  {
    farbe = 0x00FF00;  // Grün
    currentPixel = 0;
    strip.clear();
  } 
  else if ( !digitalRead(BUTTON_RED) && (farbe != 0xFF0000) ) 
  {
    farbe = 0xFF0000;  // Rot
    currentPixel = 0;
    strip.clear();
  }
  animation();
}

void animation() 
{
  if ( ((millis() - previousMillis) >= interval) && (currentPixel < NUM_PIXELS / 2)) 
  {
    previousMillis = millis();
    strip.setPixelColor(currentPixel, farbe);
    strip.setPixelColor(NUM_PIXELS - currentPixel - 1, farbe);
    strip.show();
    currentPixel++;
  }
}

Guten Abend, und vielen Dank. Ich kann das leider erst Montag Abend testen, da wir über Ostern weggefahren sind. Melde mich auf jedenfall. Ich wünsche euch allen schöne Ostern.

Danke für die Rückmeldung, frohe Festtage!

Wenn Du zwei Streifen an zwei Pins hängst, kann jeder Streifen auch ein anderes Muster zeigen:

#include <Adafruit_NeoPixel.h>

#define BUTTON_GREEN   2
#define BUTTON_RED     3
#define NUM_PIXELS     144

Adafruit_NeoPixel stripA = Adafruit_NeoPixel(NUM_PIXELS, 8, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel stripB = Adafruit_NeoPixel(NUM_PIXELS, 9, NEO_GRB + NEO_KHZ800);

uint32_t farbe = 0;
const unsigned long interval = 100;
unsigned long previousMillis = 0;

uint16_t currentPixel = 0;

void setup() 
{
  currentPixel = 0;
  stripA.setBrightness(50);
  stripB.setBrightness(50);
  pinMode(BUTTON_GREEN, INPUT_PULLUP);
  pinMode(BUTTON_RED, INPUT_PULLUP);
  stripA.begin();
  stripA.show();
  stripB.begin();
  stripB.show();
}

void loop() 
{
  if ( !digitalRead(BUTTON_GREEN) && (farbe != 0x00FF00) ) 
  {
    farbe = 0x00FF00;  // Grün
    currentPixel = 0;
    stripA.clear();
    stripB.clear();
  } 
  else if ( !digitalRead(BUTTON_RED) && (farbe != 0xFF0000) ) 
  {
    farbe = 0xFF0000;  // Rot
    currentPixel = 0;
    stripA.clear();
    stripB.clear();
  }
  animation();
}

void animation() 
{
  if ( ((millis() - previousMillis) >= interval) && (currentPixel < NUM_PIXELS / 2)) 
  {
    previousMillis = millis();
    stripA.setPixelColor(currentPixel, farbe);
    stripA.setPixelColor(NUM_PIXELS - currentPixel - 1, farbe);
    stripA.show();
    stripB.setPixelColor((NUM_PIXELS / 2) + currentPixel, farbe);
    stripB.setPixelColor((NUM_PIXELS / 2) - currentPixel - 1, farbe);
    stripB.show();
    currentPixel++;
  }
}
1 Like

Hallo agmue, funktioniert super. Vielen Dank :+1:
Muss ich mir jetzt genauer anschauen und daraus lernen.