Memory Overflow Exception
While working on FAR 🚀 I noticed that memory management will be crucial to making sure not only the code runs efficiently but can actually be loaded onto the Arduino Board. Coming from a desktop and web background with a PC and Server with more than 16gb of RAM terabytes of storage and processors clocked at 4.0ghz+ developing for an Arduino Board has been quite the experience. I have had to take much more into consideration while developing for an Arduino Uno than I normally would have to. In this post I will specifically talk about managing both the RAM and FLASH Memory usage. This has proven to be a challenging but valuable test of my development skills and has forced me to go back to many fundamentals that I admit have ignored for years.
Getting Started
For those who are not familiar Arduino Boards are microcontrollers that can be programmed in a C/C++ based language, they are incredibly easy to use and inexpensive. While incredibly useful due to their small footprint, they are very limited in speed and memory. Normally this is not an issue since Arduino Projects are small, but in the case of a flight controller it has proven to be an interesting challenge since many libraries have to be linked together to get all the submodules to work and even more code is needed to process that information and make decisions. While I am still a distance from testing this inside an actual model rocket or plane, I have begun to have to make many decisions on the direction I want to go in, to insure I have enough resources left in the board for the software to properly function.
RAM and FLASH
Flash Memory is the memory the program is stored in. After compilation the code is uploaded to the Arduino’s Flash Memory. From there it is run every time the program begins. Therefore if your codebase (post compilation) exceeds the Flash’s memory limit, you will not even be able to upload the code to the Arduino. In my case I am using about 57% of the Uno’s Flash. This though was brought down from 60% and I plan on doing more optimizations to bring it down even more so I can fit more code into the limited space. This is accomplished by writing cleaner code, and being mindful of repeated processes and variables in classes. This can be done with the use of classes and functions that group together common tasks your program will run. This will save a lot of space and time in the long run and produce cleaner and easier to read code. While this should be done already in any project it is a good reminder to look for repeated tasks and simplify them into a function.
RAM is the memory used by variables and is dynamically allocated and changed at runtime. Read This if you want more information on RAM and how it functions. All you really need to know for your Arduino is, the larger your variables are the more RAM you will use up, so it is crucial to use the correct data type for your variables and also if you can clean up the unused variables, and properly deconstruct your classes to make sure no memory stays allocated that does not need to be. An example of this is const int i = 100
can be const byte i = 100
this is because i
will always be 100, therefore why store it in a data type that takes up 2 bytes when you can store it in a variable that takes up 1 byte. If you expand this logic across your entire program you can save large sums of data. This technique works well in regular development and should always be considered.
These both need to be taken into consideration when writing your software. It is crucial to keep both these memory limitations in mind and write clean code and also use the correct data types otherwise you will run into issues as you expand your project, which may prove difficult to fix if you did not use the proper software development techniques from the start.
Arduino Memory Table
This is a list of the Boards I am considering using, each has their advantages and disadvantages. As you can see as well each has different amounts of RAM and Flash Memory Avalalbe for use. This list was taken from Arduinos Documentations.
| Board | RAM | Flash |
|---------|------|-------|
| Uno | 2kB | 32kB |
| Nano | 2kB | 32kB |
| NanoE | 6kB | 48kB |
| NanoIoT | 32kB | 256kB |
|---------|------|-------|
Data Type Table
Here is a list of data types Arduino Supports. As you can see as the memory usage goes up so does the amount of data you can store. This is the important in regular development but even more so when working with a limited amount of memory, since if you are not smart about your data type usage you can easily run out of memory.
| Data Type | Size | Range |
|-----------|-------|-----------------------------|
| bool | 1byte | 0 to 1 |
| char | 1byte | -128 to 127 |
| uchar | 1byte | 0 to 255 |
| byte | 1byte | 0 to 255 |
| int | 2byte | -32768 to 32767 |
| uint | 2byte | 0 to 65535 |
| word | 2byte | 0 to 65535 |
| long | 4byte | -21474383648 to 21474383647 |
| ulong | 4byte | 0 to 4294967295 |
| float | 4byte | -3.4028E+38 to 3.4028E38 |
| double | 4byte | -3.4028E+38 to 3.4028E38 |
|-----------|-------|-----------------------------|
In Conclusion
So how do we properly write our code to both run as intended and also not run out of memory?
Some solutions you can take are
- Make sure you use the proper data types for variables
- Do you only need to store a value between 1 and 100? Use a byte or (unsigned) char instead of an integer. There is no reason to store a value you do not expect to exceed 255 on an integer since you can store it in a byte and use up half the space in the programs memory.
- Choose the correct board for the project scope
- The boards I listed are just a few of the many Arduino and Third Party Vendors offer. If you are seeing 32kBs is not enough space, maybe its time to upgrade your board.
- This should be only after optimizing your code. Cleaner and efficient code is ALWAYS a better solution.
- Only use libraries you need
- This is crucial, since some libraries are very bloated and can take up a lot of the Flash memory, it is important to only include the Libraries you absolutely need or better yet, create your own.
Arduinos will test your skills as a developer because it is easy to write software when you are not limited by the resources of the computer system but when constrained to a limited amount of memory and processing power it forces you to come up with clever solutions and seriously think through your code. This has improved my skills as a developer over the 1 year of working on this project since it has forced me to reconsider what variables I am using and how they can affect the overall performance of any project I am working on. It has made me more careful with my choices and more deliberate and has even helped me bring down memory usage in other personal projects, which while it may not be a constraint like in this one it is good to know I am using less memory and writing more efficient and faster code.