Using PROGMEM for Arrays in Arduino 

 October 19, 2023

By  Peter

Join Our Mailing List

We publish fresh content each week. Read how-to's on Arduino, ESP32, KiCad, Node-RED, drones and more. Listen to interviews. Learn about new tech with our comprehensive reviews. Get discount offers for our courses and books. Interact with our community.

One email per week, no spam, unsubscribe at any time.

In Arduino programming, PROGMEM is a keyword used to store data in the microcontroller’s program memory (flash memory) instead of RAM. This is particularly useful when dealing with large arrays of constant data like lookup tables, strings, or graphical assets. Here’s a step-by-step guide on how to use PROGMEM arrays in Arduino:

1. Include the <avr/pgmspace.h> Library:

Before you can use PROGMEM, you need to include the AVR library for program memory access, pgmspace. Add the following line at the beginning of your Arduino sketch:

#include <avr/pgmspace.h>

2. Declare Your Array with PROGMEM:

To declare an array that will be stored in flash memory, you use the const keyword along with PROGMEM. Here’s an example of declaring an array of integers:

const int myArray[] PROGMEM = {1, 2, 3, 4, 5};

3. Accessing Data from PROGMEM:

To access data stored in flash memory, you need to use special functions like pgm_read_byte(), pgm_read_word(), or pgm_read_dword() depending on the data type. For example, to read an integer from the myArray declared above, you would do the following:

int value = pgm_read_word(&myArray[2]); // Read the third element (index 2)

The pgm_read_word() function is used for 16-bit data types like int.

4. Using PROGMEM with Strings:

Using PROGMEM for strings is more common and a technique you may have already heard about. After all, a string is simply an array of chars. Here’s an example:

const char myString[] PROGMEM = "Hello, PROGMEM!";

To read a character from this string, you would use the pgm_read_byte function, like this:

char character = pgm_read_byte(&myString[7]); // Read the 8th character (index 7)

5. Be Mindful of Data Types:

Ensure you use the correct pgm_read_* function based on your reading data type. The functions are available for different data sizes (byte, word, word). You can find documentation for all functions defined in the pgmspace library here.

6. Write to PROGMEM (Rarely Needed):

Writing data to PROGMEM is possible but rare and requires a more complex procedure that involves using the avr/boot.h library and performing a bootloader update. It’s generally used for advanced purposes and not recommended for beginners.

Here is the entire sketch for this article:

#include <avr/pgmspace.h>

// Declare an array of integers stored in PROGMEM
const int myArray[] PROGMEM = {1, 2, 3, 4, 5};

// Declare a string stored in PROGMEM
const char myString[] PROGMEM = "Hello, PROGMEM!";

void setup() {
  delay(1000); // Give some time for serial monitor to open

void loop() {
  // Access and print an integer from the PROGMEM array
  int value = pgm_read_word(&myArray[2]); // Read the third element (index 2)
  Serial.print("Value from PROGMEM Array: ");

  // Access and print a character from the PROGMEM string
  char character = pgm_read_byte(&myString[7]); // Read the 8th character (index 7)
  Serial.print("Character from PROGMEM String: ");

  delay(1000); // Delay for readability in the serial monitor


But why use PROGMEM in the first place? Here are ten reasons.

  1. Conserving RAM: RAM is often limited in microcontrollers, and using PROGMEM allows you to store data in flash memory instead. This frees up valuable RAM for variables and dynamic data during program execution.
  2. Storing Large Constants: When your program requires large arrays of constant data, such as lookup tables, fonts, or graphical assets, storing them in PROGMEM prevents them from consuming too much RAM.
  3. String Storage: Storing strings in flash memory with PROGMEM is a common practice, especially when dealing with long strings or multiple strings, as it reduces RAM usage. This is crucial when working with low-memory microcontrollers.
  4. Optimizing for Embedded Systems: In embedded systems, memory optimization is critical. Using PROGMEM allows you to design more efficient programs that can run smoothly on resource-constrained devices.
  5. Energy Efficiency: Accessing data from flash memory can be more energy-efficient than accessing RAM, as it often involves lower power consumption.
  6. Reducing Fragmentation: Constantly creating and destroying variables in RAM can lead to memory fragmentation, which can cause issues in the long run. Storing constants in PROGMEM eliminates this concern.
  7. Speed: Flash memory access can be slightly slower than RAM access, but the difference is negligible for most applications. Using PROGMEM can be an acceptable trade-off for its benefits in terms of memory management.
  8. Persistent Storage: Data stored in flash memory persists across power cycles. This is useful for storing configuration settings, calibration data, or firmware updates.
  9. Optimizing Bootloader Space: In some cases, PROGMEM can be used to store bootloader code or data, allowing you to use more of the available flash memory for your application.
  10. Sharing Knowledge: When teaching electronics and programming, using PROGMEM is a valuable skill to share with students. It empowers them to create more memory-efficient and practical Arduino projects.

Using PROGMEM for arrays in Arduino is a valuable technique to conserve RAM and store large datasets efficiently in flash memory.



You may also like

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}

I’m excited to introduce you to the latest and greatest version of KiCad – version 8 (stable release). This article will overview the new features and capabilities added to this popular open-source electronic design automation

Read More
KiCad 8: The new and updated features, a full review

Learning anything worth learning from the ground up is hard. The road to proficiency is filled with roadblocks, distractions, and dead-ends. Everyone learns differently and for different reasons. Some of us learn to advance our

Read More
From struggling to thriving: Understanding the journey from Beginner to Proficient (in programming or anything else)