RAM Verbrauch sehr unterschiedlich

Hallo,

um den µC von Zwischenberechnungen zu entlasten, lege ich vorher arrays an.

Zuerst hatte ich ein array von Hand mit 360 Werten fest angelegt.
freeRAM zeigt mir 7471 Bytes an.

Lasse ich das array in setup automatisch befüllen, zeigt mir freeRAM nur noch 6751 Byte an.

Ich ging davon aus das ungefähr der gleiche RAM Verbrauch anfällt. Bis auf die zusätzliche Rechenfunktion.
Wodurch entstehen diese krassen Unterschiede?

/*
 Arduino Mega 2560
 
 mit Vorberechnung
 
 freeRAM 6751 Bytes
*/

int sinus[360];  // 360° Werte im Index von 0 ... 359

void setup()  {
   
  Serial.begin(38400);    
   
  for (int i=0; i<360; i++)  {
    sinus[i] = Grad_to_Bogenmass(i); 
  }
  
}   // Ende setup


void loop(void) {
 
  
  Serial.println( freeRAM() );
 
}   // Ende loop


/* ------------------------------------------------------------------------------------------------ */

int Grad_to_Bogenmass( float a )    // Berechnung des Bogenmasses vom Sinus
{
    int b = 0;
    b = (int) (sin (a / 180 * PI)*10000 + 0.5);   // multipliziert mit 10k um brauchbare Ganzzahlen zubekommen + richtig runden lassen
    return(b);                      // gibt den Wert von b (bogenmass) zurück
}


 // ***  Funktionen  *** 
int freeRAM() 
{ 
   extern int __heap_start, *__brkval;  
   int v;  
   return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}
/*
 Arduino Mega 2560
 
 mit fester array Vorbelegung
 
 freeRAM 7471 Bytes
*/

// 360° Werte im Index von 0 ... 359
int sinus[] = {0,175,349,523,698,872,1045,1219,1392,1564,1736,1908,2079,2250,2419,2588,2756,2924,3090,3256,3420,3584,3746,3907,4067,4226,4384,4540,4695,4848,5000,5150,5299,5446,5592,5736,5878,
                  6018,6157,6293,6428,6561,6691,6820,6947,7071,7193,7314,7431,7547,7660,7771,7880,7986,8090,8192,8290,8387,8480,8572,8660,8746,8829,8910,8988,9063,9135,9205,9272,9336,9397,9455,
                  9511,9563,9613,9659,9703,9744,9781,9816,9848,9877,9903,9925,9945,9962,9976,9986,9994,9998,10000,9998,9994,9986,9976,9962,9945,9925,9903,9877,9848,9816,9781,9744,9703,9659,9613,
                  9563,9511,9455,9397,9336,9272,9205,9135,9063,8988,8910,8829,8746,8660,8572,8480,8387,8290,8192,8090,7986,7880,7771,7660,7547,7431,7314,7193,7071,6947,6820,6691,6561,6428,6293,
                  6157,6018,5878,5736,5592,5446,5299,5150,5000,4848,4695,4540,4384,4226,4067,3907,3746,3584,3420,3256,3090,2924,2756,2588,2419,2250,2079,1908,1736,1564,1392,1219,1045,872,698,523,
                  349,175,0,-175,-349,-523,-698,-872,-1045,-1219,-1392,-1564,-1736,-1908,-2079,-2250,-2419,-2588,-2756,-2924,-3090,-3256,-3420,-3584,-3746,-3907,-4067,-4226,-4384,-4540,-4695,
                  -4848,-5000,-5150,-5299,-5446,-5592,-5736,-5878,-6018,-6157,-6293,-6428,-6561,-6691,-6820,-6947,-7071,-7193,-7314,-7431,-7547,-7660,-7771,-7880,-7986,-8090,-8192,-8290,-8387,
                  -8480,-8572,-8660,-8746,-8829,-8910,-8988,-9063,-9135,-9205,-9272,-9336,-9397,-9455,-9511,-9563,-9613,-9659,-9703,-9744,-9781,-9816,-9848,-9877,-9903,-9925,-9945,-9962,-9976,
                  -9986,-9994,-9998,-10000,-9998,-9994,-9986,-9976,-9962,-9945,-9925,-9903,-9877,-9848,-9816,-9781,-9744,-9703,-9659,-9613,-9563,-9511,-9455,-9397,-9336,-9272,-9205,-9135,-9063,
                  -8988,-8910,-8829,-8746,-8660,-8572,-8480,-8387,-8290,-8192,-8090,-7986,-7880,-7771,-7660,-7547,-7431,-7314,-7193,-7071,-6947,-6820,-6691,-6561,-6428,-6293,-6157,-6018,-5878,
                  -5736,-5592,-5446,-5299,-5150,-5000,-4848,-4695,-4540,-4384,-4226,-4067,-3907,-3746,-3584,-3420,-3256,-3090,-2924,-2756,-2588,-2419,-2250,-2079,-1908,-1736,-1564,-1392,-1219,
                  -1045,-872,-698,-523,-349,-175};

