Arduino Duemilanove freier RAM Anzeige

Hallo an alle hier im Forum!

Ich habe schon einiges mit dem Arduino gemacht bzw. mit der Software Arduino0018 programmiert.

Seit neuestem habe ich eine relativ langen Source-Code, welcher anscheinend den RAM des Arduinos sprengt.
Drauf gekommen bin ich dadurch, dass nach der Programmierung des Arduinos ( und nur einer kleinen Veränderung, welche keinen Einfluss haben darf ) dieser dann sehr merkwürdige Sachen machte und Text auf der Seriellen nicht mehr ausgegen hat bzw. einen ganz anderen Text ausgegeben hat, obwohl dies eine Einschaltmeldung ist und immer gleich im Main-Programm auf oberster Stelle steht.

Daher habe ich recherchiert und bin drauf gekommen, dass es wahrscheinlich ein RAM-Overflow sein könnte.

Deshalb meine Frage: Gibt es irgendwie eine möglichkeit beim kompilieren eines Sketches den noch freien verfügbaren RAM anzeigen zu lassen? Gibt es vielleicht eine andere Programmiersoftware, welche dies unterstützt?

Vielen Dank schon mal im Voraus.

lg

Ja, Dein Ansatz ist richtig.

Es liegt daran, daß Du Dein Programm auslagern mußt wenn es zugroß wird, bzw. Du zugroße Variablen oder Inhalte hast.

Ich hatte das gleiche Problem.

Hier der Link bzw. Tipp der funktioniert hat:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1266081093

Lieber Gruß
ChrisS

Wow, vielen Dank für die schnelle Antwort!

Ich wusste nicht, dass die Zeichen, welche ich per serieller Schnittstelle sende, ins RAM kommen. Dachte eigentlich das diese fix im Flash sind und nichts mit dem RAM zu tun haben!?

Danke für den Tipp bzw. Link. Werde ihn mir mal durchlesen.

Gibt es aber auch eine Möglichkeit den noch verfügbaren Speicherplatz im RAM anzeigen zu lassen?

lg Gerald

Du mußt Dir klar machen was Ram (also "Laufzeitram") und was Flashram (SRAM) ist....

Dein Programm wird in compilierter Form ins Flashram/SRam geschrieben.
Wenn es gestartet wird, wird es allerdings im Ram ausgeführt.

Bedeutet für Dich... alles was größer als Dein Ram ist, und sei dein SRAM noch so groß... killt die Ausführung.

Die Variante mit Progmem läßt dein Programm auf im Sram hinterlegte Daten zugreifen. Also quasi eine Brücke vom Ram ins Sram.

Hier ein kleiner Code... bezieht sich aufs freie Flashram.

Serial.print("free memory = ");
Serial.print(availableMemory());
Serial.print(" - memory used = ");
Serial.println(8192-availableMemory());

int availableMemory()
{
 int size = 8192;
 byte *buf;
 while ((buf = (byte *) malloc(--size)) == NULL);
 free(buf);
 return size;
}

Im letzten Post von MEM ist eine kleine Library... die Dir die Infos ermöglicht die Du suchst.

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1213583720;start=all

Viel Spaß und Glück!!!

PS: Wenn Du es nicht hinbekommen solltest... einfach Code posten... wir sind hier Opensource :wink: dann kann man Dir vielleicht genauer helfen.

Lieber Gruß
ChrisS

Also mir ist der Unterschied zwischen den verschiedenen Speicherarten jedenfalls klar:

  1. Register
  2. RAM, die Atmels haben nur SRAM, kein DRAM, hier liegen Variablen. Inhalte gehen nach Strom abschalten verloren. Nicht nach Reset!!!
  3. EEPROM, persistenter Speicher für Daten die das Programm kontrolliert
  4. Flash, persistenter Speicher für das Programm

Das kompilierte C Programm wird im Flash gespeichert. Wenn da der Platz nicht reicht, dann kann man das Programm schon gar nicht sinnvoll in den Prozessor schreiben. Das Programm wird immer im Flash ausgeführt. Nur die Variablen kommen ins RAM.

Zur Laufzeit kann es sein, daß das RAM nicht reicht. Das liegt daran, daß der Stack und der Heap von verschiedenen Seiten allokiert werden. Sobald man zuviel Platz verbraucht kommen sich Stack und Heap in die Quere. Danach geht einiges (bzw. so ziemlich alles) schief.

Ob noch Platz ist ermittle ich so:

void free_dump() {

      uint8_t *heapptr;
      uint8_t *stackptr;

      stackptr = (uint8_t *)malloc(4);   // use stackptr temporarily
      heapptr = stackptr;                // save value of heap pointer
      free(stackptr);                    // free up the memory again (sets stackptr to 0)
      stackptr =  (uint8_t *)(SP);       // save value of stack pointer


      // print("HP: ");
      pgm_print(PSTR("HP: "));
      println((int) heapptr, HEX);

      // print("SP: ");
      pgm_print(PSTR("SP: "));
      println((int) stackptr, HEX);

      // print("Free: ");
      pgm_print(PSTR("Free: "));
      println((int) stackptr - (int) heapptr, HEX);
      println();
}

