- Trending Categories
Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
Physics
Chemistry
Biology
Mathematics
English
Economics
Psychology
Social Studies
Fashion Studies
Legal Studies
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
How to use PROGMEM in Arduino to store large immutable data?
PROGMEM is the keyword you use when you wish to store data in the program memory (flash) instead of the SRAM. While you can use PROGMEM for a single variable, it won't make much sense to do so. After all, the SRAM would have more than enough space to accommodate your single variable, and it will be faster to access the variable stored in SRAM.
PROGMEM is primarily used for large chunks of data (an array mostly), which can overwhelm the SRAM (which is generally much smaller in size than the flash memory, but faster to access). The implication of storing something in PROGMEM is that it cannot be modified dynamically at runtime. Therefore, people generally use PROGMEM to store large immutable text or data.
If you are using Arduino IDE version below 1.0 (why?), then you need to include
#include <avr/pgmspace.h>
at the top of your code to use the PROGMEM keyword. For versions of Arduino >= 1.0, you can use the PROGMEM keyword directly without any includes required.
Note that PROGMEM works only with global variables or the ones defined with a static keyword.
Syntax
The syntax is as follows −
const dataType arrayName[] PROGMEM = {data0, data1, data3…};
Any variable type is allowed for datatype and arrayName is the name of your array.
In order to access the data stored in the flash memory using PROGMEM, you use specialized functions −
strlen_P(arrayName) − This function returns the length of the array arrayName.
pgm_read_byte_near(address) − This function returns the value of one byte located at address.
pgm_read_word_near(address) − This function returns the value of one word (2 bytes on most microcontrollers) with location starting from address.
The usage of these functions will be clear in the example below. These aren't the only functions to be used with PROGMEM. There are several others, which you can find here.
Example
Let's begin with the example. We will use the example given in Arduino's documentation.
We will look at the first example. As you can see, there are two arrays defined in PROGMEM, one is an array of 16-bit integers (16-bit = 1 word on Arduino Uno), while the second is an array of characters (each character is 8-bit or 1 byte long)
// save some unsigned ints const PROGMEM uint16_t charSet[] = { 65000, 32796, 16843, 10, 11234}; // save some chars const char signMessage[] PROGMEM = {"I AM PREDATOR, UNSEEN COMBATANT. CREATED BY THE UNITED STATES DEPART"};
Later, there are two global variables defined, which will be used later.
unsigned int displayInt; char myChar;
Within setup, we initialize Serial. Later, we read one word at a time, to print the integers of the charset array. Notice how we use charSet + k for the address we want to read. You may remember that the name of an array is also the pointer to its first element. That same property is being used here.
void setup() { Serial.begin(9600); while (!Serial); // wait for serial port to connect. Needed for native USB // put your setup code here, to run once: // read back a 2-byte int for (byte k = 0; k < 5; k++) { displayInt = pgm_read_word_near(charSet + k); Serial.println(displayInt); } Serial.println();
Later, we read one byte each from the signMessage array and print it to the Serial Monitor. Please note that we are using the strlen_P function to get the length of the array, to determine the termination condition of the for loop.
// read back a char for (byte k = 0; k < strlen_P(signMessage); k++) { myChar = pgm_read_byte_near(signMessage + k); Serial.print(myChar); } Serial.println(); }
Nothing happens inside the loop.