Questions tagged [progmem]

PROGMEM is a keyword used when declaring a variable that keeps the data in flash instead of copying it into SRAM. It is part of the pgmspace.h library. Use this tag for discussions about using this attribute.

Memory types on an Arduino

RAM is precious on a microcontroller, PROGMEM (program memory) not quite as much so. On the Arduino Uno (using an Atmega328P) you have:

  • 1 KB of EEPROM
  • 2 KB of RAM
  • 32 KB of PROGMEM (Flash Memory - where your program goes)

Clearly, there is a lot more program memory than RAM.


Constants are normally copied from PROGMEM into RAM

Constants in your program are initially stored in PROGMEM (where else could they be stored when the power is off?) but copied into RAM by compiler-generated initialization code at the very start of executing your sketch (program).

For example:

Serial.println ("Hello, world!");

The constant string "Hello, world!" is initially in PROGMEM, but copied into RAM at startup. This means that room for it has to be allowed for in RAM as well as in the Flash memory.

This uses up valuable RAM for what is really just a copy of something that will never change.

Another example:

const int NUMBER_OF_ELEMENTS = 10;
const float table[NUMBER_OF_ELEMENTS] = 
      { 1.0, 34.234, 324.234, 23.1, 52.0, 3.6, 5.6, 42.42, 1908, 23.456 } ;

Although this table of floating-point values won't change, it is also copied into RAM. If you have a large table, you will soon run out of RAM.


The PROGMEM attribute

You can prevent this copying into RAM by adding PROGMEM to a data declaration, like this:

const int NUMBER_OF_ELEMENTS = 10;
const float table[NUMBER_OF_ELEMENTS] PROGMEM = 
      { 1.0, 34.234, 324.234, 23.1, 52.0, 3.6, 5.6, 42.42, 1908, 23.456 } ;

Accessing PROGMEM constants

Unfortunately the compiler (on the AVR Arduinos anyway) expects all data to be in RAM and does not allow for accessing data directly from PROGMEM.

You can make a small library PROGMEM_readAnything.h:

#include <Arduino.h>  // for type definitions

template <typename T> void PROGMEM_readAnything (const T * sce, T& dest)
  {
  memcpy_P (&dest, sce, sizeof (T));
  }

template <typename T> T PROGMEM_getAnything (const T * sce)
  {
  static T temp;
  memcpy_P (&temp, sce, sizeof (T));
  return temp;
  }

Copy the above into a text file, save it as PROGMEM_readAnything.h, and place that into a folder called PROGMEM_readAnything, and put that folder inside your Arduino libraries folder which itself is inside your sketchbook folder. Like this:

(sketchbook location)/libraries/PROGMEM_readAnything/PROGMEM_readAnything.h

Now you can access a PROGMEM constant like this:

float thisOne;
PROGMEM_readAnything (&table[3], thisOne);

Or:

float thisOne = PROGMEM_getAnything (&table[3]);

The F() macro

For simple string constants, you can use the F() macro to easily keep strings in PROGMEM, like this:

Serial.println (F("Hello, world!"));
66 questions
13
votes
1 answer

Can I write to Flash Memory using PROGMEM?

On the documentation of Arduino, I quote: http://playground.arduino.cc/Learning/Memory Note: Flash (PROGMEM) memory can only be populated at program burn time. You can’t change > the values in the flash after the program has started running. And…
zzarbi
  • 233
  • 1
  • 2
  • 5
12
votes
2 answers

Why can I not use pointers instead of array with PROGMEM?

I'm currently changing some libraries to use flash instead of RAM for string storage so that I do not run out of SRAM on a project. Some strings in the library are declared in this manner: const char *testStringA = "ABC"; This is different to how I…
Cybergibbons
  • 5,420
  • 7
  • 34
  • 51
9
votes
3 answers

PROGMEM: do I have to copy data from flash to RAM for reading?

I have got some difficulties understanding the memory management. Arduino documentation says, it is possible to keep constants like strings or whatever I don't want to change during runtime in program memory. I think of it as embedded somewhere in…
Ariser
  • 577
  • 1
  • 8
  • 26