Das ist nicht ganz so gefährlich wie die von ChrisS beschrieben Methode. Die hatte ich früher mal im Einsatz und damit eher schlechte Erfahrungen gemacht. Grund: sie schlägt zu spät an. Ich habe nie analysiert warum genau, aber die Methode oben scheint bisher zuverlaessig zu funktionieren.

pgm_print und print sind Spezialversionen weil ich schon die Print Library rausgekegelt habe (verbraucht unnötig Ram und Flash und bei mir ist es eng). Einfach wieder durch die normalen Serial.prints ersetzen.

Regelmaessig kommt die größte unnötige Rambelegung daher, daß eigentlich konstante Strings im Ram abgelegt werden. Daß kann man mit den "Progmem" Makros beheben.

http://www.cs.mun.ca/~paul/cs4723/material/atmel/avr-libc-user-manual-1.6.5/pgmspace.html

Das ist allerdings nichts für Anfänger. Mit den Progmem Makros kann man sich ganz schön selber austricksen. Allerdings holt das mit am Meissten raus.

Was dann auch noch ganz schön reinhaut ist der relativ große Puffer für die serielle Kommunikations.

Die einfachste Massnahme ist grundsätzlich einfach den nächstgrößeren Prozessor zu nehmen. Wenn das nicht geht siehe oben. Wenn Flash das Problem ist --> auf ISP umsteigen und als erstes den Bootloader über die Klippe schieben.

Gruß, Udo

Hey Udo, ich weiß Du hast keine Zeit....

bitte irgendwann alles mal in den Playground schieben,
und sei es der englische Playground...

Hast recht, S mit D verwechselt...
nichtsdestotrotz wollte ich es möglichst einfach umschreiben,
.... hast Du aber definitiv besser gelöst als ich....

Lieber Gruß
ChrisS

Hallo!

Vielen Dank für die ausführlichen Infos!
Mir ist nur noch nicht ganz klar, warum der Text, den ich über die Serielle Schnittstelle rausschreibe, in den RAM gelegt wird. Ist der Text nicht als konstant anzusehen und wird vom Flash gelesen?
Oder muss anhand der Anzahl der Bytes in diesem String auch die Variablen im RAM reserviert werden?

Dieses Thema beschäftigt mich schon die ganze Zeit, da ich es verstehen möchte, jedoch für mich nicht wirklich durchschaubar ist.
Deswegen wäre es nicht schlecht zu wissen, wie der Prozessor bzw. Compiler und der Speicher ( RAM ) mit der seriellen Schnittstelle zusammenhängen.

lg Gerald

Serielle Schnittstelle und Strings haben nur zufällig etwas miteinander zu tun. Man gibt häufig Strings über die serielle Schnittstelle aus, daß ist alles.

Die Sache mit den Strings liegt daran, daß die Atmels eine Harvard Architektur (Programm und Variablenspeicher sind getrennt) haben und C Compiler für von Neumann Architekturen (ein Speicher für alles) ausgelegt sind.

Der Compiler löst das so, daß eben Programme in den Flash Speicher kommen aber alle Variablen bei der Initialisierung ins Ram kopiert werden. Er kann ja nicht wissen, daß die Strings sich nicht ändern sollen. OK, er könnte es wissen aber es hilft nichts weil die Speicherarithmetik dann anders ist.

Da der Compiler also nicht selber weiss was gewünscht ist nimmt er wenn man nichts sagt daß, was bei einer von Neumann Architktur passieren würde --> die Strings kommen ins Ram. Wenn man mit den Makros arbeitet passiert das nicht. Aber man kann dann die normalen Stringfunktionen nicht mehr benutzen weil die ja für eine von Neumann Architektur ausgelegt sind.

Achso ok, dann versteh ich das schon etwas besser warum es dann so leicht zu einem Overflow kommen kann.

Gibt es jedoch irgendeine Möglichkeit die RAM-Ausnutzung beim Compilieren schon anzuzeigen? Damit ich weiß ( ohne das Programm im uC laufen zu lassen ) wie weit ca. der RAM ausgenutzt ist bzw. ob ich schon einen Overflow habe?

Vielen Dank nochmals für die Infos!!

Wie sollte das gehen? Der Compiler kann ja nicht wissen was das Programm zur Laufzeit so alles tun wird. --> es geht nicht.

Naja, wenn Du viele statische Variablen/Strings hast, die den Hauptteil des Programms ausmachen, dann kannst du Dich schon daran orientieren, und daß dürfte vielleicht sogar der Normalfall bei Beginern sein.

Ich denke die dynamische erzeugung von Inhalten die die Grenzen des Speichers sprengen ist dann schon eher der semi-professionelle Part.

Tja, wie kann man es nun machen...