void setup()  {
   
  Serial.begin(38400);    
    
}   // Ende setup


void loop(void) {
 
  
  Serial.println( freeRAM() );
 
}   // Ende loop


/* ------------------------------------------------------------------------------------------------ */

int Grad_to_Bogenmass( float a )    // Berechnung des Bogenmasses vom Sinus
{
    int b = 0;
    b = (int) (sin (a / 180 * PI)*10000 + 0.5);   // multipliziert mit 10k um brauchbare Ganzzahlen zubekommen + richtig runden lassen
    return(b);                      // gibt den Wert von b (bogenmass) zurück
}


 // ***  Funktionen  *** 
int freeRAM() 
{ 
   extern int __heap_start, *__brkval;  
   int v;  
   return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

Ich weiß nicht, aber wenn du RAM sparen willst, berechne die Werte vorher und schreibe die Tabelle per PROGMEM ins Flash. Dann kannst du die einzelnen Werte mit pgm_read_word() auslesen

Hallo,

ich verstehe es auch nicht. In beiden Fällen steht im array das gleiche drin, laut meiner Meinung. Um wieviel langsamer ist das lesen aus dem Flash im Vergleich zum RAM?

Du meinst ich soll feste Werte ins Array schreiben. Genau das wollte vermeiden und bin am abändern auf automatische Vorabberechnung. Sodass ich flexibler bin und nicht bei Änderungen jedesmal 360 Werte ändern muß.

Das sind alles Vorabübungen für einen Frequenzgenerator, weil ich so ein nettes IC namens TI-8830 habe. :)

Doc_Arduino: Du meinst ich soll feste Werte ins Array schreiben.

Wenn du RAM sparen willst. Andererseits hast du auf dem Mega 8kB. Da kann man auch mal 720 Byte verballern

Das interessante ist dass der Unterschied genau die 720 Byte ist. Ich glaube dass der Compiler das Array wegoptimiert weil du nie darauf zugreifst. Lass mal ein paar Werte davon auf Serial ausgeben. Dann wirst du wahrscheinlich feststellen dass du plötzlich mehr RAM verbrauchst

Hallo,

mir ging es jetzt nicht primär um RAM einzusparen. Da haben wir uns falsch verstanden. Denn wie Du schon sagst, beim Mega spielen 720 Byte keine Rolle. :)

Den Effekt konnte ich mir nicht erklären. Und genau da hast du mal wieder den Finger in der "richtigen Wunde". Der Compiler optimiert das tatsächlich weg ohne Zugriff im Sketch. Lasse ich das in loop per for Schleife ausgeben, zeigt freeRAM 6745 Byte an.

Damit wäre alles geklärt. Danke mal wieder. :)

Doc_Arduino: Wodurch entstehen diese krassen Unterschiede?

Der GCC-Compiler ist ein "optimierender" Compiler und bei Arduino ist die Optimierung eingeschaltet.

Sobald der Compiler erkennt, dass Variablen in einem Programm nur "deklariert", aber dann tatsächlich nirgendwo im Programm auch "verwendet" werden, wird der Compiler diese Variablen aus dem fertigen Programm komplett "herausoptimieren", so dass die Variablen dann im Programm gar nicht mehr vorhanden sind.

Wenn Du tatsächlich den RAM-Verbrauch vergleichen möchtest, mußt Du also die Variablen auch im Programm verwenden. Beispielsweise alle Variablen einmal auf Serial ausgeben.

Durch die Optimierung des Compilers wird nicht in jedem Fall das Programm erstellt, das exakt Deinem Quellcode entspricht, sondern es wird ein Programm erstellt, das sich genau so verhält wie das, was Du tatsächlich programmiert hast.

Hallo,

auch dir nochmal Danke für die Erklärung.