Program memory trouble

I have a long list of chars I want to store using PROGMEM, and I do not need them changed.

const char PROGMEM *riddle1[] = {"Those who","make it sell it","Those who buy","it never use it",
"The one who uses","it, never knows","What is it?"};

I get an error message saying " error: variable 'riddle1' must be const in order to be put into read-only section by means of 'attribute((progmem))'"

I thought the error might be that I accidentally change riddle1[] but I didn't
Any advice would be greatly appreciated.
Thanks,

  • D

Look at section "Arrays of strings" here :slight_smile:

I already did, but none of the examples were quite like the ones I used. I think the string of chars might be what is hindering the code.

No, you need to first declare the individual strings in the array and then the array itself, wich is exactely how it is done in the example linked to..

Something like this could work:

const char line1[] PROGMEM = "Those who";
const char line2[] PROGMEM = "make it sell it";
const char line3[] PROGMEM = "Those who buy";
const char line4[] PROGMEM = "it never use it";
const char line5[] PROGMEM = "The one who uses";
const char line6[] PROGMEM = "it, never knows";
const char line7[] PROGMEM = "What is it?";

const char* const riddle1[] PROGMEM = 
{
    line1, line2, line3, line4, line5, line6, line7
    
};

void setup() 
{
    Serial.begin(9600);
    while(!Serial);
    
    for( uint8_t i=0; i<7; i++ )
        Serial.println( (__FlashStringHelper*)pgm_read_word(riddle1 + i));

}//setup

void loop() 
{
}//loop

Do you want to put the strings into PROGMEM? Or the pointers to the strings? Or both?

IMO, the savings you get from storing the pointers themselves in PROGMEM is not worth the hassle.

const char line1[] PROGMEM = "Those who";
const char line2[] PROGMEM = "make it sell it";
const char line3[] PROGMEM = "Those who buy";
const char line4[] PROGMEM = "it never use it";
const char line5[] PROGMEM = "The one who uses";
const char line6[] PROGMEM = "it, never knows";
const char line7[] PROGMEM = "What is it?";

const __FlashStringHelper* const riddle1[] = {
  (__FlashStringHelper*)line1,
  (__FlashStringHelper*)line2,
  (__FlashStringHelper*)line3,
  (__FlashStringHelper*)line4,
  (__FlashStringHelper*)line5,
  (__FlashStringHelper*)line6,
  (__FlashStringHelper*)line7
};

void setup() {
  Serial.begin(115200);
  delay(1000);

  for ( uint8_t i = 0; i < 7; i++ ) {
    Serial.println(riddle1[i]);
  }
}

void loop() {}

OP said he had a "long list of chars" he wanted in PROGMEM. I took "long" to mean "long" and so there's value in storing the pointers there too.

If "long" actually means only 5 riddles or something, then the benefit of putting the pointers in PROGMEM diminishes.

Here’s another technique. I like it because you don’t need intermediate pointers and the compiler counts the number of strings for you, thus avoiding a “man with two watches” problem. The result is a single pointer stored in RAM. The downside is that the array can no longer be ragged but must be rectangular. This wastes some PROGMEM. Everything in engineering is a trade-off.

const char riddle2[][20] PROGMEM = {
  "Those who",
  "make it sell it",
  "Those who buy",
  "it never use it",
  "The one who uses",
  "it, never knows",
  "What is it?"
};

const uint8_t numStrings = sizeof(riddle2) / sizeof(riddle2[0]);

void setup() {
  Serial.begin(115200);
  delay(1000);

  for ( uint8_t i = 0; i < numStrings; i++ ) {
    Serial.println((__FlashStringHelper*)riddle2[i]);
  }
}

void loop() {}