Garnicht! Aber es gibt mechanismen die man zur Abschätzung nutzen kann. Die sind aber gehobenes Level, und wahrscheinlich eher nicht das was Du umsetzen willst, weil kompliziert.

Udo ist da Experte, und er weiß weshalb er darauf nicht näher eingeht.

Es ist definitiv nicht sinnvoll, es sei denn es muß unbedingt sein... bis aufs letzte Byte den Speicher auszulasten...

Wie gesagt, Du kannst mit entsprechender Programmierung Inhalte je nach Atmega-Modell im Bereich irgendwas um die 16-32k speichern. Das ist viel...

Der Overflow liegt einfach am falschen Umgang mit den Variablen...

Wie gesagt, Progmem hat mir damals sehr geholfen....

Lieber Gruß
ChrisS

@ChrissS Zur Erinnerung: ich hatte nicht gesagt, ich hätte grundsätzlich keine Zeit. Ich hatte gesagt, ich habe dafür keine Zeit weil ich es für wenig sinnvoll halte. Die Gründe hatte ich schon aufgeführt.

Davon abgesehen: lies doch einmal das was ich im Playground abgelegt habe bevor Du wieder um ein Tutorial bettelst:

Arduino Playground - HomePage verweist auf
AVR-Tutorial – Mikrocontroller.net

Und dort steht was?
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Speicher
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Speicherzugriffe

D.h. es gibt bereits ein sehr gutes deutsches Tutorial. Nur steht da nicht dauernd drin "alles was hier steht gilt auch für den Arduino".

Was den "Experten" angeht: ich bin KEIN Experte. Ich habe nur die genannten Tutorials durchgelesen und lese gelegentlich auch die Datenblätter.

Udo

"Davon abgesehen: lies doch einmal das was ich im Playground abgelegt habe bevor Du wieder um ein Tutorial bettelst:"

Hallo Udo, daß hört sich etwas negativ an. Ich nehms aber nicht persönlich.

Was meine Beweggründe angeht. Ich gehöre absolut nicht zu den Leuten die "Kannste mir mal, haste mal, will ich haben mach Du das" gehören.

Aber ich bin vor ca. nem halben Jahr auf den Arduino gestoßen weil ich eine Alternative zu der Platine vom großen C gesucht habe.

Ich habe Hardware und eine Community gefunden, die etwas macht was eigentlich wundervoll für jeden Einsteiger ist, Bereitstellung von Hardware und Software in leichtverständlicher Form, Nutbarkeit für Anfänger, eine Community die lebt und Unterstützt.

Ich kenne Microcontroller.net, und ich finde Deinen Einsatz absolut ok.

Ich stelle aber fest daß man in der deutschen Ecke nur vereinzelt auf wirklich aktive Member stößt. Du bist einer der aktivsten die ich hier bemerkt habe, und bei der Anzahl von Posts und insbesondere deren Qualität denke ich daß man Dich als Anfänger durchaus als Experten werten kann. Versteh es als Lob.

Natürlich kann man sich fast jegliche Information aus dem Netz oder Datenblättern holen, wenn ich den Spirit von Arduino aber auch als Einsteigerplattform wahrnehme (sonst würden wir hier wahrscheinlich Assembler progen) ist die Informationsbeschaffung und Aufbereitung für Einsteiger einfach ein Faktor. Man muß das Rad nicht neu erfinden, und die Verlinkung ist sicher schon ein guter Ansatz.

Ein ganz kleines bisschen gehts aber auch um die wahrgenommene "äußere Qualität" einer Plattform.

Faktisch brauche ich auch kein microkontroller.net... google würde da reichen, aber arduino ist aus meiner Sicht genau das Gegenteil, es soll erleichtern. Ich finde das Zusammentragen von Informationen, das aufbereiten für Einsteiger nicht verwerflich, denn wenn das niemand macht hätte auch microcontroller.net oder wer auch immer keine Tutorials.

Gut, ist alles etwas offtopic hier...
Es war nicht als Angriff gemeint... im Gegenteil, wie schon geschrieben, schätze ich Deinen Einsatz hier erheblich... und so war das auch gemeint.

Lieber Gruß
ChrisS

War mir nicht bewusst, dass es doch so schwierig ist, den RAM-Verbrauch zu ermitteln.
Ich werde einfach in zukunft besser drauf aufpassen, wie ich die Variablen und konstante Strings einsetze!
Eure Antworten habe mir schon sehr viel geholfen!!

lg Gerald

@Chriss: es geht nicht darum, daß das Erstellen von Tutorials für Einsteiger verwerflich wäre. Das habe ich nie gesagt. Es geht darum, daß das Erstellen solcher Tutorials Zeit kostet die ich lieber für andere Dinge verwende.

Die Argumentation mit der Einsteigerplattform verstehe ich, aber da bin ich die falsche Adresse. Wenn eine Plattform den Anwendern nicht gut genug dokumentiert ist, dann ist die erste Adresse immer der Hersteller.

Gruß, Udo