0

I am unable to access elements of a 2D PROGMEM array from inside a loop. Please see the following example:

const byte a1[] PROGMEM = {'a', 'b', 'c', 'd'};
const byte a2[] PROGMEM = {'e', 'f', 'g', 'h', 'i'};
const byte a3[] PROGMEM = {'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q'};
const byte a4[] PROGMEM = {'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};

const byte * const arr[] PROGMEM = {a1, a2, a3, a4};

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

  Serial.println(pgm_read_byte(&(arr[0][0])));
  Serial.println(pgm_read_byte(&(arr[1][0])));
  Serial.println(pgm_read_byte(&(arr[2][0])));
  Serial.println(pgm_read_byte(&(arr[3][0])));
  for (int i = 0; i < 4; i++) {
    Serial.print(i);
    Serial.print(":");
    Serial.println(pgm_read_byte(&(arr[i][0])));
  }
  int j = 0;
  Serial.println(pgm_read_byte(&(arr[j][0])));
  j = 1;
  Serial.println(pgm_read_byte(&(arr[j][0])));
  j = 2;
  Serial.println(pgm_read_byte(&(arr[j][0])));
  j = 3;
  Serial.println(pgm_read_byte(&(arr[j][0])));
}

void loop() {

}

The output is:

97
101
106
114
0:12
1:174
2:12
3:148
97
101
106
114

I verified and re-verified the syntax so many times. could not find anyone facing similar issue. I am at my wits end why it would not print correct values inside the loop. Any ideas?

EDIT: expected output is:

97
101
106
114
0:97
1:101
2:106
3:114
97
101
106
114
6
  • 1
    the constant uses like arr[1][0] are replaced at compile time with the items value. they are not read from the array in runtime. even with j with constant value the compiler evaluates it at compile time and replaces with the value
    – Juraj
    Commented Feb 22, 2019 at 20:18
  • I think you are right.. is there any way I can achieve accessing the elements from inside the loop? Commented Feb 22, 2019 at 20:21
  • arduino.cc/reference/en/language/variables/utilities/progmem
    – Juraj
    Commented Feb 22, 2019 at 20:22
  • I had already gone through it.. after you put it here, i took some ideas and made it work.. giving below as answer.. thanks.. Commented Feb 22, 2019 at 20:30
  • 1
    You can make it easier. For example when each array is a zero terminated string, or when all the arrays have the same fixed size, or one long string with markers. A two-dimensional array with a different number of elements without knowing how many elements are valid, that seems so very weird.
    – Jot
    Commented Feb 22, 2019 at 21:17

2 Answers 2

0
const byte a1[] PROGMEM = {'a', 'b', 'c', 'd'};
const byte a2[] PROGMEM = {'e', 'f', 'g', 'h', 'i'};
const byte a3[] PROGMEM = {'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q'};
const byte a4[] PROGMEM = {'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};

const byte * const arr[] PROGMEM = {a1, a2, a3, a4};

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

  for (int i = 0; i < 4; i++) {
    Serial.print(i);
    Serial.print(':');
    for (int j = 0; j < 4; j++) {
      Serial.print((char) pgm_read_byte_near(pgm_read_word(arr + i) + j));
      Serial.print(',');
    }
    Serial.println();
  }
}

void loop() {

}

output

0:a,b,c,d,
1:e,f,g,h,
2:j,k,l,m,
3:r,s,t,u,

at runtime the size of the arrays is unknown, so I print the first 4 items

1

After going through link given by Juraj above again, I could make it work as follows:

const byte a1[] PROGMEM = {'a', 'b', 'c', 'd'};
const byte a2[] PROGMEM = {'e', 'f', 'g', 'h', 'i'};
const byte a3[] PROGMEM = {'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q'};
const byte a4[] PROGMEM = {'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};

const byte * const arr[] PROGMEM = {a1, a2, a3, a4};

void setup() {
  Serial.begin(74880);

  Serial.println(pgm_read_byte(&(arr[0][0])));
  Serial.println(pgm_read_byte(&(arr[1][0])));
  Serial.println(pgm_read_byte(&(arr[2][0])));
  Serial.println(pgm_read_byte(&(arr[3][0])));
  for (int i = 0; i < 4; i++) {
    Serial.print(i);
    Serial.print(":");
    Serial.println(pgm_read_byte_near(pgm_read_word(&(arr[i])) + 0));
  }
  int j = 0;
  Serial.println(pgm_read_byte(&(arr[j][0])));
  j = 1;
  Serial.println(pgm_read_byte(&(arr[j][0])));
  j = 2;
  Serial.println(pgm_read_byte(&(arr[j][0])));
  j = 3;
  Serial.println(pgm_read_byte(&(arr[j][0])));
}

void loop() {

}

Now it shows the expected output and access from inside loop using variable index is possible. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.