In einer Klasse Methoden mehrfach instantiieren?

Hallo Leute,
nach der Super Hilfe letztens hoffe ich erneut auf eure Unterstützung.
Ziel: ich will eine Klasse My_ARgbStrip erzeugen, welche die Adafruit Neopixel Bibo nutzt um einen entsprechenden Streifen anzusprechen. Die repräsentiert einen solchen Streifen. In diesem LED streifen also dieser Klasse möchte ich mir beliebig viele "Snippets" also Teilstücke erstellen können, welche eine startadresse, anzahl der LEDs und ein ich nenne es Muster bekommen. Diese "Snippets" sollen dann unterschiedliche und voneinander unabhängige Leuchteffeckte darstellen. Die werden dann dementsprechend von der My_ARgbStrip auf dem Streifen dargestellt, sodass auf dem Streifen segmente mit unterschiedlichen Leuchteffeckten entstehen. Wenn ich einen 2. Streifen habe will ich dann halt einfach nur eine weitere My_ARgbStrip initiieren und entsprechend wieder mit den belinigen Snippets rumspielen.

Ich vermute, dass ich eine Klasse My_ARgbStrip und eine Klasse My_ARgbSnippet schreiben muss aber ich weiß leider noch nicht wie ich die My_ARgbSnippet so in die My_ARgbStrip einbinde, dass ich beim Programmieren des Arduino mehrere Snippets im Strip erstellen kann.

Jedes Snippet-Objekt erhält (im Konstruktor) eine Referenz auf das zugehörige Strip-Objekt, und Angaben über seine Position im Strip. Diese Angaben werden im Snippet gespeichert und verwendet, wenn Änderungen an das Strip-Objekt geschickt werden.

Der Titel ist verwirrend. Das hat nichts mit Methoden zu tun

Serenifly:
Der Titel ist verwirrend. Das hat nichts mit Methoden zu tun

Sorry für die falsche verwendung, wie würde es denn richtiger heißen?

DrDiettrich:
Jedes Snippet-Objekt erhält (im Konstruktor) eine Referenz auf das zugehörige Strip-Objekt, und Angaben über seine Position im Strip. Diese Angaben werden im Snippet gespeichert und verwendet, wenn Änderungen an das Strip-Objekt geschickt werden.

ähm tut mir leid aber ich zwar was du meinst aber nicht wie ich das umsetzen kann :frowning:
im Moment sieht der Konstruktor vom Snippet so aus:

#include "Arduino.h"
#include "My_ARgbSnippet.h"
#include <Adafruit_NeoPixel.h>

My_ARgbSnippet::My_ARgbSnippet(int adresse, int pixe):snippet(adresse, pixel)
{

}
  • edit, hab gerade selber gemerkt dass deteils die sich zur laufzeit ändern wie farbe und muster wenn ich das richtig verstanden habe nix im konstruktor verloren haben. daher rausgelöscht

knautschkissen:
... im Moment sieht der Konstruktor vom Snippet so aus: ...

Interessanter wäre IMO die Klassendefinition, die üblicherweise im Header steht. Wie sieht denn dort bislang die Klasse aus, die Dir vorschwebt?

Gruß

Gregor

gregorss:
Wie sieht denn dort bislang die Klasse aus, die Dir vorschwebt?

Das kannst du aus dem Konstruktor ableiten. Er hat dort wohl ein Objekt der Klasse das dann im Konstruktor initialisiert wird

Das Problem wird jetzt sein dass statt einem Objekt beliebig viele haben möchte. Das ist etwas problematisch, da es keine dynamischen Container wie Listen oder Vektoren gibt.
Man könnte ein Array aus Zeigern verwalten. Das hätte dann eine maximale Größe, was aber praktisch meistens ok ist. Die Objekte selbst würden natürlich außerhalb der Klasse existieren und man fügt nur deren Adresse in das Array ein.

Hier die .h vom Snippet

#ifndef My_ARgbSnippet_h
#define My_ARgbSnippet_h
#include "Arduino.h"
#include <Adafruit_NeoPixel.h>
class My_ARgbSnippet
{
  private:
    Adafruit_NeoPixel snippet;
    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
    byte _speed;//Geschwindigkeit Lauflicht
    int  _actualPosition;//Aktuelle Position des Musters im Snippet
    void _calc();//Berechnung neue Bitmusterposition
    