6
votes
1 answer

What are the benfits of global variables over static class members?

On an embedded system we use global variables often to keep dynamic memory consumption on heap and stack low. But global variables are also considered bad programming practice if they aren't used in a global sense, i.e. they are used only inside one…
Ariser
  • 577
  • 1
  • 8
  • 26
5
votes
4 answers

How can a function/method determine if a const array passed in is PROGMEM (flash) or not (RAM)?

Is it possible for a function/method to know if a constant array that has been passed in is in flash or RAM? If I have a method or function that receives a constant array that is in RAM, the array is declared like this: const uint8_t MY_ARRAY[] = {…
Casey
  • 151
  • 6
5
votes
2 answers

Using PROGMEM to store array of structs

I am hitting the limits of my arduino's SRAM and found that SRAM usage can be reduced by storing static stuff in flash memory instead of SRAM. My project can (optionally) be built with an included SimulatorClass. I use this to 'playback' data at…
Alex
  • 181
  • 2
  • 3
  • 9
4
votes
1 answer

Flash String Helper object as variable

So I have a Bunch of commonly used char arrays to build commands in my library. So to preserve memory, I have them put into flash, via PROGMEM ext, typedef const char PROGMEM ProgChar; ProgChar AT[] = "AT"; ProgChar AT_RST[] = "RST"; Then in my…
3
votes
2 answers

PROGMEM : pgm_read_float_near() equivalent for double? (Arduino Due)

I'm using an Arduino Due where double have a size of 8 bytes. In my software, I use double table const stored in prog memory, I was using an UNO before and used pgm_read_float_near() to retrieve these values. What function should I use?
snoob dogg
  • 239
  • 2
  • 5
  • 15
3
votes
2 answers

How is a 41KB char array filling up 256KB of program memory?

I have an array of 41,400 elements of type char, which I am trying to put in program memory on a Mega2560. It should have 256KB of flash memory, but when I try to compile my sketch, it says the size of the array is too large. Each char is one byte,…
yigiped
  • 33
  • 1
  • 4
3
votes
2 answers

How to correctly pack an unsigned long from 3 unsigned chars?

I would like to use 652 unsigned long values on an Arduino Uno, but it doesn't look like there's enough memory. I thought about the splitting unsigned long values to 3 unsigned chars to store in PROGMEM which I can letter recall and join as unsigned…
George Profenza
  • 311
  • 1
  • 6
  • 17
2
votes
2 answers

PlatformIO and const PROGMEM

I'm using the DuinoWitchery LCD library (https://github.com/duinoWitchery/hd44780) in a PlatformIO Arduino project with CLion. The following code works if I stick it in main.cpp: // near top of class... const PROGMEM uint8_t decimalDigit[10][8] = { …
Bitbang3r
  • 561
  • 1
  • 3
  • 14
2
votes
2 answers

PROGMEM char* mangled text

I wrote a program using PROGMEM for massive string arrays. One of the arrays worked, but when I added the second one, the serial output only puts out "th". Pastebin Code: http://pastebin.com/9U7QZQKn
Josh
  • 45
  • 1
  • 3
2
votes
0 answers

Strange things happening with Arduino PROGMEM

I am currently working on a display library. The font should be stored in PROGMEM. The code looks something like this: unsigned int i = 0; Serial.println(pgm_read_byte(&font[1]),HEX); unsigned char width = pgm_read_byte(&font[0]); unsigned char…
w7sbc
  • 21
  • 1
2
votes
1 answer

PROGMEM doesn't cause Sketch size to change

I'm trying to pinpoint some strange behaviour involving the use of PROGMEM and the size of a Sketch. I've written a library that contains a number of functions, in addition to several large global byte arrays and 32-bit uint arrays. These arrays are…
2
votes
1 answer

Problem when using PROGMEM on array holding notes for speaker on Arduino

The problem I've been having is a little weird. I'm trying to set up audio for my Arduino project and have been playing around with the example included in the IDE. The problem is whenever I try to make the array of notes go into PROGMEM, it makes…
1
2 3 4 5