As explained briefly the types of memories in Arduino, RAM (or SRAM) memory is the type that get ignored most easily, because there isn’t anywhere you can find out the usage footprint (well i should say not easy to find out). It usually hardly run out so we tend to forget about it. But if you do run out of RAM memory, your sketch will not work properly on your arduino, sometimes it doesn’t even allow you to upload the code.
Here I will show you how you can check the memory usage of your Arduino sketch, and a few things you can do to optimize Arduino memory usage.
What Happen If I Run Out Of RAM on Arduino?
If you run out of SRAM, your program may fail in unexpected ways; it will appear to upload successfully, but not run, or run strangely. To check if this is happening, you can try commenting out or shortening the strings or other data structures in your sketch (without changing the code). If it then runs successfully, you’re probably running out of SRAM.
SRAM Explained
On the Uno we have 2KB of RAM, and 8KB on the Mega2560. Notice that there’s not much SRAM available in the Uno. It’s easy to use it all up by having lots of strings in your program. For example, a declaration like:
char string[] = "Today is a sunny day";
This puts 20 bytes into SRAM plus the ” terminator (1 extra byte). This might not seem like a lot, but it doesn’t take long to get to 2048 bytes.
Global and Static variables are the first things loaded into SRAM. They push the start of the heap upward toward the stack and they will occupy this space for all eternity.
Variables created in functions, are dynamically allocated objects and data. Unlike Global and Static variables, these variables can be de-allocated to free up space at function exit. But Every function call creates a stack frame that makes the stack grow toward the heap. This data is usable within the function, but the space is 100% reclaimed when the function exits!
Measure Arduino RAM Usage
In the arduino IDE directory there is the avr-gcc compiler. It also contains a tool named ‘avr-size’. Go to hardware/tools/avr/bin/ and it should be there.
When compiling, the IDE will create a temporary directory in your temp directory and copy all the C(++) files to it. For example in Windows 7, This is C:Users[your username]AppDataLocalTempbuild[random tag][Sketch name].cpp.elf
You need to run avr-size.exe, type the path to my temporary folder and hand it the elf file.
The output of avr-size looks very similar to this. The result means
- text – flash data used for code
- data – Memory with initialized data (the initial value has to be stored in FLASH too!)
- bss – Memory that is initialized with zero’s (the compiler will add some code so it will initialize data & bss)
- dec & hex are a decimal and hex display of the combined RAM and FLASH size of your program.
The Arduino IDE reported to me this program is 3956 bytes big (FLASH). That’s related to 3924 (code flash) + 32 (initial RAM values) = 3956 bytes FLASH. The RAM usage is data+bss combined(!) = 32+320 = 352 bytes SRAM usage.
This is a usually tool for fixed RAM allocations, however it’s important to realize that it does not count the RAM used by automatic variables local to a function or block which are allocated on the stack at the start of execution of that function and deallocated at the end. That can only be determined by executing (or simulating) a particular path through the program.
You can also find out Adafruit’s different method.
Memory Optimization Tips
There are a few things you can do to address this problem:
- Avoid dynamic heap allocations – These can quickly fragment the limited heap-space.
- Prefer local to global allocation – Stack variables only exist while they are being used. If you have variables that only are used in a small section of your code, consider making that code into a function and declaring the variables local to the function.
- If your sketch talks to a program running on a (desktop/laptop) computer, you can try shifting data or calculations to the computer, reducing the load on the Arduino.
- If you have lookup tables or other large arrays, use the smallest data type necessary to store the values you need; for example, an int takes up two bytes, while a byte uses only one (but can store a smaller range of values).
- If you don’t need to modify the strings or data while your sketch is running, you can store them in flash (program) memory instead of SRAM; to do this, use the PROGMEM keyword.