Verständnisfrage: Speicherplatz auf dem Arduino

Hallo miteinander,

Wenn ich ein Programm schreibe dann muss man ja auch immer auf die Größe achten die das Programm später mal haben wird, denn sonst ist der Speicher irgend wann Voll und man bekommt ein Problem :slight_smile:

Wenn man den Code über die IDE Koppeliren lässt dann wird einen angezeigt welchen Speicher man wie verbraucht hat. Das finde ich ganz interessant, doch dazu habe ich mal das ein oder andere was mir nicht so ganz klar ist.

z.B. der Code

void setup()
{
  Serial.begin(9600);
  Serial.println ("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); 
  Serial.println ("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); 
  Serial.println ("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); 
  Serial.println ("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); 
  Serial.println ("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); 
  Serial.println ("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); 
  Serial.println ("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); 
  Serial.println ("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); 
  Serial.println ("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); 
  Serial.println ("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); 
}
void loop() {}

Text nach dem Koppeliren:

Der Sketch verwendet 1622 Bytes (5%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 288 Bytes (14%) des dynamischen Speichers, 1760 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

Wenn ich den Code jedoch so schreibe:

void setup()
{
  Serial.begin(9600);
  Serial.println (F("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890")); 
  Serial.println (F("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890")); 
  Serial.println (F("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890")); 
  Serial.println (F("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890")); 
  Serial.println (F("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890")); 
  Serial.println (F("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890")); 
  Serial.println (F("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890")); 
  Serial.println (F("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890")); 
  Serial.println (F("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890")); 
  Serial.println (F("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890")); 
}
void loop() {}

Text nach dem Koppeliren:

Der Sketch verwendet 2608 Bytes (8%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 188 Bytes (9%) des dynamischen Speichers, 1860 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

Wenn die IDE sagt:
"Der Sketch verwendet" == dann ist damit der Speicher für den Programm Code gemeint?
"Globale Variablen verwenden" == das ist dann z.B. der Speicher der reserviert ist für eine Variable die ich berechne lasse denn der berechnete Wert soll ja im Kurzzeit gentechnisch bleiben.

  • Der Sketch Speicher ist zu 100% wider vorhanden wenn ich mein Bord ein und ausgeschaltet habe.
  • Der Globale Variablen Speicher ist Leer sprich keine Erinnerung mehr daran was vorher gewesen ist. wenn das Bord ein und ausgeschaltet wurde.

Habe ich das so richtig verstanden?

Gruß Mücke

Man unterscheidet zwischen RAM und ROM.
(wikipedia gibt gerne genauere Auskunft)

Und ja, bei den AVR steckt der Code im ROM.

Hm-ich rate mal mit (ich geb zu, genauer als du weiss ich es vermutlich auch nicht):

Programmspeicher liegst du richtig. Dort drin liegt ganz einfach das Programm selber.

Aber die globalen Variablen: das dürften die sein, die im Programm bereits reserviert sind, also eben alle globalen, für die du im Programm schon Speicherplatz reserviert hast.
Das ergbt nämlich Sinn, denn nur deren Speicherverbrauch lässt sich exakt im Vorfeld berechnen (eine Byte-Variable, die im Kopf schon definiert ist als global, wird dieses Byte, und genau das, auch die ganze Zeit belegen).
Leer ist dieser Speicher aber nicht, denn wenn du im Programmkopf z.B. stehen hast

int X=325;

dann wird an irgeneiner Speicherstelle genau das stehen. Kann sich jedoch später ggf. ändern, da sich ja die Variable ändern kann. Aber am Speicherverbrauch ändert das nichts.

Wenn du jedoch in einem Unterprogramm sowas machst wie

int i=0;

dann wird dieser Speicher nur so lange gebraucht, wie die Variable i "lebt"- und danach wieder freigegeben.
Grundsätzlich kann man eine Menge Speicher sparen, indem man Variablen möglichst lokal definiert (wenn das halt geht), riskiert aber, dass irgendwann der Speicher dann nicht ausreicht (weil zu viele lokale Variablen gleichzeitig im Speicher "leben".

Ein guter Test, ob der Speicher irgendwann überlaufen kann: einfach mal alle jemals verwendeten Variablen im Kopf zu definieren (als global), dann sollte man eigentlich den tatsächlichen, maximalen Verbrauch sehen können (vorausgesetzt, der Compiler optimiert das nich einfach weg).

Hallo,

Sketch Speicher meint den Flash, darin ist das eigentliche Programm dauerhaft gespeichert. Wie eine Festplatte.
Nach Reset beginnt es komplett von vorn.

Globaler Speicher meint den flüchtigen RAM, darin landen zum Bsp. deine normalen Variablen und Zwischenergebnisse etc. Nach Reset sind die Werte weg, was eigentlich auch nicht weiter schlimm ist.

Normal würde man denken dass konstante Texte automatisch im Flash/ROM bleiben und kein RAM belegen. Die AVRs haben allerdings eine Harvard Architektur. Das heißt dass Flash und RAM getrennte Adress- und Daten-Busse haben und nicht auf die gleiche Art adressiert werden können. Die meisten Assembler-Befehle können nur mit Daten im RAM umgehen. Was im Flash liegt muss vorher meistens ins RAM kopiert werden.
Das geschieht bei Text-Konstanten automatisch und daher belegen sie wenn man nichts macht RAM. Man muss die Umwege mit F() und PROGMEM machen damit sie im Flash bleiben. Und kann dann auch nicht so ganz einfach auf sie zugreifen, sondern braucht extra Funktionen um die Daten ins RAM zu kopieren.

32-Bit Arduinos haben dieses Problem nicht, da die ARM Prozessoren anders arbeiten. Die haben zwar getrennte Buse, aber einen gemeinsamen Adress-Raum für Flash und RAM

Ok, dann habe ich das richtig verstanden.

Demnach muss ich mir beim "Der Sketch verwendet xxx Bytes (99%) des Programmspeicherplatzes." keine sorgen machen, da dieser nicht durch irgend welche Variablen die warum auch immer gerade nicht Aktiv sind nicht noch platz gebracht wird.

Danke euch, für eure antworten die Wiki Seite habe ich mir auch angeschaut, Danke.

Spiel mal mit dieser Variante (achte auf den Unterschied zu deiner), und schau dir RAM und Flash Bedarf an.

void setup() {
  Serial.begin(9600);
  Serial.println ("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890");
  Serial.println ("2345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901");
...
}

Mit deinen 10 gleichen println Zeilen hast du dem Compiler die Chance gegeben, dich auszutricksen.
Weiterhin viel Spass.

Hallo Michael_X,

ich musste zwei mal hinschauen was der unterschied ist, du hast die Zahlenreihen alle unterschiedlich gemacht.

Ich gehe davon aus das die IDE hier die selben Texte abgekürzt hat. Das ist gemein gewesen für den Test.
Ich habe das mal zusammen gefasst.
Es ist sehr interessant, das UNO ist schon fast voll für mein Verständnis mit dem bissen Code :slight_smile:

Code:

void setup() {
  Serial.begin(9600);
  Serial.println ("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890");
  Serial.println ("2345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901");
  Serial.println ("3456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012");
  Serial.println ("4567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123");
  Serial.println ("5678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234");
  Serial.println ("6789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345");
  Serial.println ("7890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456");
  Serial.println ("8901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567");
  Serial.println ("9012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678");
  Serial.println ("0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789");
}
void loop() {}

ROM: 2592 Bytes (8%) von 32256 Bytes
RAM: 1198 Bytes (58%) von 2048 Bytes

Mit F() im Code:

void setup() {
  Serial.begin(9600);
  Serial.println (F("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"));
  Serial.println (F("2345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901"));
  Serial.println (F("3456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012"));
  Serial.println (F("4567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123"));
  Serial.println (F("5678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234"));
  Serial.println (F("6789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345"));
  Serial.println (F("7890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456"));
  Serial.println (F("8901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567"));
  Serial.println (F("9012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678"));
  Serial.println (F("0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"));
}
void loop() {}

ROM: 2608 Bytes (8%) von 32256 Bytes
RAM: 188 Bytes (9%) von 2048 Bytes

das ist der Hammer, der ROM ist so gut wie nicht mehr geworden, jedoch sind die Speicher Belegungen vom RAM extrem runter gegangen. das ist der Hammer.

Danke für den Hinweis.

Gruß Mücke

das ist der Hammer.

Ich bin erstaunt, was (oder wie sehr) dich das alles so erstaunt.
:sunglasses: :sunglasses: :sunglasses:

mit dem bissen Code

Da siehst du mal, wie speicherintensiv Text ist, im Vergleich zur Logik, die z.B. in einer Steuerung steckt.

Dass Bilder, Sound oder gar Video nichts für einen Uno sind, sollte so auch klar sein.

Schön dass du es gelernt hast
Regel 1: Fester Text hat im RAM nichts zu suchen.

combie:
Ich bin erstaunt, was (oder wie sehr) dich das alles so erstaunt.
:sunglasses: :sunglasses: :sunglasses:

:o

michael_x:
Dass Bilder, Sound oder gar Video nichts für einen Uno sind, sollte so auch klar sein.

Wie kommst du gerade auf die Dinge? daran habe ich bisher noch nicht mal im Traum gedacht.
für mich ist ein Arduino grundsetzlich für die hadware Steuerung vorhanden, wenn ich mehr haben möchte muss man sich ein raspberry pi oder so was dazu nehmen :wink:

michael_x:
Schön dass du es gelernt hast
Regel 1: Fester Text hat im RAM nichts zu suchen.

Das schreibe ich mir ganz dick hinter die Ohren !!