Hi,
Here's the question.... is there any way of conclusively telling if lack of memory is causing problems?
Here's the background....
I have a datalogger project that I have run successfully on a arduino mega and an arduino mini-pro.
The project used to compile, upload and run on both arduinos, the only difference was that on the mini-pro I would get warnings about lack of memory (99% of program storage space and over 90% of dynamic memory).
This wasn't a problem (then) because exactly the same code would work in exactly the same fashion on both devices.
I've had to make some amendments, and the code still compiles and uploads to both devices, but it only works on the mega. I still use the same amount of memory (+- a percentage point or two) and get the same warnings, the only difference is that the file I log to remains empty (no error messages, no other sign of problems), the file just remains empty. (all other behavior is normal, the display updates ok, and all the sensors still work)
To pre-empt a couple of questions, I have done the development on a mega, just because that's what I happened to have lying around, and run it on a mini-pro because I needed to make it small. I've come up with a solution, because I've managed to physically squeeze the mega version into the physical space available, so the question is now just academic, but if something like this happens again I'd really like to know how to tell if lack of memory really is the root of the problem.
The following function is handy for determining how much memory you have available:
//
// Used in calculating free memory.
//
extern unsigned int __bss_end;
extern void *__brkval;
//
// Returns the current amount of free memory in bytes.
//
int freeMemory() {
int free_memory;
if ((int) __brkval)
return ((int) &free_memory) - ((int) __brkval);
return ((int) &free_memory) - ((int) &__bss_end);
}
There are some issues, however:
- This doesn't do any good unless you call it at appropriate times.
- What you call dynamic memory is affected by calls to functions. Thus, calling freeMemory() has an affect on how much memory is available.
- Having deeply nested functions and/or functions that use a lot of dynamic memory for their own purposes (e.g. variables) can consume a lot of memory temporarily.
- You can have lots of available memory and still run into problems if the memory space gets really fragmented.
Using more memory by a percentage point or two may be all it takes to go over the edge. Changing your code (for example, by making functions more deeply nested) can also put you over the edge. Remember that code tends to either work or not work, there is rarely a "sort of works".
The experts here can suggest ways to save space, but only if you post your code (and use code tags!).
90% of SRAM is really pushing your luck. It's because there must be room for the stack.
The freeMemory() function vaj4088 posted can provide clues, but you have to figure out where in your code (including the libraries) that the maximum amount of memory is used. This requires some experimentation.
Another approach is to add some code that writes a pattern into RAM at startup and then, at a later point, checks to see how far in the address space the pattern has been disturbed.
Neither of these are guaranteed to give you the correct answer, particularly in a complex sketch with many possible branches. But in a straightforward logging sketch you may be able to figure it out.
Yet another approach would be to allocate a global array of 6K and run the sketch on your mega. Since this will effectively turn your mega into a device with only 2K RAM you should get the same symptoms as you do with your mini-pro. Then decrease the size of the array until the problem goes away.
The 6K global array approach is CLEVER!