Arduino

Buy | Download | Getting Started | Learning | Reference | Hardware | FAQ

Blog » | Forum » | Playground »

Reference Language (extended) | Libraries | Comparison | Board

## PROGMEM

Store data in flash (program) memory instead of SRAM. There's a description of the various types of memory available on an Arduino board.

The PROGMEM keyword is a variable modifier, it should be used only with the datatypes defined in pgmspace.h. It tells the compiler "put this information into flash memory", instead of into SRAM, where it would normally go.

PROGMEM is part of the pgmspace.h library. So you first need to include the library at the top your sketch, like this:

    #include <avr/pgmspace.h>

#### Syntax

    dataType variableName[] PROGMEM = {dataInt0, dataInt1, dataInt3...};

- program memory dataType - any program memory variable type (see below)
- variableName - the name for your array of data

Note that because PROGMEM is a variable modifier, there is no hard and fast rule about where it should go, so the Arduino compiler accepts all of the definitions below, which are also synonymous.

    dataType variableName[] PROGMEM = {};
    dataType PROGMEM variableName[] = {};
    PROGMEM dataType variableName[] = {};

Common programming styles favor one of the first two however.

While PROGMEM could be used on a single variable, it is really only worth the fuss if you have a larger block of data that needs to be stored, which is usually easiest in an array, (or another C data structure beyond our present discussion).

Using PROGMEM is also a two-step procedure. After getting the data into Flash memory, it requires special methods (functions), also defined in the pgmspace.h library, to read the data from program memory back into SRAM, so we can do something useful with it.

As mentioned above, it is important to use the datatypes outlined in pgmspace.h. Some cryptic bugs are generated by using ordinary datatypes for program memory calls. Below is a list of variable types to use. Floating point numbers in program memory do not appear to be supported.

     prog_char      - a signed char (1 byte) -127 to 128
     prog_uchar     - an unsigned char (1 byte) 0 to 255
     prog_int16_t   - a signed int (2 bytes) -32,767 to 32,768
     prog_uint16_t  - an unsigned int (2 bytes) 0 to 65,535
     prog_int32_t   - a signed long (4 bytes) -2,147,483,648 to * 2,147,483,647.
     prog_uint32_t  - an unsigned long (4 bytes) 0 to 4,294,967,295

#### Example

The following code fragments illustrate how to read and write unsigned chars (bytes) and ints (2 bytes) to PROGMEM.

    #include <avr/pgmspace.h>

    // save some unsigned ints
    PROGMEM  prog_uint16_t charSet[]  = { 65000, 32796, 16843, 10, 11234};

    // save some chars
    prog_uchar signMessage[] PROGMEM  = {"I AM PREDATOR,  UNSEEN COMBATANT. CREATED BY THE UNITED STATES DEPART"};

    unsigned int displayInt;
    int k;    // counter variable
    char myChar;

    // read back a 2-byte int
     displayInt = pgm_read_word_near(charSet + k)

    // read back a char
    myChar =  pgm_read_byte_near(signMessage + k);

Arrays of strings

It is often convenient when working with large amounts of text, such as a project with an LCD display, to setup an array of strings. Because strings themselves are arrays, this is in actually an example of a two-dimensional array.

These tend to be large structures so putting them into program memory is often desirable. The code below illustrates the idea.

    /*
     PROGMEM string demo
     How to store a table of strings in program memory (flash),
     and retrieve them.

     Information summarized from:
     http://www.nongnu.org/avr-libc/user-manual/pgmspace.html

     Setting up a table (array) of strings in program memory is slightly complicated, but
     here is a good template to follow.

     Setting up the strings is a two-step process. First define the strings.

    */

    #include <avr/pgmspace.h>
    prog_char string_0[] PROGMEM = "String 0";   // "String 0" etc are strings to store - change to suit.
    prog_char string_1[] PROGMEM = "String 1";
    prog_char string_2[] PROGMEM = "String 2";
    prog_char string_3[] PROGMEM = "String 3";
    prog_char string_4[] PROGMEM = "String 4";
    prog_char string_5[] PROGMEM = "String 5";

    // Then set up a table to refer to your strings.

    PGM_P PROGMEM string_table[] =	   // change "string_table" name to suit
    {
      string_0,
      string_1,
      string_2,
      string_3,
      string_4,
      string_5 };

    char buffer[30];    // make sure this is large enough for the largest string it must hold

    void setup()
    {
      Serial.begin(9600);
    }

    void loop()
    {
      /* Using the string table in program memory requires the use of special functions to retrieve the data.
         The strcpy_P function copies a string from program space to a string in RAM ("buffer").
         Make sure your receiving string in RAM  is large enough to hold whatever
         you are retrieving from program space. */

      for (int i = 0; i < 6; i++)
      {
        strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // Necessary casts and dereferencing, just copy.
        Serial.println( buffer );
        delay( 500 );
      }
    }

#### See also

- Types of memory available on an Arduino board
- array
- string

Reference Home

Corrections, suggestions, and new documentation should be posted to the Forum.

The text of the Arduino reference is licensed under a Creative Commons Attribution-ShareAlike 3.0 License. Code samples in the reference are released into the public domain.

Edit Page | Page History | Printable View | All Recent Site Changes