In einer Klasse Methoden mehrfach instantiieren?

knautschkissen:
... Blick auf den speicher werfen ...

Ich kenne diese LED-Streifen ja nicht und weiß demzufolge nicht, wie viel Speicher allein die Bibliothek zur Ansteuerung benötigt.

Über wie viele LEDs reden wir denn?

Gruß

Gregor

Hallo
Es geht im momentanen projekt um einen LED Streifen mit 300 LEDs. Ein Beispielprojekt aus der Adafruit NeoPixel lib die ich nutze belegt:
“Der Sketch verwendet 3376 Bytes (10%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 41 Bytes (2%) des dynamischen Speichers, 2007 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.”
das verändert sich nicht wenn ich die Anzahl der LEDs variiere.
Mein Modell benötigt 21 Snippets, die längen variieren zwischen min 1 und Max 63 Pixel.
Die Werte sind mir also beim Compilieren bekannt und ein dynamisches verändern zur laufzeit der Snippet konfiguration ist nicht vorgesehen. Halt nur das Muster, die Richtung, Geschwindigkeit und Farbe des Lauflichtes ändern sich. zu vrschwänderisch mit Speicher darf ich allerdings nicht umgehen, weil der Arduino parallel auch noch 4 RFID Reader auswerten muss mit deren Hilfe ich um das Modell der Biogasanlage eine art Frage Antwortspiel mit RFID Karten umsetzen will. Jenachdem welche Frage und Antwort gegeben wird reagieren die Lauflichter. Das ist ein Schülerprojekt das ich betreue und will daher den Umgang mit den LEDs möglichst einfach halten, damit die Schüler (10. Klasse Gymnasium) sich auf die Abläufe konzentrieren können und nicht mit der Ansteuerung kämpfen müssen.

Globale Variablen verwenden 41 Bytes (2%)

Da sind wohl keine "snippets" enthalten und kein Speicherplatz für die aktuelle Farbe von 300 RGB leds.
Evtl. wird dein Objekt My_ARgbStrip myARgbStrip(300,10,6); wegoptiomiert, weil es gar nicht verwendet wird.

Du hast außerdem die

warning: large integer implicitly truncated to unsigned type [-Woverflow]

bei const byte Pixel=300;
übersehen.

Hi

Das Array für die Pixel wird erst zur Laufzeit reserviert, deshalb tauchen diese Bytes auch nicht beim Kompilieren auf.
Spaßeshalber kannst Du Das mit verschieden großen Größen ausprobieren.
Jede LED braucht 3 Byte - somit müsste eine Änderung um 1 den belegten Platz um 3 Byte ändern - macht's aber nicht.
Du kannst auch 100 ... 200 ... 1000 Pixel anlegen - Das fällt Dir erst auf die Füße, wenn der Arduino unvorbereitet sich selber den Speicher unter den Füßen weg zerrt.
Auszug aus der Adafruit NeoPixel Library:

void Adafruit_NeoPixel::updateLength(uint16_t n) {
  if(pixels) free(pixels); // Free existing data (if any)

  // Allocate new data -- note: ALL PIXELS ARE CLEARED
  numBytes = n * ((wOffset == rOffset) ? 3 : 4);
  if((pixels = (uint8_t *)malloc(numBytes))) {
    memset(pixels, 0, numBytes);
    numLEDs = n;
  } else {
    numLEDs = numBytes = 0;
  }
}

Das ist die ÄNDERUNG der Stripe-Länge - wie der Code durchlaufen wird beim normalen Erstellen des Stripe, habe ich nicht ganz durchblickt - ist wesentlich weiter unten in der .cpp (ab 1293).

MfG

Mal eine Zwischenfrage eines Neopixel-Unkundigen: Wieso muss denn überhaupt die ganze Pixelreihe im RAM liegen? Können die Daten nicht „on the fly“ erzeugt und übertragen werden?

Falls es nicht anders geht: Die neuen Nanos haben einen geradezu pervers großen Speicher, allerdings laufen die z. T. mit 3,3 Volt.

Gruß

Gregor

PS: Z. B. Arduino Nano Every | Arduino Official Store (6 kB SRAM, 5 V), Arduino Nano 33 BLE with headers | Arduino Official Store (256 kB, 3,3 V)

Hi

Du bekommst das Timing nicht hin - die Daten der NeoPixel werden so schnell ausgegeben, daß Du in einzelne Takte rechnen musst - deshalb sind Interrupts dabei auch gesperrt, weil sonst alleine millis() Dir die Übertragung abreißen lassen würde.
Bei den WS2812B ist das Timing extrem kritisch, da der Takt eben eingehalten werden MUSS.
Bei den APA (102 oder 106 - Eines ist ein WS2812B-Äquivalent, das Andere hat getrennte DATA und TAKT-Leitung) ist Das eben wegen des getrennt übertragenen Takt nicht (so?) kritisch - hatte ich aber noch nicht in den Fingern und das DaBla auch nicht soweit studiert, um die End-Bedingung Derer zu kennen.
Bei den WS2812B ist's eine Zeit keine neuen Daten - Das bekommen alle LEDs mit, Die bereits Daten empfangen haben - entweder, weil Sie gerade die Daten bekommen, oder weil Sie die Daten danach weiter leiten - und schwupps, schalten die LED alle zusammen um.

MfG

Hallo
Die Belegung des Speichers stammt aus einem beispielprojeckt aus der Adafruit NeoPixel Bibliothek, in der nur mithilfe der bibo die leds angesprochen werden. das hat noch nichts mit meiner umsetzung dessen zu tun.
An dieser Stelle wollte ich mich übrigens für die Hilfe bedanken. Der Aufbau steht und ich muss “nurnoch” umsetzen wie ich die Lauflichter weiterschiebe, aber das ist bitgeschupse. Ich belege damit ca 30% des dynamischen Speichers wenn ich als Beispiel mit 10 snippets arbeite.
Wen es interessiert hier die .h dateien.

#ifndef My_ARgbStrip_h
#define My_ARgbStrip_h
#include "Arduino.h"
#include <Adafruit_NeoPixel.h>
#include "My_ARgbSnippet.h"

class My_ARgbStrip
{
  private:
    Adafruit_NeoPixel strip;
    int _pixel;
    byte _pin;
    byte _snipCount=0;
    My_ARgbSnippet _Snippets[20];
    
    
    
    
  public:
    My_ARgbStrip(int pixel, byte pin);
    bool init();//im Setup aufrufen um NeoPixel zu starten
    void addSnippet(byte Nummer, byte Adresse, byte Pixel);//Konfiguration der Snippets
    void showSnipped(byte Nummer);//Stelle Snippet auf Strip dar
    void showStrip();//Stelle alle Snippets auf dem Strip dar
    void setSnippetColor(byte Nummer, byte r, byte g, byte b);//Setze Farbe
    void setSnippetDesign(byte Nummer, byte design);//Setze Muster
    void setSnippetDelay(byte Nummer, int _delay);//Setze verzögerung bis Muster weitergeschoben wird
    bool calculate(unsigned long *timestamp);//Prüfe und Berechne Snippets wenn delay abgelaufen
};
#endif
#ifndef My_ARgbSnippet_h
#define My_ARgbSnippet_h
#include "Arduino.h"

class My_ARgbSnippet
{
  private:

    int _adresse;//Startadresse des Snipet
    int _pixel;//Anzahl Pixel im Snippet
    byte _r;//Red
    byte _g;//Green
    byte _b;//Blue
    byte _bright;//Brightness
    byte _muster;//Darzustellendes Muster
    int _delay;//Geschwindigkeit Lauflicht
    int  _actualPosition;//Aktuelle Position des Musters im Snippet
    bool _dir;//Richtung Lauflicht
    unsigned long _nextStamp;//Zeit nächster Schritt
    byte _distance=1;//Schrittweite
    byte _repeats=1;//Vervielfältigung Muster
    
    

  public:
    My_ARgbSnippet();//Konstruktor
    void setupSnippet(int Adresse, int Pixel);//Setup Snippet
    void setColor(byte r, byte g, byte b);//Setze Farbe
    void setDesign(byte muster);//Setze Muster
    void setDelay(int setdelay);//Setze Geschwindigkeit Lauflicht
    bool execute(unsigned long *timestamp);//Zeitstempel(millis() im loop)und entscheidung ob muster sich ändert oder nicht
    //void setBright(byte bright);//Setze Helligkeit
    void setDir(bool dir);//Setze Richtung
    void getSnippet(int *snipdata);// gebe Farbe und Helligkeit der leuchtenden LEDs im Snippet zurück
    int getAdresse();//Adresse des Snippet in String
    int getPixel();//Anzahl der Pixel
    int getPosition();//aktuelle Stposition des Musters im Snippet
    void setDistance(byte distance);//Setze Schrittweite
    void setRepeats(byte repeats);//Setze Vervielfältigung Muster

};
#endif

fertig bin ich noch lange nicht, aber das Grundgerüst steht erstmal und scheint bislang zu funktionieren.

Danke Nochmal

gregorss:
Mal eine Zwischenfrage eines Neopixel-Unkundigen: Wieso muss denn überhaupt die ganze Pixelreihe im RAM liegen? Können die Daten nicht „on the fly“ erzeugt und übertragen werden?

Falls es nicht anders geht: Die neuen Nanos haben einen geradezu pervers großen Speicher, allerdings laufen die z. T. mit 3,3 Volt.

Gruß

Gregor

PS: Z. B. Arduino Nano Every | Arduino Official Store (6 kB SRAM, 5 V), Arduino Nano 33 BLE with headers | Arduino Official Store (256 kB, 3,3 V)

Soweit ich weiß liegt von Neopixel nicht viel im Ram erst recht nicht der ganze Strip.
Ich hatte auch nicht vor den ganzen Strip im Ram zu spiegeln. Mein Ziel ist es eine Bibliothek zu schreiben, mit der ich mir den Strip in"beliebig"(bis zu 20) viele virtuelle Streifen zerlegen kann auf denen verschiedene Lauflichter dargestellt werden. Die Lauflichter erzeuge ich durch Adresse/Länge und schiebe den so entstehenden Strich nach einer definierbaren Zeit einfach eine Adresse weiter. Am Ende rufe ich nurnoch die NeoPixel auf, schreibe in einer Forschleife die (länge = Anzahl) Pixel auf die von Adresse weiterzählenden Pixel und lösche die vorhergehenden, die ich aufgrund der bekannten Schrittweite ja kenne. Und mit show wird das ganze dann auf dem Strip übertragen.

postmaster-ino:
Hi

Du bekommst das Timing nicht hin - die Daten der NeoPixel werden so schnell ausgegeben, daß Du in einzelne Takte rechnen musst - deshalb sind Interrupts dabei auch gesperrt, weil sonst alleine millis() Dir die Übertragung abreißen lassen würde.
Bei den WS2812B ist das Timing extrem kritisch, da der Takt eben eingehalten werden MUSS.
Bei den APA (102 oder 106 - Eines ist ein WS2812B-Äquivalent, das Andere hat getrennte DATA und TAKT-Leitung) ist Das eben wegen des getrennt übertragenen Takt nicht (so?) kritisch - hatte ich aber noch nicht in den Fingern und das DaBla auch nicht soweit studiert, um die End-Bedingung Derer zu kennen.
Bei den WS2812B ist’s eine Zeit keine neuen Daten - Das bekommen alle LEDs mit, Die bereits Daten empfangen haben - entweder, weil Sie gerade die Daten bekommen, oder weil Sie die Daten danach weiter leiten - und schwupps, schalten die LED alle zusammen um.

MfG

das mit millis() könnte ein problem werden, weil ich mir so meine zeit hole. bislang funktioniert es erstmal aber habe ja auch noch nicht alles drin. Ich behalte das im Hinterkopf. Wenn das Problem Auftritt wende ich mich wieder an euch. Dazu währe momentan eine idee entweder direkt auf das Zeitgeberregister zuzugreifen wenn das geht oder ganz primitiv programmdurchläufe zählen. Bei den Lauflichtern kommt es mir nicht auf die Millisec an. Aber Ein Problem nach dem anderen.

knautschkissen:
Soweit ich weiß liegt von Neopixel nicht viel im Ram erst recht nicht der ganze Strip.

Das ist ein tiefgreifender Irrtum. Auszug aus der Adafruit_Neopixels.cpp:

numBytes = n * ((wOffset == rOffset) ? 3 : 4);
if((pixels = (uint8_t *)malloc(numBytes)))

Also 3 (RGB) oder 4 (RGBW) Bytes pro LED im RAM - der ganze Strip.

Gruß Tommy

Tommy56:
Auszug aus der Adafruit_Neopixels.cpp:
...

D. h. der Strip wird vor der Übertragung im RAM zusammengeschraubt, übertragen und das RAM dann wieder freigegeben?

Selbst wenn der ganze Streifen mit 300 LEDs ständig im RAM vorliegen muss - bei 4 Byte/LED und einer Handvoll (?) Verwaltungsdaten wären das ja „nur“ 120x Byte, womit gut 700 Bytes für den Rest des Programms zur Verfügung stehen würden - hmm ... 700 Bytes ... ganz schön viel g

Gruß

Gregor

Nein, der wird nicht freigegeben. Was sollte das bringen, wenn er gleich wieder angelegt werden müsste für die nächste Änderung?

Gruß Tommy

Hi

Die Farb-Änderungen, Die Du im Sketch ausübst, werden NUR in das Array geschrieben, Welches für den Stripe erstellt wurde.
Diese Byte werden NICHT beim Kompilieren mit angezeigt, da Diese erst beim START des Script reserviert werden.
Freigegeben werden Diese auch nur, wenn die Instanz, Die Du angelegt hast, am Ende der Funktion wieder zerstört wird - dadurch kann man auch z.B. die Länge des Stripe während der Laufzeit anpassen - wie Das mit dem freien Speicher aussieht - kA, Verkleinern müsste gehen, da der vorher belegte Bereich ja freigegeben wird, bevor der neue Bereich reserviert wird.
Wenn der Stripe länger werden soll, braucht's wohl ein entsprechend großes Stück Speicher, Welches noch Keiner haben wollte.

Die ganzen Animatione-Berechnungen landen Alle nur im Array.
Erst das .show() schiebt die Daten (aus dem Array, weshalb Das zwingend auch vorhanden sein muß) in den Stripe.
Dabei werden die Interrupts abgeschaltet, weshalb millis() langsamer wird.
Habe eine Uhr, Die mit ca. 750 millis() pro Sekunde zurecht kommen muß - der Sketch passt diese Zeit während der Laufzeit an, damit die Animationen des Sekundenzeiger trotzdem innerhalb der Sekunde fertig wird - es wird also nicht von 1000 ausgegangen, sondern der Wert passt sich sekündlich an, sollten weniger millis() in der letzten Sekunde vergangen sein.
Die Animation wird wohl ca. 90% der Zeit verprassen - also die letzte Änderung ist knapp vor dem Sekundenwechsel.
Der Sekundentakt kommt von einer DS3231.

MfG

Danke für die Erläuterungen!

Um zur Abwechslung auch einmal mit Neopixeln zu spielen und mir diesbezüglich Ahnung zu verschaffen, habe ich mir mal einen „Probemeter“ bestellt.

Ein Nano 33 BLE Sense liegt hier auch schon herum - also langweilig wird mir nicht :slight_smile:

Gruß

Gregor

Hallo Leute
Danke nochmal für eure Hilfe.
Wollte hier nochmal eine Erfolgsmeldung geben. Es funktioniert (auch mit millis() für Zeitstempel).
-Ich kann auf dem Strip beliebig(bis zu 20) viele Snippets konfigurieren in beliebiger Länge.
-Jeder Snippet hat sein eigenes Muster(1 bis 255 LEDs pro Strich)
-Das Muster kann auch mehrfach angezeigt werden kann wenn ich nicht nur 1 strich darauf sehen möchte --jeder Snippet überwacht selbst wann es an der Zeit für ihn ist sich zu aktualisieren
-Vorwärts/Rückwärts für jeden einstellbar
-Überlappen von Snippets möglich um sozzusagen Vorder und Hintergrundfarbe zu ermöglichen
-es können Mehrere Streifen mit beliebig vielen Snippets angelegt werden.

Also vielen Dank nochmal :slight_smile: Ich mach wenn ich mit der Doku fertig bin daraus eine lib die ich auch gerne zur Verfügung stelle wenn jemand Interesse hat und mir sagt wie und wo das geht^^