A Comparison of Arduino Sketch Sizes in Memory

A comparison of several Arduino sketches from the Arduino code examples, as well as some code that uses a combination of library functions, shows how much memory is used in an Arduino Uno. This gives a rough idea of what the Arduino Uno is capable of handling in terms of memory usage / sketch size before having to move up to an Arduino that has more memory such as the Arduino MEGA.

Memory Usage in the Arduino IDE

Older versions of the Arduino IDE only showed the amount of Flash memory (non-volatile memory) used by an Arduino sketch at compile time i.e. when the Verify icon is clicked on the toolbar.

Newer versions of the Arduino IDE now show both the amount of Flash memory and SRAM memory that a sketch will use after compiling. The amount of SRAM memory used does not include local variables, however the compiler message shows the amount of SRAM left for local variables.

Arduino IDE Showing Sketch Memory Usage

Arduino IDE Showing Sketch Memory Usage

 

 

 

 

 

 

 

 

 

 

 

The above image shows the Arduino IDE after compiling. The area below the sketch shows the messages from the compiler that displays the sketch memory usage.

Arduino Sketch Memory Usage Examples

The examples below show the memory usage reported by the Arduino IDE compiler. Arduino IDE version 1.6.4 compiling for an Arduino Uno is used for all the examples.

Most of the sketches can be found in the Arduino IDE examples under File –> Examples as shown below, a link is given to sketches that are not found in with the IDE examples. The SRAM usage does not include SRAM used by local variables. The Flash memory maximum size of 32,256 bytes is the Arduino Uno Flash memory size of 32,768 bytes, minus 0.5kB used for the boot loader program.

Blinking An LED

File –> Examples –> 01.Basics –> Blink
This simple sketch blinks the on-board LED on and off at a set interval.

Flash usage: 1,030 bytes (3%) of 32,256
SRAM usage: 9 bytes of 2,048

Reading Analog Input

File –> Examples –> 01.Basics –> AnalogReadSerial
Reads a single analog value and prints it to the serial port.

Flash usage: 2,382 bytes (7%) of 32,256
SRAM usage: 184 bytes (8%) of 2,048

Reading Digital Input

File –> Examples –> 01.Basics –> DigitalReadSerial
Reads the state of a single digital input and prints the result to the serial port.

Flash usage: 2,704 bytes (8%) of 32,256
SRAM usage: 184 bytes (8%) of 2,048

Using the String Object

File –> Examples –> 08.Strings –> StringLength
Measures the length of a string sent over the serial port using a String object.

Flash usage: 3,966 bytes (12%) of 32,256
SRAM usage: 300 bytes (14%) of 2,048

Getting SD Card Information

File –> Examples –> SD –> CardInfo
Used for testing a SD card.

Flash usage: 1,502 bytes (35%) of 32,256
SRAM usage: 1,348 bytes (65%) of 2,048

Writing To and Reading From the SD Card

File –> Examples –> SD –> ReadWrite
Writes text to a file on an SD card and then reads the text back from the file.

Flash usage: 12,930 bytes (40%) of 32,256
SRAM usage: 992 bytes (48%) of 2,048

A Simple Web Server

File –> Examples –> Ethernet –> WebServer
A simple web server that hosts a web page displaying values read from analog pins. Does not used the SD card.

Flash usage: 12,612 bytes (39%) of 32,256
SRAM usage: 552 bytes (26%) of 2,048

A Simple Web Client

File –> Examples –> Ethernet –> WebClient
A web client that fetches a web page from the Internet.

Flash usage: 14,568 bytes (45%) of 32,256
SRAM usage: 673 bytes (32%) of 2,048

Printing Text to a LCD

File –> Examples –> LiquidCrystal –> HelloWorld
Prints a message to an LCD.

Flash usage: 2,328 bytes (7%) of 32,256
SRAM usage: 55 bytes (2%) of 2,048

Displaying Text from the Serial Port on the LCD

File –> Examples –> LiquidCrystal –> SerialDisplay
Display text sent over the serial port to the Arduino.

Flash usage: 3,182 bytes (9%) of 32,256
SRAM usage: 214 bytes (10%) of 2,048

Web Server that Uses the SD Card

Basic web server that hosts a web page on the SD card from the Arduino Ethernet tutorial.

Flash usage: 22,806 bytes (70%) of 32,256
SRAM usage: 1,274 bytes (62%) of 2,048

