How to determine insufficient RAM? FreeRam() shows available but fail to run!

Greetings to all arduino Gurus. Recently i was developing a project, by using Arduino Uno as the base, integrate with Ethernet+SD shield and a LCD shield. The objective is to use LCD as the Menu, buttons to navigate through Menu pages, and to select the .ini file read from the SD card. Whenever any of the .ini file is selected, it will read that .ini file to find the Section/key and send the values/data by Ethernet via TCP. Hope I had gave you the rough idea on how it work now.

I had it minimized the RAM memory utilization. But problem came when it run for a few Menu navigate, or after sending the data to Ethernet. Sometimes it shows "Buffer too small" error in Serial (debugging), and always the characters show in the LCD is distorted (sometimes it hang and arduino restart itself!).

The weird part is, FreeRam() shows it still has around 600bytes available!

Attached the code below: (sorry that it has 29800byte size and messy coding :~)

BoxV6.ino (10.9 KB)

Please note that in versions of the IDE up to and including 1.0.3, the String library has bugs as discussed here and here.

In particular, the dynamic memory allocation used by the String class may fail and cause random crashes.

I recommend reworking your code to manage without String. Use C-style strings instead (strcpy, strcat, strcmp, etc.), as described here for example.

Alternatively, install the fix described here: Fixing String Crashes

Preferably upgrade your IDE to version 1.0.4 or above at: http://arduino.cc/en/Main/Software

Thanks Nick for the information. But my IDE version is 1.0.5.

Even so, fragmentation of memory on the heap is a real concern. If it works for a while and then fails, this is a classic symptom.

If i use C-string style, it will eat up a lot RAM spaces, right?

No.

Where did you get this idea? A C-style string uses a fixed amount of memory, that you determine. Thus, if there is enough memory now, there always will be.

As a reference: Optimizing SRAM:

I do really had lost and no clue at all to fix this right. So perhaps i think the arduino Uno doesn't fit my project.
Just a basic read data from SD and serial, concatenate the data and put it into a buffer, send via Ethernet TCP and lastly, navigate Menu and display information on LCD. Is these too much for an Uno? :~

So it's the Uno's fault and not yours, eh?

But problem came when it run for a few Menu navigate, or after sending the data to Ethernet.

Clearly you are consuming memory in some way. If you switch to another device, you think that problem will go away?

I suggested you stop using String. Your response is that the device is at fault. Oh well, have it your way.

I will try to rewrite my code to avoid using string, thanks for your advice. I'm not pointing the fault at Uno, just maybe or I thought I had consume all the memory in some way as you said (but how do i determine that? FreeRam() shows sufficient).

Besides, could you share some lights on how or under what circumstance, the memory is depleted/insufficient?

Just a basic read data from SD and serial

Well that's 512 + 64 bytes right there.

AWOL:

Just a basic read data from SD and serial

Well that's 512 + 64 bytes right there.

Yup, and i left 600 byte running free.

const char *filename = "/Layouts/setting.ini";

    lcdDisplayBtm(B01111111,"BTN1          ",B10100000);
  }else if (x==0){
    lcdDisplayBtm(B10100000,"          BTN2",B01111110);
  }else{
    lcdDisplayBtm(B01111111,"BTN1      BTN2",B01111110);

There's another 70.

AWOL:
const char *filename = "/Layouts/setting.ini";

    lcdDisplayBtm(B01111111,"BTN1          ",B10100000);

}else if (x==0){
    lcdDisplayBtm(B10100000,"          BTN2",B01111110);
  }else{
    lcdDisplayBtm(B01111111,"BTN1      BTN2",B01111110);



There's another 70.

Can i ask a silly question, does the RAM always increasing when it loop? Or is it allocated a fix size for them?
In my loop(), i use FreeRam to monitor the memory changes. But it constantly feedback the same amount (~600b), despite I navigate the Menus, or reading and sending data via Ethernet. So I assumed I still have free memory.

Thank you for your helping. I'm glad.

Explain to me your understanding of fragmentation. Then I'll know that you are really glad.

What I understand of fragmentation is the computer program request block of memory, holds it and when finish, it release back the memory in chunk. Eventually the chunk is chopping into different sizes, thus, at the end the program could not request a larger chunk of memory. That's leads to data fragmentation. Please correct me if I'm wrong. :cold_sweat:

If that so, how do we overcome this problem?Fragmentation.

If that so, how do we overcome this problem?Fragmentation.

By not allowing it to happen, by not employing methods that are likely to cause it.

Remember that memory is used temperarily by the stack when calling functions,
and depends on the function called - unless you leave a generous amount free
you won't have peace of mind that the same code will always run safely, since the
arguments to a function can affect its pattern of calling and thus maximum stack
use.

I recommend making as much of the big memory gobblers statically allocated/declared
so that there are no surprises later on. You can then be reasonably confident that
the free memory measured at the end of setup() represents most of what's available
to the stack for the rest of the sketch.

Sometimes you can't do this because of the way a library has been implemented
of course.

thumthum:
If that so, how do we overcome this problem?Fragmentation.

Your understand is fine. Now:

String inData;
...
       char recieved = Serial.read();
        inData += recieved;

This is the exact sort of thing that causes it. The String class has to keep allocating memory in small units (1, then 2, then 3, etc.).

Eventually you end up with lots of small amounts over, but not close enough together to be useful.

If your inData is a known maximum length (which it better be, as you only have so much RAM) then make a char array instead.