Der Speicher der Arduinos wird für größere Programme oft knapp. Das geschieht besonders dann, wenn viele ➨Variable und ➨Arrays verwendet werden oder die Anweisung ➨Serial.print häufig benutzt wird.
Allerdings unterscheiden sich die verschiedenen Arduinos in der ➨Speicherausstattung.
Es gibt verschiedene Möglichkeiten, den verwendeten Speicher zu optimieren.
Verwendung von Variablen mit dem geringstmöglichen Speicherbedarf
Je nach Verwendungszweck und der benötigten Größe solltest du den Variablentyp verwenden, der die Anforderungen erfüllt und gleichzeitig den geringsten Speicherplatz beansprucht.
Variable | Geltungsbereich | Speicherbedarf | Bezeichnung in C |
---|---|---|---|
byte | Ganzahlen 0 bis 255 | 1 Byte (8 Bits) | signed char |
int | Ganzzahlenahlen -32.768 bis 32.767 | 2 Bytes (16 Bits) | int16_t |
unsigned int | Ganzzahlen 0 bis 65.535 | 4 Bytes (32 Bits) | uint16_t |
long | -2.147.483.648 bis 2.147.483.647 | 4 Byte (32 Bits) | int32_t |
unsigned long | 0 bis 4.294.967.295 | 4 Byte (32 Bits) | uint32_t |
float | Dezimalzahlen | 4 Byte (32 Bits) | float |
F-Makro
In vielen Programmen werden ➨Serial.print/Serial.println-Anweisungen ausgeführt. Jede dieser Anweisungen belegt Speicherplatz im ➨SRAM. Da es sich aber nicht um einen unveränderlichen String handelt, ist die Speicherung im SRAM nicht notwendig.
Das F-Makro sorgt dafür, dass der Text nicht im SRAM verbleibt, er wird vielmehr im deutlich größeren ➨Flash abgelegt und stellt so Speicherplatz für Variablen im SRAM zur Verfügung.
Beispiel:
Serial.println(F("Initialisierung abgeschlossen"));
Serial.println(F("Schreibe Messdaten in die Datei Messung.csv: "));
Serial.println(F("-----------------------------------");
PROGMEM
PROGMEM weist den Compiler an, die Daten im ➨Flash-Speicher abzulegen.
Dies gilt aber nur für Variable, die einen unveränderlichen Wert (Konstante) haben. Sie müssen global im Kopf des Programms definiert werden.
Das Programm erstellt ein Array von beliebigen Zahlen kleiner als 255. Anschließend wird eine zufällige Position im Array bestimmt und die sich dort befindende Zahl wird angezeigt.
So sieht es aus:
Das folgende Programm wurde ohne die Optimierung des Speicherplatzes erstellt:
int ZufallsZahl[] = {11, 23, 27, 31, 22, 35, 47, 76, 25, 12, 13, 14, 15, 91, 77, 99};
int Minimum = 1;
int Maximum = sizeof(ZufallsZahl) / sizeof(ZufallsZahl[0]);
void setup ()
{
// Zufallsgenerator starten
randomSeed(analogRead(A0));
Serial.begin(9600);
// auf serielle Verbindung warten
while (!Serial) {;}
Serial.println("Zahlen anzeigen:");
Serial.println("----------------------------------------");
for (byte i = 0; i < Maximum; i++)
{
byte GezogeneZahl = random(Minimum, Maximum);
Serial.print("Position im Array: \t");
Serial.print(GezogeneZahl);
Serial.print("\tZahl: ");
Serial.println(ZufallsZahl[GezogeneZahl]);
}
}
void loop()
{
// bleibt leer, Programm läuft nur einmal
}
Das Programm mit Optimierung:
- es wurde ein Variablentyp verwendet, der weniger Speicherplatz verbraucht (byte statt int)
- alle konstanten Variablen wurden mit PROGMEM definiert
- alle Serial.print/Serial.println-Anweisungen werden mit dem ➨F-Makro ausgeführt
// alle Konstanten ins SRAM kopieren
const byte ZufallsZahl[] PROGMEM = {11, 23, 27, 31, 22, 35, 47, 76, 25, 12, 13, 14, 15, 91, 77, 99};
const byte Minimum PROGMEM = 1;
const byte Maximum PROGMEM = sizeof(ZufallsZahl);
// Zahl kann nicht ausgelagert werden
// -> ist dynamisch, wird im Programm verändert
byte Zahl;
void setup ()
{
// Zufallsgenerator starten
randomSeed(analogRead(A0));
Serial.begin(9600);
// auf serielle Verbindung warten
while (!Serial) {;}
Serial.println(F("Zahlen anzeigen:"));
Serial.println(F("----------------------------------------"));
for (byte i = 0; i < sizeof(ZufallsZahl); i++)
{
byte GezogeneZahl = random(Minimum, Maximum);
// pgm_read_word + GezogeneZahl = Wert im Array an der Postion GezogeneZahl lesen
Zahl = pgm_read_word(ZufallsZahl + GezogeneZahl);
Serial.print(F("Position im Array: \t"));
Serial.print(GezogeneZahl);
Serial.print(F("\tZahl: "));
Serial.println(Zahl);
}
}
void loop()
{
// bleibt leer, Programm läuft nur einmal
}
Ein weiteres, ausführlicheres Beispiel:
const byte ZufallsZahl[] PROGMEM = {11, 23, 27, 31, 22, 35, 47, 76, 25, 12, 13, 14, 15, 91, 77, 99};
const byte Minimum PROGMEM = 1;
const byte Maximum PROGMEM = sizeof(ZufallsZahl);
const char Buchstaben[] PROGMEM = {"abcdefghijklmnopqrstuvwxyz"};
// Zahl kann nicht ausgelagert werden
// -> ist dynamisch, wird im Programm verändert
byte Zahl;
void setup ()
{
// Zufallsgenerator starten
randomSeed(analogRead(A0));
Serial.begin(9600);
// auf serielle Verbindung warten
while (!Serial) {;}
// Buchstabensalat
Serial.println(F("Buchstabensalat:"));
for (byte i = 0; i < strlen_P(Buchstaben); i++)
{
byte GezogeneZahl = random(Minimum, Maximum);
char EinzelnerBuchstabe = pgm_read_byte_near(Buchstaben + GezogeneZahl);
Serial.print(EinzelnerBuchstabe);
}
Serial.println(F("\n----------------------------------------"));
// Anzahl der Elemente im Array Zahlen anzeigen
byte AnzahlElemente = pgm_read_byte(&Maximum);
Serial.print(AnzahlElemente);
Serial.println(F(" Elemente im Array Zahlen"));
Serial.println(F("Zahlen der Reihe nach anzeigen:"));
Serial.println(F("----------------------------------------"));
// Array Zahlen der Reihe nach anzeigen
for (byte i = 0; i < sizeof(ZufallsZahl); i++)
{
Zahl = pgm_read_byte(ZufallsZahl + i);
Serial.print(Zahl);
Serial.print(F(" "));
}
Serial.println(F("\n----------------------------------------"));
Serial.println(F("Zahlen in zuf\u00e4lliger Reihefolge anzeigen:"));
Serial.println(F("----------------------------------------"));
for (byte i = 0; i < sizeof(ZufallsZahl); i++)
{
byte GezogeneZahl = random(Minimum, Maximum);
// pgm_read_word + GezogeneZahl = Wert im Array
// an der Postion GezogeneZahl lesen
Zahl = pgm_read_byte(ZufallsZahl + GezogeneZahl);
Serial.print(F("Position im Array: \t"));
Serial.print(GezogeneZahl); Serial.print(F("\tgezogene Zahl: \t"));
Serial.println(Zahl); //Serial.print(F("\t "));
}
}
void loop()
{
// bleibt leer, Programm läuft nur einmal
}
Obwohl das Programm deutlich umfangreicher ist, wird nicht mehr Speicher verbraucht.
Das Programm ohne Optimierung benötigt mehr als doppelt so viel Speicher:
int ZufallsZahl[] = {11, 23, 27, 31, 22, 35, 47, 76, 25, 12, 13, 14, 15, 91, 77, 99};
int Minimum = 1;
int Maximum = sizeof(ZufallsZahl) / sizeof(ZufallsZahl[0]);
char Buchstaben[] = {"abcdefghijklmnopqrstuvwxyz"};
void setup ()
{
// Zufallsgenerator starten
randomSeed(analogRead(A0));
Serial.begin(9600);
// auf serielle Verbindung warten
while (!Serial) {;}
// Buchstabensalat
Serial.println("Buchstabensalat:");
for (byte i = 0; i < sizeof(Buchstaben); i++)
{
byte GezogeneZahl = random(Minimum, Maximum);
Serial.print(Buchstaben[GezogeneZahl]);
}
Serial.println("\n----------------------------------------");
// Anzahl der Elemente im Array Zahlen anzeigen
Serial.print(Maximum);
Serial.println(" Elemente im Array Zahlen");
Serial.println("Zahlen der Reihe nach anzeigen:");
Serial.println("----------------------------------------");
// Array Zahlen der Reihe nach anzeigen
for (int i = 0; i < Maximum; i++)
{
Serial.print(ZufallsZahl[i]);
Serial.print(" ");
}
Serial.println("\n----------------------------------------");
Serial.println("Zahlen in zuf\u00e4lliger Reihefolge anzeigen:");
Serial.println("----------------------------------------");
for (int i = 0; i < Maximum; i++)
{
int GezogeneZahl = random(Minimum, Maximum);
Serial.print("Position im Array: \t");
Serial.print(GezogeneZahl);
Serial.print("\tgezogene Zahl: \t");
Serial.println(ZufallsZahl[GezogeneZahl]);
}
}
void loop()
{
// bleibt leer, Programm läuft nur einmal
}
SRAM EEPROM Flash
Letzte Aktualisierung: