Klasse Memberarray Größe

Wie kann ich in einer Klasse ein Array erstellen, wo die Größe des Arrays erst beim erstellen des Objekts bekannt ist?

z.B. wenn ich beim Erstellen eines Objekts einer Klasse, die Größe des Array von 12 Elementen erstellen möchte.
So geht es nicht:

const byte zahl = 12;

class Klasse{
public:
  byte n;
  byte a[n];
  Klasse(byte number){
    n=number;
  }
};

Klasse arr(zahl);

void setup() {
  Serial.begin(9600);
  for(byte i=0; i<zahl; i++){
    arr.a[i]=i;
    Serial.println(arr.a[i]);
  }
}

void loop() {
  // put your main code here, to run repeatedly:
}

Wie kann man es lösen? Wahrscheinlich liegt es noch am Knoten im Hirn das Objektorientierte zu erkennen. Oder an etwas anderem banalen. Danke

Stichwort template

edit: aus der Wühlkiste


template <size_t arrSize>
class Foo {
  private:
    byte *_ArrPoint;
    byte Array[arrSize];
    
  public:
    Foo() {
      _ArrPoint = Array;
    }

};

void setup() {
  Foo<5> x;
}

void loop() {

}
1 Like

Ich geh mal Lesestoff suchen. Danke

Entweder per Template, oder unter zur Hilfenahme des RAII Pattern

// template

constexpr size_t zahl {12};

template<size_t N>class Klasse{
public:
  byte n{N};
  byte a[N];
};

Klasse<zahl> arr;

void setup() {
  Serial.begin(9600);
  for(byte i=0; i<zahl; i++){
    arr.a[i]=i;
    Serial.println(arr.a[i]);
  }
}

void loop() {
  // put your main code here, to run repeatedly:
}

// RAII

const byte zahl = 12;

class Klasse{
public:
  const byte n;
  byte *a;
  Klasse(byte number):n(number)
  {
    a=reinterpret_cast<byte*>(malloc(n*sizeof(*a)));
  }
  ~Klasse()
  {
    free(a);
  }
};

Klasse arr(zahl);

void setup() {
  Serial.begin(9600);
  for(byte i=0; i<zahl; i++){
    arr.a[i]=i;
    Serial.println(arr.a[i]);
  }
}

void loop() {
  // put your main code here, to run repeatedly:
}

Oder gar kombiniert

// template und RAII

const size_t zahl = 12;

template<typename T>class Klasse{
public:
  const size_t n;
  T *a;
  Klasse(size_t number):n(number)
  {
    a=reinterpret_cast<T*>(malloc(n*sizeof(T)));
  }
  ~Klasse()
  {
    free(a);
  }
};

Klasse<byte> arr(zahl);

void setup() {
  Serial.begin(9600);
  for(byte i=0; i<zahl; i++){
    arr.a[i]=i;
    Serial.println(arr.a[i]);
  }
}

void loop() {
  // put your main code here, to run repeatedly:
}
1 Like

Danke. Ich habe Variante 2 probiert. Funktioniert einwandfrei.

Wenn man diese Anforderung wörtlich nimmt, und "beim erstellen" zur Laufzeit und nicht "beim Kompilieren" bedeutet, geht nur Variante 2

Bei mir geht es darum ein Array von Farbwerten von SK9822 zu speichern und auf diese von außerhalb zuzugreifen. Hier wird nur einmalig zum Beginn die Anzahl der SK9822 festgelegt, ändert sich zur Laufzeit nicht mehr.

Endlich zuhause :slight_smile:
So sieht momentan die Header-Datei aus.
sk9822ec20.h

#pragma once
#include <Arduino.h>
#include <SPI.h>

struct rgb_color {
  byte red;
  byte green;
  byte blue;
};

class SK9822EC20 {
private:
    byte current {1};                           // Stromeinstellung Default
    byte currentRegisterByte = current | 0b11100000;
    uint16_t NUM;                               // Variable für die Anzahl der LEDs
    rgb_color *pixel;                           // Zeiger auf den Anfang des Array für die Farbwerte der LEDs
    rgb_color brightness{60,30,100};            // Prozent der Leuchtkraft Default
    
    //private Methoden
    void startFrame(){                          // benötigt 32 0Bits
      for (uint8_t i = 0; i < 4; i++){          // 4 mal 8Bit â 2 Flanken (4*8*2) = 64 Flanken
        SPI.transfer(0);                        // sendet 16 Flanken, mit bleibenden 0 Datenpegel
      }
    }
    void sendColor(struct rgb_color color){     // schreibt die Werte des Pixels
      SPI.transfer(currentRegisterByte);
      SPI.transfer(color.blue);
      SPI.transfer(color.green);
      SPI.transfer(color.red);
    }
    void endFrame(){                            // Zum aktualiesieren muß pro LED eine Flanke (steigend oder fallend) eines 0Bits gesendet werden.  
      for (uint16_t i = 0; i < NUM; i+=16){     // pro Pixel eine Flanke. 8Bit = 16 Flanken
        SPI.transfer(0);                        // sendet 16 Flanken, mit bleibenden 0 Datenpegel
      }
    }
    
public:
    //Constructors
    SK9822EC20(uint16_t NUM, rgb_color brightness, byte current){
      this->NUM = NUM;
      this->current = constrain(current,1,10);
      currentRegisterByte = this->current | 0b11100000; 
      this->brightness = brightness;
      pixel=reinterpret_cast<rgb_color*>(malloc(NUM*sizeof(*pixel)));
    }
    SK9822EC20(uint16_t NUM, rgb_color brightness){
      this->NUM = NUM;
      this->brightness = brightness;
      pixel=reinterpret_cast<rgb_color*>(malloc(NUM*sizeof(*pixel)));
    }
    SK9822EC20(uint16_t NUM){
      this->NUM = NUM;
      pixel=reinterpret_cast<rgb_color*>(malloc(NUM*sizeof(*pixel)));
    }
    
