newbiefrage: WS2812b geschachtelte for-Schleife / Buttonabfrage

Hallo zusammen,

ich habe seit Kurzem einen Arduino UNO im Einsatz und bin einige Beispiele durchgegangen. Mein Ziel ist es mehrere LED-Streifen(WS2812b) auf einer Treppe von Stufe zu Stufe mit einer kurzen Pause einzublenden.

Dafür dachte ich an eine geschachtelte for-Schleife (1x je Stufe, 1x je LED auf der Stufe). Ich bin etwas eingerostet, was die Programmierung angeht. Folgender Code ergibt beim Kompilieren eine Endlosschleifen-Warnung. Ich kann leider nicht nachvollziehen, wo hier mein Fehler liegt.

Könnt mir einen Denkanstoss geben, wo mein Fehler liegt, bzw. wo ich mich in das Thema besser einlesen kann? Evtl. liegt es ja auch an der Art der Vergabe der Variablen!?

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

#define PIN            6
#define NUMPIXELS      115
int leds_pro_stufe[] = { 58, 57 }; // Anzahl LEDs pro Stufe
int stufen = sizeof(leds_pro_stufe);
int delayval = 1000;

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
void setup() {
  pixels.begin(); // This initializes the NeoPixel library.
}

void loop() {
 for(int x=0;x<stufen;x++){
  for(int i=0;i<=leds_pro_stufe[x];i++){
    pixels.setPixelColor(i, pixels.Color(120,40,10)); // 
  }
    pixels.show();
    delay(delayval);
 }
}

Das ist doch bestimmt nicht Dein komplettes Anliegen. Da sollen doch bestimmt noch auslösende Sensoren mitspielen oder?
Dann sieht die Sache ganz anders aus, also bitte komplette Informationen.

Das ist falsch:

int leds_pro_stufe[] = { 58, 57 }; // Anzahl LEDs pro Stufe
int stufen = sizeof(leds_pro_stufe);
// richtig:
int stufen = sizeof(leds_pro_stufe) / sizeof(leds_pro_stufe[0]);

sizeof liefert die Länge in Bytes, int ist 2 Byte groß.

Gruß Tommy

Hi

Auch werden bei der 2.ten Stufe die LEDs der ersten Stufe umgefärbt.
Das i fängt wieder bei 0 an.

Sofern Du nicht wirklich Einzel-Streifen pro Stufe machen willst, sondern so viele LED zusammen hängst, wie der Arduino verdauen kann, wirst Du pro Stufe einen Offset mithalten müssen.
Deine Stufe 1 geht von Led 0 bis 57 (58 Stück).
Somit fängt Deine Stufe 2 bei 58 an und hat 'x' LEDs.
Stufe 3 wieder + Anzahl der LEDs der vorherigen Stufe ...

Du wirst bei einem Uno wohl über 300 NeoPixel kommen, dann ist der Speicher aber auch voll.
Dann wirst Du ggf. einen weiteren Uno verbauen, Der auch noch etwas vom Ersten entfernt angesiedelt werden wird - der Abstand zur ersten LED sollte nicht zu groß werden.

Oder Du nimmst einen Arduino, Der von vorne herein mehr Speicher hat - bis wie viele LEDs z.B. der Mega mag, müsste man Mal durchrechnen (pro LED 3 Byte, die Lib will etwas Platz und das Programm wird hier auch etwas RAM beanspruchen).

MfG

Danke schon einmal, für Eure Antworten!

Das Verständnis der verschiedenen Variablentyp-Längen fehlt mir scheinbar tatsächlich: da muss ich mich noch einmal einlesen. :o

Der Code ist natürlich nicht komplett, sondern ich strauchle schon bei der geschachtelten for-Schleife, weil beim Kompilieren die Warnung vor einer Endlosschleife kommt. Alles Weitere soll dann folgen (Auslösen, durch einen angeschlossenen Bewegungsmelder)

Genau, den Offset werde ich dann weitertragen müssen, was bei meinem Code-Schnipsel noch nicht berücksichtigt ist. Dem würde ich mich im nächsten Schritt widmen wollen.