Web Server that Uses the SD Card and LCD

This code is based on the above SD card web server, but also uses an LCD display to show some text during initialization and to display the amount of free SRAM.

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
#include <LiquidCrystal.h>

// MAC address from Ethernet shield sticker under board
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 20); // IP address, may need to change depending on network
EthernetServer server(80);  // create a server at port 80

File webFile;
// have to change the pin numbers from the example defaults when using the Ethernet shield
LiquidCrystal lcd(3, 2, 8, 7, 6, 5);

int freeRam () {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

void setup()
{
    // set up the LCD's number of columns and rows:
    lcd.begin(16, 2);
    // Print a message to the LCD.
    lcd.print("Initializing...");
  
    Ethernet.begin(mac, ip);  // initialize Ethernet device
    server.begin();           // start to listen for clients
    Serial.begin(9600);       // for debugging
    
    // initialize SD card
    Serial.println("Initializing SD card...");
    if (!SD.begin(4)) {
        Serial.println("ERROR - SD card initialization failed!");
        return;    // init failed
    }
    Serial.println("SUCCESS - SD card initialized.");
    // check for index.htm file
    if (!SD.exists("index.htm")) {
        Serial.println("ERROR - Can't find index.htm file!");
        return;  // can't find index file
    }
    Serial.println("SUCCESS - Found index.htm file.");
    lcd.setCursor(0, 1);
    lcd.print("Done.");
}

void loop()
{
    EthernetClient client = server.available();  // try to get client

    if (client) {  // got client?
        boolean currentLineIsBlank = true;
        while (client.connected()) {
            if (client.available()) {   // client data available to read
                char c = client.read(); // read 1 byte (character) from client
                // last line of client request is blank and ends with \n
                // respond to client only after last line received
                if (c == '\n' && currentLineIsBlank) {
                    // send a standard http response header
                    client.println("HTTP/1.1 200 OK");
                    client.println("Content-Type: text/html");
                    client.println("Connection: close");
                    client.println();
                    // send web page
                    webFile = SD.open("index.htm");        // open web page file
                    if (webFile) {
                        while(webFile.available()) {
                            client.write(webFile.read()); // send web page to client
                        }
                        webFile.close();
                    }
                    lcd.clear();
                    lcd.setCursor(0, 0);
                    lcd.print("Free RAM:");
                    lcd.setCursor(0, 1);
                    lcd.print(freeRam());
                    break;
                }
                // every line of text received from the client ends with \r\n
                if (c == '\n') {
                    // last character on line of received text
                    // starting new line with next character read
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                    // a text character was received from client
                    currentLineIsBlank = false;
                }
            } // end if (client.available())
        } // end while (client.connected())
        delay(1);      // give the web browser time to receive the data
        client.stop(); // close the connection
    } // end if (client)
}

Flash usage: 24,100 bytes (74%) of 32,256
SRAM usage: 1,338 bytes (65%) of 2,048

Finding the Amount of Available SRAM at Runtime

The above sketch uses the freeRam() function from the Arduino Playground article on available memory to display the amount of available SRAM at runtime (while the sketch is running as opposed to at compile time).

The compiler shows the amount of free memory as 710 bytes available for local variables. The amount of free memory shown by the freeRam() function is 657 bytes at the time that the web page has been sent to the client. This available SRAM now takes into account the local variables that are in use and this is the reason that the runtime RAM available is less than the compile time RAM.

Comparing the Memory Usage Results

From the above memory usage results, it can be seen that some of the simpler sketches use less than 15% of available Flash and less than 15% of available SRAM. These are very simple sketches that only demonstrate a single principle.

The SD card read / write example starts approaching the half way mark of the available memory resources with the web client and  simple web server using less than half the memory resources.

As soon as more libraries are used together, memory usage goes over the 50% mark as is the case with the SD card web server at 70% Flash memory usage and  62% SRAM usage. This is still a relatively simple web server hosting a single static web page, but now including the SD card library.

When the LCD is added to the SD card web server, memory usage goes up to 74% for Flash and 65% for SRAM.

From the above, we can see that a simple sketch that uses multiple libraries can quickly use up available memory resources on an Arduino Uno. There are some techniques for making more efficient use of memory. One of the simplest ways to free up RAM is to use the F() macro to keep text in Flash memory so that it does not get copied to RAM at all. The F() macro can be applied to strings that are constant and aren’t modified at runtime.

Freeing Up SRAM

The same sketch above can be modified using the F() macro to put the text strings that are sent from the Arduino over the serial port, to the LCD and to the Ethernet client into Flash memory. For example, the string in the following line of code:

Serial.println("Initializing SD card...");

can be put into Flash memory like this:

Serial.println(F("Initializing SD card..."));

by putting the string including the opening and closing quotation marks into the brackets of the F() macro.

The above sketch will then look like this:

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
#include <LiquidCrystal.h>

// MAC address from Ethernet shield sticker under board
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 20); // IP address, may need to change depending on network
EthernetServer server(80);  // create a server at port 80