  public:
    My_ARgbStrip(int pixel, byte pin);//Konstruktor
    void setR(byte r);//Setze Farbe
    void setG(byte g);//Setze Farbe
    void setB(byte b);//Setze Farbe
    void setspeed(byte setspeed);//Setze Geschwindigkeit Lauflicht
    void setTime(unsigned long *timestamp);//Zeitstempel(millis() im loop)und entscheidung ob muster sich ändert oder nicht
    void setBright(byte bright);//Setze Helligkeit
    void getSnippet(byte *snipdata);// gebe Farbe und Helligkeit der leuchtenden LEDs im Snippet zurück


};
#endif

das ist erstmal der Entwurf. weiß selbst noch nicht ob ich noch mehr brauche

Serenifly:
Das kannst du aus dem Konstruktor ableiten. Er hat dort wohl ein Objekt der Klasse das dann im Konstruktor initialisiert wird

Das Problem wird jetzt sein dass statt einem Objekt beliebig viele haben möchte. Das ist etwas problematisch, da es keine dynamischen Container wie Listen oder Vektoren gibt.
Man könnte ein Array aus Zeigern verwalten. Das hätte dann eine maximale Größe, was aber praktisch meistens ok ist. Die Objekte selbst würden natürlich außerhalb der Klasse existieren und man fügt nur deren Adresse in das Array ein.

Das währe grundsätzlich ok für mich, kann dass Array ja meinetwegen für 50 oder so auslegen. halt eine sache des speichers. ich weiß nur leider noch nicht wie man dass umsetzt. Adressen in ein array schreiben finde ich raus, aber wie weiter. Tut mir leid, aber hab sowas vorher halt nie gemacht. Wenn ich ein Funktionierendes Beispiel habe bekomme ich das angepasst aber komplett neu ist für mich immer schwierig. Meine anderen Projekte waren einfacher gestrickt bzw unübersichtlicher spagetticode und das will ich mir abgewöhnen. Früher hätte ich jeden snippet einzeln als funktion in der ino geschrieben und am ende auf den strip mit der neopixelbibo geschrieben. will halt versuchen das halbwegs ordentlich zu machen

Zumindest ungewöhnlich ist ein Getter, der als Rückgabe void hat.

void getSnippet(byte *snipdata);

Wäre da nicht logischer

byte *getSnippet(byte *snipdata);

also einfach den Zeiger wieder zurück geben

Gruß Tommy

knautschkissen:
Hier die .h vom Snippet

Wenn Du mich fragst, kannst Du das deutlich verkürzen. Ich frage mich z. B., wozu Du mehr als lediglich Startadresse (Position im Gesamt-Strip?) und das darzustellende Muster brauchst. Naja, evtl. noch einen Zeiger auf eine Position innerhalb des Musters.
Im Übergeordneten Programmcode greifst Du dann lediglich auf das Muster des Snippets zu (was Du vermutlich mit der Methode getSnippet() möchtest). Das baust Du bzw. der übergeordnete Code in den „Gesamt-Strip“ ein und wenn der inclusive seiner „Sub-Strips“ bzw. Snippets fertig ist, überträgst Du ihn.

Das ist zumindest das, was mir vorschwebt, wenn ich mir den bisherigen Teil des Threads vor Augen halte.

HTH

Gregor

Tommy56:
Zumindest ungewöhnlich ist ein Getter, der als Rückgabe void hat.

void getSnippet(byte *snipdata);

Wäre da nicht logischer

byte *getSnippet(byte *snipdata);

also einfach den Zeiger wieder zurück geben

Gruß Tommy

wollte halt auf diese weise ein Array zurückgeben dass die Farben und Adressen der leuchtenden LEDs enthält ich weiß gerade nicht wozu dafür getSnippet als Zeiger zurückgegeben wird?

gregorss:
Wenn Du mich fragst, kannst Du das deutlich verkürzen. Ich frage mich z. B., wozu Du mehr als lediglich Startadresse (Position im Gesamt-Strip?) und das darzustellende Muster brauchst. Naja, evtl. noch einen Zeiger auf eine Position innerhalb des Musters.
Im Übergeordneten Programmcode greifst Du dann lediglich auf das Muster des Snippets zu (was Du vermutlich mit der Methode getSnippet() möchtest). Das baust Du bzw. der übergeordnete Code in den „Gesamt-Strip“ ein und wenn der inclusive seiner „Sub-Strips“ bzw. Snippets fertig ist, überträgst Du ihn.

