Array im PROGMEM verwenden

Ich habe ziemlich viele lange Arrays die sich aber nicht ändern.
Gibt es eine möglichkeit diese im Programmspeicher zu speichern aber trozdem so zu verwenden?

  int Eins[]      = {101, 102, 103, 104, 105, 106, 107}; 
  int Ein[]       = {103, 104, 105, 106, 107};
  int Zwei[]      = {89, 90, 91, 92, 93, 94, 95}; 
  int Drei[]      = {82, 83, 84, 85, 86, 87, 88}; 
  int Vier[]      = {70, 71, 72, 73, 74, 75, 76}; 
  int Fuenf[]     = {108, 109, 110, 111, 112, 113, 114}; 

//zb. so 

void SwitchLED(int MyArray[], int n) {  // Funktion um LEDs anzusprechen
  
  for (i = MyArray[0]; i < MyArray[0]+n; i++) {
      leds[i] = farbe;                      
      FastLED.setBrightness(BRIGHTNESS);
  }
}

//=====
SwitchLED(Eins, (sizeof(Eins)/2));

Weil wenn ich einfach die Arrays mit

const PROGMEM  int Eins[]      = {101, 102, 103, 104, 105, 106, 107};

Deine Beispielzahlen lassen vermuten, dass byte[] genügen würde.
Prüfe das mal.

Gruß Tommy

Macht vom Dynamischen Speicher keinen Unterschied hab ich schon ausprobiert und
weiter unten kommen noch längere wo es nicht mehr aussreicht darum hab ichs einheitlich gemacht

Wenn du PROGMEM schon kennst, wieso wendest du es dann nicht komplett an? Du brauchst du die entsprechende Lese-Funktion:
https://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html

Also hier pgm_read_byte() (für ein Array aus Byte). Der übergibt man dann die Adresse(!) der Konstante und man bekommt deren Wert:

byte b = pgm_read_byte(&array[index]);

Ja genau das ist mein Problem ich versteh nicht wie ich das Lesen anwende...

Oder ob es einfach mit einer Funktion wie sizeof_P o.Ä funktioniert

const int iArr[] PROGMEM = { 101, 102, 103, 104, 105, 106, 107 };
const byte bArr[] PROGMEM = { 101, 102, 103, 104, 105, 106, 107 };

void setup()
{
  Serial.begin(9600);

  size_t size = sizeof(iArr);
  Serial.println(size);
  for (unsigned int i = 0; i < size / sizeof(iArr[0]); i++)
  {
    Serial.print(pgm_read_word(&iArr[i]));
    Serial.print(", ");
  }

  Serial.println('\n');
  size = sizeof(bArr);
  Serial.println(size);
  for (unsigned int i = 0; i < size; i++)
  {
    Serial.print(pgm_read_byte(&bArr[i]));
    Serial.print(", ");
  }
}

void loop()
{
}

Man muss die Daten halt extra aus dem Flash auslesen, da die normalen Assembler-Befehle dank der Hardvard-Architektur des Controllers nur mit Daten im RAM umgehen können

Wo ist da das Problem?

Spar ich mir dadurch dann überhaupt dynamischen Speicher wenn er es eh wieder reinladen muss?

Oder ist es dann nicht einfacher wenn ich es wie oben einfach stehen lasse?

Ich nutz es so:

// hier kannst du mit sizeof arbeiten
const byte test_var1[] PROGMEM = {10,12,13,14};

// hier funktioniert sizeof nicht mehr
#define TEST_VAR2_LEN  5
const char * const test_var2[] PROGMEM = {"test","test2","test3","test4","test7"};


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  // dies geht mit sizeof
  for(uint8_t i=0; i<(sizeof(test_var1)-1); i++)
  {
    Serial.println( (byte)pgm_read_word(&(test_var1[i])) );
  }

  // hier geht sizeof nicht mehr so einfach
  for(uint8_t i=0; i<TEST_VAR2_LEN; i++)
  {
    Serial.println( (char *)pgm_read_word(&(test_var2[i])) );
  }

}

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

}
1 Like

Dynamischer Speicher ist das sowieso nicht (da nichts zur Laufzeit angelegt wird).

Aber du spart dir aber klar RAM damit. Normal würde das ganze Array im RAM landen. So wird jedesmal nur ein Wert kopiert

Du lädst ja nur den einen Wert rein, den Du gerade brauchst.

Gruß Tommy

Okey stimmt macht Sinn.

void SwitchLED(int MyArray[], int n) {  // Funktion um LEDs anzusprechen
  
  for (i = pgm_read_word(&MyArray[0]); i < pgm_read_word(&MyArray[0])+n; i++) {  // Liest den Wert aus dem Programmspeicher aus
      leds[i] = farbe;                      
      FastLED.setBrightness(BRIGHTNESS);
  }
}

//=====
SwitchLED(Eins, (sizeof(Eins)/2)); //

//Edit funktioniert danke

Hi

Wenn die Arrays in der Art aufgebaut sind, wie Das oben suggeriert wird, würde ich mir die Werte ERRECHNEN.
Zumindest die vorgestellten Zahlen-Folgen sind Alle ohne Probleme von einem Startwert aus errechenbar.

MfG

// hier funktioniert sizeof nicht mehr
#define TEST_VAR2_LEN  5
const char * const test_var2[] PROGMEM = {"test","test2","test3","test4","test7"};

Natürlich funktioniert sizeof da, es liefert vielleicht nur nicht die Werte die du erwartest.

Und die Strings die du da anlegst sind im RAM, nur deren Zeiger im PROGMEM.

postmaster-ino:
Hi

Wenn die Arrays in der Art aufgebaut sind, wie Das oben suggeriert wird, würde ich mir die Werte ERRECHNEN.
Zumindest die vorgestellten Zahlen-Folgen sind Alle ohne Probleme von einem Startwert aus errechenbar.

MfG

Stimmt, habe ich gar nicht richtig hingeguckt :grin: Das spart deutlich mehr Speicher !

Ulli