During the writing of my beehive monitoring project "Apaguard " using an Arduino UNO, i've been quickly very clode to the SRAM limit...

The Arduino UNO has "only" 2048 bytes of SRAM, which can quickly be filled if no precautions are taken.
Here are a few tricks i used during my writing, which permitted me to save a lot of SRAM and should be used by anyone coding on Arduino.

Ruel number 1 : declaring the right variables

1) Always use the right type of variables in your declaration. Right means, the smallest memory usage as possible. This table gives the memory space  used for each type of vaiable.

Type Min Max Size Perf
byte 0 255 8  :)
char -128 127 8  :)
unsigned int 0 65 535 16  :/
int −32 768 32 767 16  :/
unsigned long 0 4,294,967,295 32  :(
long -2,147,483,648 2,147,483,647 32  :(
float / double -3.4028235E+38 3.4028235E+38 32  :'(

For example, if a variable x will vary from 0 to 10, declare it in BYTE abd nt INT. This alone, will save you 8 bytes !

If possible, avoid the usage of FLOAT variables. They are consuming a lot of memory and need a lot of CPU time when manipulated.

2) All variables that will NOT be modified, that means "read only" should be declared as CONST. They will be stored in FLASH Memory, not SRAM.

For example byte x = 10 should be declared like const byte x = 10 . Change also byte pinPowerGSM = 13 to const byte pinPowerGSM = 13

3) Use the PROGMEM function to place ARRAY and BITMAPS variables in the FLASH memory. Is only really interesting when hadling large arrays as they are some restrictions o the usage of this function.

PROGMEM is a function of the pgmspace.h library that must be loaded by adding :  #include <avr/pgmspace.h>

Ex : const char apn[]  = "orange"  becomes const char apn[] PROGMEM = "orange"

To read the variables, you must use another function of the pgmspace.h library :  pgm_read_xx. Check in the documentation on how to handle these PROGMEM functions.

Rule number 2 : Global and local variables

In a general manner, using global variables is not recommended. Use local variables whenever possible. If a variable is used only inside a function, declare it in this function.

When a global variable is declared, its address is stored in the SRAM. Manipulating global variables costs extra bytes to access to this addresses...

Rule number 3 : Use the F macro !

Probably the most bytes saving rule ! When using print functions, like print, println, Serial.print, etc., the compiler is loading the text to be written in the SRAM but there is no need to do that ... The F macro has been written to load these texts in the FLASH memory, saving some extra bytes.

ATTENTION, only to be used with pure text, not with variables!! Take the good habit to write your code using this function, you will make a huge SRAM economy !

Ex : Serial.println ("This is a test") should be written Serial.println (F("This is a test"))

Rule number 4 : optimize your loops !

As amazing it could sound, loops that decrementing are consuming less ressources than loops that are incrementing variables ! Use i-- instead of i++ .

do {} while loops are generally more efficient than while{} and for {expr1;expr2;expr3}

Also, try to integrate statements and operations from different loops to fewer or onl one loop.

Rule number 5 : Use the conditional compiling !

Very often during a sketch writing, we need to display texts to the serial port for debugging and tests. Once the software works perfectly (lucky guy) these informations are not needed anymore and can bee deleted or commented to save some SRAM and FLASH memory.

A much more elegant and easy way to do that, is to use a compiler option named conditional compiling.

Ex :

// uncomment next line for developing phase

void setup(){
void loop() {
    Serial.println(F("Program started. Wait for wakeup !"));

By commenting or decommenting this option, the compiler will include or exclude the code lines between the #ifdef DEBUG_DISPLAY ( or any other word like TEST ) and #endif.
Anything can be written between these options, commands, functions, etc...


References :