Das ich mit meinem Vorhaben (15 Stufen zu je 57-73 LEDs) auch an die Speicher-grenzen stoßen würde, hätte ich tatsächlich auch nicht gedacht. Da werde ich wohl in den kommenden Tagen noch einige Recherche anstellen müssen.

Also wieder einen Schritt zurück und nicht den 3. vor dem 1. machen :confused:

Danke schonmal! Die nächsten Abende werden einiges an Lektüre erfordern :wink:

Besser:

int leds_pro_stufe[] = { 58, 57 }; // Anzahl LEDs pro Stufe
int stufen = sizeof(leds_pro_stufe)/sizeof(leds_pro_stufe[0]);

Noch besser:

byte leds_pro_stufe[] = { 58, 57 }; // Anzahl LEDs pro Stufe
byte stufen = sizeof(leds_pro_stufe)/sizeof(leds_pro_stufe[0]);

jeti79:
Das ich mit meinem Vorhaben (15 Stufen zu je 57-73 LEDs) auch an die Speicher-grenzen stoßen würde, hätte ich tatsächlich auch nicht gedacht. Da werde ich wohl in den kommenden Tagen noch einige Recherche anstellen müssen.

Du kannst mehrere Arduinos verwenden, die dann untereinander beispielsweise mittels CanBus kommunizieren müssen. Oder Du verwendest einen Teensy 3.2 oder etwas in der Art.

Wenn möglich, empfehle ich Dir APA102 anstelle WS2812.

Die LEDs möchten ca. 60 A Strom haben. Auch die notwendige Dicke der Kabel kann einen erstaunen.

Danke, für Deine Hilfe: den Code werde ich heute Abend mal erneut angehen. :sunglasses:

Was die Speichernutzung angeht:

Ist es möglich, alle LEDs einer Stufe als eine Art Array anzusprechen und so 15 Speicherstellen zu verwenden, anstatt allen 900+x? (Ich plane aktuell keine unterschiedlichen Effekte innerhalb der Stufe, sondern die gleiche Farbe für jede LED). Ansonsten würde ich mir mal was mit mehr Speicher (zB den Teensy) ansehen. Mit mehreren Arduinos würde ich jetzt ungern arbeiten wollen.
Nur fällt es mir schwer, die benötigte Speichermenge zu bestimmen. :roll_eyes:

Die WS2812b habe ich bereits massenhaft zu Hause. Deshalb bin ich mit denen gestartet. Bzgl. der Verdrahtung konnte ich schon in einem Video sehen, dass man die LEDs nicht alle in Reihe schalten sollte, sondern auch Parallel anschließen soll, damit es dort keine Probleme gibt. :slight_smile:

Wir betreiben die LEDs in einer Art "Warmweiss", wo wir immerhin schonmal bei ca. 25mA pro LED landen. Das haben wir vorab geprüft, um ein passendes Netzteil auszuwählen.

jeti79:
Ist es möglich, alle LEDs einer Stufe als eine Art Array anzusprechen und so 15 Speicherstellen zu verwenden, anstatt allen 900+x?

Man weiß nie, was es so alles gibt, aber bekannt ist es mir nicht.

jeti79:
Nur fällt es mir schwer, die benötigte Speichermenge zu bestimmen. :roll_eyes:

Je LED ein Byte, je Lichtpunkt (pixel) drei Bytes. 15x73x3 Bytes = 3.285 Bytes

Schaue Dir bitte auch die Bibliothek FastLED an, die möglicherweise besser geeignet ist.

Schaue Dir bitte auch die Bibliothek FastLED an, die möglicherweise besser geeignet ist.

Danke - werd ich mir nachher ansehen!

Hi

Ok, schon vorhanden ist ein starkes Argument.
Wobei die Ansteuerung 'normaler' RGB-LED eher trivial ist und mit einem 16x-PWM-Modul (I²C) erledigt werden kann.
Auch kosten 'normale' RGB-Stripes kaum Geld.

Das Problem bei Deinem gemessenem Strom: Dein DMM (digitales Multi Meter) zeigt Dir einen gemittelten Wert an.

  1. kann Es gar nichts Anderes
  2. kann Es kein PWM erfassen, sondern glättet das Signal