Das ist zumindest das, was mir vorschwebt, wenn ich mir den bisherigen Teil des Threads vor Augen halte.

HTH

Gregor

Hängt damit zusammen, dass das Lauflichter werden. Ein Snippet behinhaltet z.B. 20 LEDs das Muster besteht aber nur aus z.B. 5 LEDs hintereinander. Diese 5 LEDs sollen nun durch die 20 verfügbaren geschoben werden und wenn die hinten "rausfallen" vorne wieder anfangen. Wird ein interaktives Modell einer Biogasanlage in dem die Energie und Stoffströme mit Hilfe eines LED Strips dargestellt werden

Warum ein Strip für alles, und nicht für jedes Segment ein eigener Strip? Dann können alle diese Strips statisch angelegt und individuell getaktet werden.

knautschkissen:
Hängt damit zusammen, dass das Lauflichter werden. Ein Snippet behinhaltet z.B. 20 LEDs das Muster besteht aber nur aus z.B. 5 LEDs hintereinander. Diese 5 LEDs sollen nun durch die 20 verfügbaren geschoben werden und wenn die hinten "rausfallen" vorne wieder anfangen. Wird ein interaktives Modell einer Biogasanlage in dem die Energie und Stoffströme mit Hilfe eines LED Strips dargestellt werden

Dann würde IMO folgendes genügen:

Im „Hauptsketch“ deklarierst Du

struct RGBColor
{
  byte r;
  byte g;
  byte b;
};

und im Header

class My_ArgbSnippet
{
  private:
    byte positionImGesamtstrip;
    RGBColor pixels[20];
    void schieben(); // Funktion, die die Pixel im Array verschiebt
  public:
    ...
    // Hier Konstruktor und eine Funktion, die z.B. bei jedem loop()-
    // Durchlauf aufgerufen wird (zum Schieben und was sonst ansteht)
    // Und natuerlich eine Funktion, die einen Zeiger auf die Pixels zurueckgibt
    ...
};

Wie gesagt, ich weiß nicht, wieso Du so ein riesiges Monster programmieren möchtest. Im Hauptsketch benutzt Du z. B. vier Instanzen dieser Klasse, um einen Strip mit insgesamt 80 LEDs darzustellen.

Gruß

Gregor

DrDiettrich:
Warum ein Strip für alles, und nicht für jedes Segment ein eigener Strip? Dann können alle diese Strips statisch angelegt und individuell getaktet werden.

Dann hat man allerdings nur eine feste Anzahl an Segmenten mit jeweils einer festen Anzahl an LEDs. Was der OP vorhat, ist deutlich flexibler.

Gruß

Gregor

gregorss:
Dann hat man allerdings nur eine feste Anzahl an Segmenten mit jeweils einer festen Anzahl an LEDs. Was der OP vorhat, ist deutlich flexibler.

Gruß

Gregor

Das habe ich vor. Sicher könnte ich für das Modell fest ohne klassen etc das ganze programmieren, aber ich möchte daraus für mich eine bibliothek machen, mit der ich auch andere derartige Modelle erstellen kann und will das ganze dementsprechend möglichst flexibel halten. die andere Methode möchte ich mir abgewöhnen weil dass jedesmal zu großem aufwand und unübersichtlichem spagetticode wird.

Ich hatte gerade im Bett noch eine Idee, ohne es ausprobiert zu haben, könnte dass vll zum erfolg führen?

ino

"My_ARgbStrip.h"
const byte snipCount=10, Pixel=300, Pin=6;
My_ARgbStrip myARgbStrip(Pixel,Pin,snipCount);

void setup() {
  // put your setup code here, to run once:
myARgbStrip.AddSnippet(10,10,0);
}

void loop() {
myARgbStrip.tuWas(Nummer,...);
...
}

Strip.h

#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;
    My_ARgbSnippet _snippets[_snipCount];
    
    
    
  public:
    My_ARgbStrip(int pixel, byte pin, byte snipCount);
    bool init();//im Setup aufrufen um NeoPixel zu starten
     void AddSnippet(byte Adresse, byte Pixel, byte Nummer);//Erzeuge im Array_snippets an der stelle Nummer ein Snippet mit Adresse, Pixel...
     void tuWas(Nummer,...);
    
    

};
#endif