File webFile;
// have to change the pin numbers from the example defaults when using the Ethernet shield
LiquidCrystal lcd(3, 2, 8, 7, 6, 5);

int freeRam () {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

void setup()
{
    // set up the LCD's number of columns and rows:
    lcd.begin(16, 2);
    // Print a message to the LCD.
    lcd.print(F("Initializing..."));
  
    Ethernet.begin(mac, ip);  // initialize Ethernet device
    server.begin();           // start to listen for clients
    Serial.begin(9600);       // for debugging
    
    // initialize SD card
    Serial.println(F("Initializing SD card..."));
    if (!SD.begin(4)) {
        Serial.println(F("ERROR - SD card initialization failed!"));
        return;    // init failed
    }
    Serial.println(F("SUCCESS - SD card initialized."));
    // check for index.htm file
    if (!SD.exists("index.htm")) {
        Serial.println(F("ERROR - Can't find index.htm file!"));
        return;  // can't find index file
    }
    Serial.println(F("SUCCESS - Found index.htm file."));
    lcd.setCursor(0, 1);
    lcd.print(F("Done."));
}

void loop()
{
    EthernetClient client = server.available();  // try to get client

    if (client) {  // got client?
        boolean currentLineIsBlank = true;
        while (client.connected()) {
            if (client.available()) {   // client data available to read
                char c = client.read(); // read 1 byte (character) from client
                // last line of client request is blank and ends with \n
                // respond to client only after last line received
                if (c == '\n' && currentLineIsBlank) {
                    // send a standard http response header
                    client.println(F("HTTP/1.1 200 OK"));
                    client.println(F("Content-Type: text/html"));
                    client.println(F("Connection: close"));
                    client.println();
                    // send web page
                    webFile = SD.open("index.htm");        // open web page file
                    if (webFile) {
                        while(webFile.available()) {
                            client.write(webFile.read()); // send web page to client
                        }
                        webFile.close();
                    }
                    lcd.clear();
                    lcd.setCursor(0, 0);
                    lcd.print(F("Free RAM:"));
                    lcd.setCursor(0, 1);
                    lcd.print(freeRam());
                    break;
                }
                // every line of text received from the client ends with \r\n
                if (c == '\n') {
                    // last character on line of received text
                    // starting new line with next character read
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                    // a text character was received from client
                    currentLineIsBlank = false;
                }
            } // end if (client.available())
        } // end while (client.connected())
        delay(1);      // give the web browser time to receive the data
        client.stop(); // close the connection
    } // end if (client)
}

This changes the original sketch memory usage from:
Flash: 24,100 bytes (74%)
SRAM: 1,338 bytes (65%) — 710 bytes for local variables
Runtime SRAM available: 657 bytes

To:
Flash: 24,170 bytes (74%)
SRAM: 1,086 bytes (53%) — 962 bytes for local variables
Runtime SRAM available: 909 bytes

Which frees up 253 bytes of memory for local variables.

The image below shows the above sketch running and reporting back the number of free bytes of SRAM available from the freeRam() function.

Arduino SD Card Web Server with LCD

Arduino SD Card Web Server with LCD Displaying Free SRAM after using the F() Macro

From this comparison of sketches on the Arduino Uno, it can be seen that the main limiting factor on the Arduino Uno is the amount of available memory. A relatively short sketch that uses functions or objects from several libraries can quickly use up 70% of available memory. Any sketch that gets slightly more complex can start approaching the 100% memory usage mark.

When available RAM becomes limited, there is good chance that the sketch can start exhibiting unexpected behaviour and even crash as the unavailability of RAM results in variables being overwritten. One technique has been shown that can help to reduce the amount of RAM used by a sketch.