    //Dekonstruktor
    ~SK9822EC20(){
      free(pixel);
    }
    
    //Öffentliche Methoden
    void show(){                                // Schiebt alle Daten raus
      SPI.beginTransaction(SPISettings());      // Beginnt Übertragung
      startFrame();                             // 32 0Bits
      for(uint16_t i = 0; i < NUM; i++){        // Für jedes Pixel
        sendColor(pixel[i]);                    // Farbwert Rot, Grün, Blau
      }
      endFrame();                               // Aktualisiert die Pixel, abhängig der Anzahl der LEDs
      SPI.endTransaction();                     // Beendet Übertragung
    }
    rgb_color getPixelColor(uint16_t NUM){
      return pixel[NUM];
    }
    void setPixelColor(uint16_t NUM, byte red, byte green, byte blue){
      if(this->NUM < NUM) return;
      rgb_color color {red, green, blue};
      setPixelColor(NUM, color);
    }
    void setPixelColor(uint16_t NUM, rgb_color color){
      if(this->NUM < NUM) return;
      pixel[NUM].red = uint16_t(uint16_t(color.red)*uint16_t(brightness.red)/100);
      pixel[NUM].green = uint16_t(uint16_t(color.green)*uint16_t(brightness.green)/100);
      pixel[NUM].blue = uint16_t(uint16_t(color.blue)*uint16_t(brightness.blue)/100);
    }
    byte getCurrent(){
      return current;
    }
    void setCurrent(uint8_t current){
      this->current = constrain(current,1,10);
      currentRegisterByte = this->current | 0b11100000; 
    }    
};

Und die *ino dazu

/* Arduino Erweiterung https://github.com/SpenceKonde/DxCore
 * Datasheet https://ww1.microchip.com/downloads/aemDocuments/documents/MCU08/ProductDocuments/DataSheets/AVR32-16DD20-14-Prel-DataSheet-DS40002413.pdf
// AVR32DD20QFN Breakout
//             +----+
//  MOSI PA4  1|    |20 PA3
//  MISO PA5  2|    |19 PA2 
//  SCK  PA6  3|    |18 PA1 
//  SS   PA7  4|    |17 PA0 
//      *PC1  5|    |16 UPDI 
//      *PC2  6|    |15 RESET
//      *PC3  7|    |14 GND
//     *VDD2  8|    |13 VDD
//       PD4  9|    |12 PD7
//       PD5 10|    |11 PD6 
//             +----+
//              UPDI
 */       

#include <SPI.h>
#include "sk9822ec20.h"

const byte current {1};                       // Stromeinstellung (1-10)
const uint16_t NUM {780};                     // Anzahl der Pixel
rgb_color globaleFarbe;                       // globaler Zwischenspeicher für Farbwerte
const rgb_color brightness{60,30,100};        // Prozent der Leuchtkraft
SK9822EC20 strip(NUM, brightness, current);   // Anzahl LEDs, Helligkeit in Prozent (RGB), Strom(1-10)

uint32_t timestamp;
uint16_t refresh {50};

void setup() {
  SPI.begin();
  strip.show();
}

void loop() {
  if(millis()-timestamp > refresh){
    rainbow();
    //justOn();
    strip.show();
    timestamp = millis();
  }
}

void justOn(){
  for(uint16_t i=0; i<NUM; i++){
    strip.setPixelColor(i,255,255,255);
  }
}

void rainbow(){                                                   // Farbwechsel nach Regenbogen
  rgb_color lokaleFarbe = globaleFarbe;  
  for(uint16_t i=0; i<NUM; i++){                                  // Für jedes Pixel den Farbwert etwas ändern (Regenbogen)
    if(lokaleFarbe.red == 250 && lokaleFarbe.blue == 0 && lokaleFarbe.green < 250) lokaleFarbe.green += 10;
    else if(lokaleFarbe.red > 0 && lokaleFarbe.blue == 0 && lokaleFarbe.green == 250) lokaleFarbe.red -= 10;
    else if(lokaleFarbe.red == 0 && lokaleFarbe.blue < 250 && lokaleFarbe.green == 250) lokaleFarbe.blue += 10;
    else if(lokaleFarbe.red == 0 && lokaleFarbe.blue == 250 && lokaleFarbe.green > 0) lokaleFarbe.green -= 10;
    else if(lokaleFarbe.red < 250 && lokaleFarbe.blue == 250 && lokaleFarbe.green == 0) lokaleFarbe.red += 10;
    else if(lokaleFarbe.red == 250 && lokaleFarbe.blue > 0 && lokaleFarbe.green == 0) lokaleFarbe.blue -= 10;
    else {
      lokaleFarbe.red=250; lokaleFarbe.blue=0; lokaleFarbe.green=0;                          // wenn es nicht in die Range passt, Startwert Festlegen
    }
    strip.setPixelColor(i,lokaleFarbe);               // setzt dem Aktuellen Pixel den Farbwert
    if (i==0) {                                                   // Nur nach beim ersten Durchlauf
      globaleFarbe = lokaleFarbe;          // Den ersten veränderten Farbwert den globalen Farbvariablen übergeben (Startwert etwas verschieben, um das wandern des Regenbogens zu simulieren)
    }
  }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.