ich habe ein Speicherproblem auf meinem Arduino Uno (328) und dazu zunächst mal grundsätzliche Verständnisfragen:
Beim Compilieren wird mir ja die Sketch-Größe angezeigt. Beinhaltet diese den reinen Programmcode oder auch schon die reservierten Speicherbereiche für die Variablen?
Mein Programm benötigt eine ganze Reihe von Arrays, diese werden so vor der Setup-Funktion erzeugt:
#define ANZAHL_JOBS 100
int Wert1[ANZAHL_JOBS] = {0};
int Wert2[ANZAHL_JOBS] = {0};
float Wert3[ANZAHL_JOBS] = {0};
unsigned long Wert4[ANZAHL_JOBS] = {0};
...
Das Programm läuft stabil solange ich die Anzahl_Jobs relativ klein halte. Ab einer gewissen größe Crasht das Programm und gibt über ein Serial.println nur noch wilde Zeichen zurück. Ich gehe davon aus dass ich irgendwo im Programm einen Fehler habe der sich eben erst ab einer höheren Arraygröße auswirkt (unkontrollierte Speicherbefüllung).
Um den Fehler einzugrenzen habe ich die Arrays bewust sehr hoch eingestellt und Bereiche des Programms auskommentiert um festzustellen bei welchem Teil das Problem auftritt. Nun habe ich festgestellt dass die Sketchgröße kleiner ist als rein rechnerisch die Summe des benötigten Speichers für die Arrays??? Wann wird genau der Speicher für die Arrays festgelegt und "reserviert"?
Um die Verwirrung komplett zu machen: In einer aufgerufenen Funktion steckt eine for-Schleife - diese habe ich zu Debug-Zwecken komplett leer geräumt und statisch auf 5 Durchläufe gesetzt. Alleine die Existenz der for-Schleife (Ohne Inhalt!) bewirkt dass der Sketch auf einmal riesen groß wird. Es scheint als ob erst mit der For-Schleife der Speicherplatz der Arrays "eingeplant" wird. Kommentiere ich die For-Schleife aus ergibt die Compilierung lediglich ca. 5.000 byte. (Alleine die Arrays müssten ca. 50.000 byte haben - passt nicht auf das Uno, ist mir klar) Mit der For-Schleife bekomme ich dann (verständlicher weise) die Fehlermeldung das das ganze zu groß ist.
Vielleicht kann mir jemand kurz den Zusammenhang zwischen Sketchgröße und reserviertem Speicher für Variablen/Arrays erklären.
Danke.
Unbenutzte Variablen/Funktionen werden wegoptimiert.
Zumindest soll es so sein.
Klappt aber scheinbar nicht immer.....
Dein eingangs geschildertes Problem deutet auf einen Stacküberlauf hin.
Vorbelegter Speicher wächst von 0 nach oben.
Der Stack von oben, also den hohen Adressen, nach unten.
Wenn sich diese beiden begegnen gibts die lustigsten Erscheinungen.
Beinhaltet diese den reinen Programmcode oder auch schon die reservierten Speicherbereiche für die Variablen?
Nur den Programmcode.
Die neueste IDE (Beta?) zeigt auch den Platzbedarf der Variablen
Jetzt wird mir einiges klarer. Das heißt ich muss selbst überlegen ob der "übrige" Speicher (32k - Sketch) für die Variablen reicht.
Das hilft mir erst mal weiter - ich vermute dann hat mein Programm gar keinen Fehler sonder es passiert genau die von dir beschriebene Überlagerung ab einer bestimmten Arraylänge.
Ich werd mir mal die neueste IDE besorgen - dann sehe ich zumindest ob ich den Speicherbedarf richtig berechnet habe.
Hab die Beta IDE installiert - die zeigt das ja wunderbar an. Das ist TOP!!! Da hätte ich mir gester einige Stunden Fehlersuche spaaren können...
Ich bin schon mal irgendwo über eine Diskussion gestolpert die Variablen im Flash ablegt - da mach ich mich nochmal auf die Suche...
Eine physikalische Erweiterung geht vermutlich nicht oder?
Muss es denn unbedingt float und long sein? Kann man das nicht irgendwie als ausdrücken? Fließkommawerte entstehen ja oft erst durch Division, diese Rechnung kann man dann beispielsweise dort ausführen wo der Wert gebraucht wird, so muss man nur einen int Wert speichern der vielleicht auch in 16 oder gar 8bit passt. Wenn man nicht gar ganz auf Float verzichten kann. Zum Beispiel indem man nur mit einer festen Anzahl Nachkommastellen arbeitet.(Festkommaarithmetik)
Alleine die Arrays müssten ca. 50.000 byte haben
Double precision floating point number. On the Uno and other ATMEGA based boards, this occupies 4 bytes. That is, the double implementation is exactly the same as the float, with no gain in precision.
Du kannst den Flash Speicher gar nicht so einfach im laufenden Betrieb ändern. Also ist das rein theoretisch. Von der Hardware geht das schon: http://www.atmel.com/images/doc1644.pdf
Aber das wird vom Arduino nicht unterstützt. Und wenn wäre es nicht so einfach wie im normalen Code eine Variable zuzuweisen.
Eine physikalische Erweiterung geht vermutlich nicht oder?
Der atmega328 des Uno ist nicht der größtmögliche 8bit-Controller von atmel.
Beim Arduino Mega (atmega2560) hast du vier mal so viel RAM ( 8 kB ).
Dann gibt es noch externe Speicher-Module, die aber nicht so einfach in den RAM-Adressbereich eingebunden und für heap oder stack Variable verwendet werden können. Üblicherweise könntest du die per I2C ansprechen.
Wenn du ganz andere Größenordnungen RAM brauchst, brauchst du was anderes als einen 8-bit µC.
Ja, ich bin auch schon davon abgekommen. Flash ist ja "read-only" das bringt mir also gar nichts.
Variblen optimieren ist sicher ein Ansatz, das ist momentan sehr "großzügig" angelegt. Es geht teilweise um Geschwindigkeiten und Entfernungen, die habe ich momentan als float angelegt, da gibt es sicher platzsparendere Lösungen.
Auf die 50k komme ich da mein Codebeispiel nur einen Teil der Arrays darstellt, im richtigen Code sind es noch ne ganze Ecke mehr.
Den atmega2560 habe ich auch entdeckt. Da muss ich mich noch schlau machen. Das Uno-Board hatte ich gewählt weil es in Foren empfohlen wurde um LED-Strips ohne Clock anzusprechen. Da werde ich mal nachlesen ob die größeren Boards genauso geeignet sind (es ging glaube ich darum dass kein Linux oder so laufen darf...).
Mit 8kb kann ich mit Variablenoptimierung und Herunterstufen meiner Anforderungen an die JobAnzahl klar kommen - denke ich zumindest...