Jede einzelne LED im WS2812B-Stripe (auch in APA oder wie Sie Alle heißen) hat einen eigenen µC, Der nur die drei(oder 4) LEDs ansteuert und auf neue Daten wartet.
Keiner der Kontroller 'weiß' etwas von den Anderen - würde Ihm aber ja auch nicht helfen.
Theoretisch ist es so möglich, daß ALLE LED zur gleichen Zeit AN sind.
Das zwar nur Millisekunden, aber in der Zeit werden die 54A tatsächlich gezogen.
Im Mittel bist Du wieder bei den von Dir gemessenen ~25mA, aber leider nur im Mittel.
Da die LEDs sehr schnell takten, wären keramische Kondensatoren (Abblock-Kondensatoren) meine Wahl, Die liefern dem IC Strom, wenn Er Den braucht.
Nur, der IC braucht viel Strom und auf dem Stripe wird man kaum zusätzliche C's anbringen können.

Man könnte sich den Ausgabe-Code der benutzten Lib anschauen, ob man Da jede LED einfach 60x ausgeben kann - bei den APA102 sollte Das 'mit Bordmitteln' gehen - einfach die Ausgaberoutine 60x in einer FOR-Schleife ausführen und erst dann zur nächsten LED weiter gehen.
Bei den WS2812B ist die Ausgabe definitiv in Assembler in der Lib drin - Das ist schwere Kost, zumindest habe ich noch nicht verstanden, wie der Assembler-Code an die Arduino-Variablen kommt.
Der Assembler-Code selber ist nicht so kompliziert (bei AVR-Prozessoren ist die Menge der Befehle auch sehr überschaubar).

MfG

Danke, für die ausführliche Antwort! So verstehe sogar ich das ;D

.. natürlich ist die Aussage dahinter für mich nicht die Beste, aber da muss ich im Zweifel wohl doch zum nächst größeren Netzteil greifen. PWM Module kenne ich selbst jetzt noch nicht - da würde ich mich im Zweifel belesen müssen. ::slight_smile:

Wie ich das Alles so lese, ist mein Vorhaben gar nicht so trivial, wie ich es mir erhofft habe- wohl wissend, dass meistens irgendwelche Stolpersteine da sind, die man vorher nicht erahnt. Aber man wächst ja bekanntlich mit seinen Aufgaben und das Thema muss jetzt nicht zwingend in einer Woche abgearbeitet sein... 8)

Ich habe heute (erstmal noch ohne FastLED) weiter am Code gebastelt und nach Eurer Korrektur funktioniert das Script zumindest mit ca. 240 LEDs schonmal wie es soll!

Je LED ein Byte, je Lichtpunkt (pixel) drei Bytes. 15x73x3 Bytes = 3.285 Bytes

Oder Du nimmst einen Arduino, Der von vorne herein mehr Speicher hat - bis wie viele LEDs z.B. der Mega mag, müsste man Mal durchrechnen (pro LED 3 Byte, die Lib will etwas Platz und das Programm wird hier auch etwas RAM beanspruchen).

Wie äußert sich eigentlich genau, dass der Speicher voll ist? Mein/Euer verdacht ist, ja dass der UNO da schnell am Ende ist: Wenn ich mit der Variable "NUMPIXELS" spiele (die ja scheinbar den Speicher für die LEDs reserviert) reicht diese scheinbar bis 600, da dann da Script noch komplett ausgeführt wird, danach passiert einfach gar nichts. Die Kompilierinfo sagt:

Der Sketch verwendet 2504 Bytes (7%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 76 Bytes (3%) des dynamischen Speichers, 1972 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

Was für mich eigentlich danach klingt, dass da noch massig Luft wäre.

Parallel habe ich mir den Arduino Mega mal angesehen - der scheint ja ein bisschen mehr Power zu haben (256kb statt 32kb, wenn das der entscheidende Speicherbereich ist).

Den Uno würde ich dann für LEDs im Schlafzimmer nutzen - ca. 4m...

Hier mein aktueller Code, der als Nächstes dann um die Bewegungsmelder erweitert werden soll

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

int leds_je_stufe[] = {0, 58, 57, 58, 58,58, 63, 73, 59, 59, 73, 67, 60, 59, 59, 59 }; // Anzahl LEDs pro Stufe
int stufen = sizeof(leds_je_stufe)/ sizeof(leds_je_stufe[0]);                          //Anzahl Treppenstufen

#define NUMPIXELS      600
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

int delayval = 1250;  // delay delay in Millisekunden
int startpixel = 0 ;  // Pixel am Anfang des aktuellen Streifens
int endpixel = 0;     // Pixel am Anfang des aktuellen Streifens
int i = 0 ;           // Zählvariable hier vorab initialisiert

void setup() {
  pixels.begin();
}

void loop() {

for(int x=1;x<stufen;x++){
  startpixel=endpixel;
  endpixel=startpixel+leds_je_stufe[x];
  for(i=startpixel;i<endpixel;i++){
    pixels.setPixelColor(i, pixels.Color(100,50,10));
    }
   pixels.show();
   delay(delayval);
 }
}

Hi
Diese Ausgabe

Der Sketch verwendet 2504 Bytes (7%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 76 Bytes (3%) des dynamischen Speichers, 1972 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

enthält NICHT den Platz der LEDs.
Dieser Platz wird erst beim Start des Programm 'angefordert'.

Aber: Versuch's doch einfach!
Lasse einen Uno 600 NeoPixel antreiben, ändere die Farben der 600 Pixel und schaue, wie weit Du dabei kommst.

Mit etwas Glück findest Du den Weg, wie man doch mehr NeoPixel an den Uno bekommt - habe Da wohl meine Zweifel, soll Dich aber nicht Bremsen!

MfG

Ich hab mich evtl. etwas doof ausgedrückt:

Ich habe bisher ca. 240 LEDs physikalisch dran, das funktioniert sehr gut. (eine Reihe einblenden, x sek warten, nächste Reihe an, bis 4 Reihen voll sind.)

Wenn ich mit dem Wert "NUMPIXELS" spiele, funktioniert das, bis ich den Wert auf über 600 ändere. Daher vermute ich, dass das der Wert ist, bis zum dem ich einen UNO ausreizen könnte.

Ich habe mir den Mega mal dazu bestellt - der kann ja nicht schaden :wink:

Hi

jeti79:
Ich habe mir den Mega mal dazu bestellt - der kann ja nicht schaden :wink:

Ein wahres Wort gelassen ausgesprochen!
Habe noch nie verstanden, wie man nur EINEN Arduino kaufen kann ...
(spätestens nach der ersten blinkenden LED ist dieser Arduino ja beschäftigt ...)

MfG

postmaster-ino:
HiEin wahres Wort gelassen ausgesprochen!
Habe noch nie verstanden, wie man nur EINEN Arduino kaufen kann ...
(spätestens nach der ersten blinkenden LED ist dieser Arduino ja beschäftigt ...)

MfG

Wird wohl an der Unwissenheit liegen (in meinem Fall zumindest).
Ich hatte das Treppenstufen-Projekt zwar im Hinterkopf, dachte aber nicht, dass ich mehr- oder weniger sofort ins Projekt einsteigen kann.

Daher habe ich nur etwas zum Thema gelesen und da ich von sehr wenig code ausgegangen bin, konnte ich mir im ersten Moment nicht vorstellen, dass ich dort einen UNO ausreizen könnte. So dachte ich, dass ich erstmal einsteige, ein paar Tutorials probiere, bevor ich direkt mit den LEDs loslege... Die Rechnung habe ich aber nicht mit dem Speicherbedarf der einzelnen LEDs gemacht :smiley:

Aber der UNO ist ja nicht umsonst angeschafft: da ich noch ne MENGE zu lernen habe, werden es tendentiell eher noch ein paar mehr :smiley: :smiley:

jeti79:
Wie äußert sich eigentlich genau, dass der Speicher voll ist?

Merkwürdige Dinge passieren, meist stürzt der µC ab.

Die Adafruit-Bibliothek holt sich den Speicher erst zur Laufzeit, das kann der Compiler noch nicht wissen.

Du könntest dies probieren:

// Quelle: http://jeelabs.org/2011/05/22/atmega-memory-use/
int freeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

Ich habe es noch nicht probiert, aber mittels setPin(uint8_t p) kann man einen anderen Pin festlegen. Zwei oder drei Stufen an einen Pin, dann kannst Du die Gruppen nacheinander ansprechen. Ohne Ansteuerung machen die LEDs unverändert weiter. Speicher benötigst Du nur für eine Gruppe. Nachteil: Die Entfernung UNO zum ersten Pixel darf nicht zu lang sein und kontinuierliche Animationen dürften kompliziert sein.

Immer noch meine Empfehlung: APA102, mehrere Nanos, MCP2515 CAN Bus Modul
oder
APA102 mit einem Teensy 3.21).

Die Links dienen der Ilustration.


Anm.:
Bei 120 realen Lichtpunkten und 1095 im Programm (TwinkleFOX von Mark Kriegsman mit FastLED) festgelegt:

Der Sketch verwendet 12472 Bytes (4%) des Programmspeicherplatzes. Das Maximum sind 262144 Bytes.
Globale Variablen verwenden 4392 Bytes (6%) des dynamischen Speichers, 61144 Bytes für lokale Variablen verbleiben. Das Maximum sind 65536 Bytes.

Hi

agmue:
, aber mittels setPin(uint8_t p) kann man einen anderen Pin festlegen. Zwei oder drei Stufen an einen Pin, dann kannst Du die Gruppen nacheinander ansprechen. Ohne Ansteuerung machen die LEDs unverändert weiter. Speicher benötigst Du nur für eine Gruppe. Nachteil: Die Entfernung UNO zum ersten Pixel darf nicht zu lang sein und kontinuierliche Animationen dürften kompliziert sein.

Das klingt doch echt interessant.
An weiter entfernte Stufen kommen halt 'ein paar' Zwischen-Pixel, Die man dann berücksichtigen muß.

Hat schon Mal wer probiert, wie hoch der Widerstand werden muß, damit die Daten nicht an der ersten LED ankommen?
Denke gerade in die Richtung Analog-Switch ...

MfG

postmaster-ino:
Denke gerade in die Richtung Analog-Switch ...

Oder Quad buffer/line driver 74HC125. Als Levelshifter Teensy - APA102 verwende ich 74LS245.

Für lange Leitungen kann man schön RS485 verwenden, diese Hardware könnte man auch mal für LEDs probieren.

Puh, das wird mir grad ein bisschen zu hoch :smiley:

Ich bin ja schon froh, dass ich meine 4 LED-Streifen am laufen habe und freue mich, wenn der MEGA ankommt, damit ich (hoffentlich) auch alle anderen LEDs ansteuern kann.

Dann widme ich mich der Auslöser-Thematik. Tutorials gibts ja genügend :wink:

Zwischenzeitlich habe ich die Schaltung mit dem UNO schon mit 4 LED-Leisten am Laufen gehabt. Die Schaltung am Arduino habe ich um einen Taster erweitert. der die Schleife auslöst.
Die LEDs werden mit einem delay nach jeder Stufe eingeschaltet und am Ende nach einem delay wieder nach einander ausgeschaltet.

Vorgestern Abend habe ich endlich den Arduino Mega bekommen und wir haben die LED-Leisten komplett neu angeschlossen:

je LED-Leiste (ca. 57-73 LEDs) mit 1,5² Kabel an einen Strang 4² Kabel (Jeweils plus und Masse). also nicht in Reihe angeschlossen, sondern alle parallel. Die Datenleitung ist dagegen (0.5² Kabel) komplett (in Pfeilrichtung)durchverbunden. Die Schaltung auf dem Arduino ist gleich geblieben.

Allerdings haben wir damit scheinbar die LED-Streifen geschrottet. Daher meine Verständnisfrage:

Muss die Stromversorgung auch immer in Pfeilrichtung eingebracht werden?
Wir haben nämlich jetzt immer am Ende der Streifen eingespeist und dabei die Pfeilrichtung missachtet - haben wir damit an den Dioden einen Kurzschluss erzeugt?