In Worten(ich hoffe verständlich)
in My_ARgbStrip erzeuge ich ein Array of My_ARgbSnippet mit der Länge snipCount welche ich dem Konstruktor übergebe. in der ino ist snipCount als constante hinterlegt. Wenn das ein gangbarer weg ist, müsste ich so zwar immer in der ino snipCount mit pflegen aber das finde ich nicht schlimm. Mit myARgbStrip.AddSnippet(adresse,Pixel,Nummer) werden die Parameter an das Array an der entsprechenden stelle übergeben. Mit myARgbStrip.tuWas(Nummer,…); übergebe ich die Nummer des Strip und vll kann ich über vererbung so dann auch auf die My_ARgbSnippet Methoden zugreifen.

Kann das so funktionieren oder entstammt die Idee meinem übermüdeten Hirn dass im bett trotzdem keine ruhe gibt aber nur müll produziert.

Nein. Das geht hinten und vorne nicht so. Array Größen müssen zur Compile Zeit bekannt sein. Das geht nur mit Templates. Denke nicht zu kompliziert und gebe die maximale Größe erst mal fest vor. Das kann man später immer noch variabel machen

Und denke daran dass du auch die tatsächliche Anzahl an Elementen abspeichern musst und vor dem hinzufügen auch ob noch Platz ist

knautschkissen:
... oder entstammt die Idee meinem übermüdeten Hirn ...

Ich verstehe die Idee, aber so flexibel geht es leider nicht. Wie Serenifly sagt, müssen Array-Größen zur Compile-Zeit bekannt sein. Der Compiler muss wissen, wie groß eine Instanz einer Klasse ist.

Fang' mit einer Konstellation an, in der die Größen bekannt sind. Wenn Du es so weit hast, hast Du auch jetzt noch gar nicht bedachte (unbekannte) Problemstellen erkannt.

Wenn man sich mit solchen Sachen rein gedanklich und im Bett befasst, kann man echt hübsche Sachen anstellen. Wenn man dann auch noch tolle Sachen träumt, wacht man positiv gestimmt auf :-)))

Gruß

Gregor

PS: Boh, wie oft lag ich schon im Bett und hatte dann die Idee ... und schon war die Nacht durchgemacht. Hihi.

PPS: Gewöhne Dir an, Deine Arbeit zu versionieren und vor größeren Änderungen als neue Version zu speichern. Wenn man sich beim Programmieren mal verrannt hat, ist es nur halb so schlimm.

Auf einem entsprechend großen Controller mag das mit den Snippets ja funktionieren, aber nicht auf den kleinen ATmegas. Dort hat man ja schon Probleme, die verfügbaren LEDs in Arrays zu packen, ohne daß der Speicher platzt. Und bei jeder Änderung müssen alle LEDs eines Strips aktualisiert werden, d.h. die Daten für den Strip müssen in einem (genügend großen) Array liegen, damit sie von dort der Reihe nach in den Strip geschoben werden können. Damit können die Snippets eine feste Größe haben, die LED Werte liegen ja im Speicher des Strips.

Gut ich wird das heute Nachmittag mal mit einem festen für den Anfang festen Array ausprobieren und vor allem einen Blick auf den speicher werfen. Aber nur aus Neugier, wenn ich die Variable in der .ino als const deklariere oder meinetwegen als Zahl dem Konstruktor übergebe, die ist dann zur compile zeit ja bekannt dachte ich dass das reicht. um Speicher zu sparen hatte ich vor bei den Snippets mit Forschleifen und nicht Arrays die das gesamte snippet erhalten zu arbeiten. Strip sollte dann nurnoch mit der Startadresse des Snippet die neuen überschreiben und die die jetzt aus sein sollen aus zu machen in der Hoffnung dass ich so Speicherplatz sparen kann und die rechenzeit nicht übermäßig zunimmt dass Garnichts mehr klappt.

const heißt das man nur Lesen kann. Und nicht dass es zur Compile-Zeit bekannt ist! Denke daran dass du theoretisch mehrere Objekte der Klasse erstellen könntest und jedem eine andere Größe übergibst:

MyClass obj1(10);
MyClass obj1(20);

Das geht nur mit Templates. Dann erzeugt der Compiler im Hintergrund aber mehrere Klassen