Access array in PROGMEM

This is just test code, just to learn. I have not used Arduino in a long time.

I loaded an array in PROGMEM to save on scratch-pad RAM.

Now, I want to see if I can walk through the array and read some elements.

In my code you can see if I hard code the array index pointers then I can access the data, other wise I can't. What am I missing?

Thank you in advance.

`

const char  atest2   [20][ 5]  PROGMEM  =   
     {
     {'0','Z','z'}    ,
     {'1','B','b'}    ,
     {'2','C','c'}    ,
     {'3','D','d'}    ,
     {'4','E','e'}    ,
     {'5','F','f'}    ,
     {'6','G','g'}    ,
     {'7','H','h'}    ,
     {'8','I','i'}    ,
     {'9','J','j'}    ,
     }  ;



byte nCounter  = 1 ;


char cTemp2 =  '.' ;




void setup() 
   {
   Serial.begin( 56700 ) ;
   }



void loop() 
   {


   nCounter ++  ;  
   

 
   //  this returns "2Cc"  correctly
   Serial.print(   atest2  [2][0]) ;
   Serial.print(   atest2  [2][1]) ;
   Serial.println( atest2  [2][2]) ;


    
   //this does not work correctly
   Serial.print(   atest2  [nCounter][0]) ;
   Serial.print(   atest2  [nCounter][1]) ;
   Serial.println( atest2  [nCounter][2]) ;

      
   delay(1000) ;

   if ( nCounter > 9 )
      {
      nCounter = 0 ;  
      }


   }`

Look closely at the examples on the Arduino reference page (a very useful resource).

1 Like

that's because compiler optimisation. the data in the array is constant and you have constant indexes, so the compiler just replace the array access by the value.

when you use a variable, the compiler can't optimize and because you did not use the right functions to read bytes, words etc from flash memory, it does not work

double check the doc pointed by @jremington

1 Like

Yes:

// read back a char
  for (byte k = 0; k < strlen_P(signMessage); k++) {
    myChar = pgm_read_byte_near(signMessage + k);
    Serial.print(myChar);
  }

works great for a single long chain of chars. I have an array of char arrays. Thats where I am getting held up. Its a two dimensional array that have.

I think I have it worked out: nesting the indexes was all it took. Thank you all!

this should work

const char testArray[][3] PROGMEM = {
  {'0', 'Z', 'z'},
  {'1', 'B', 'b'},
  {'2', 'C', 'c'},
  {'3', 'D', 'd'},
  {'4', 'E', 'e'},
  {'5', 'F', 'f'},
  {'6', 'G', 'g'},
  {'7', 'H', 'h'},
  {'8', 'I', 'i'},
  {'9', 'J', 'j'},
} ;

const byte nbRows = sizeof testArray / sizeof * testArray;

void setup() {
  Serial.begin(115200) ;
  Serial.print("nb rows = "); Serial.println(nbRows);

  for (byte i = 0; i < nbRows; i++) {
    for (byte j = 0; j < 3; j++) {
      char data = pgm_read_byte(&(testArray[i][j]));
      Serial.print(data);
      Serial.write(' ');
    }
    Serial.println();
  }
}

void loop() {}
1 Like

Yes, I think that is why the "address of" operator(&) is required here
char data = pgm_read_byte(&(testArray[i][j]));

Or with your original program
Serial.print((char)pgm_read_byte(&atest2[nCounter][0])) ;

yes or really go do the maths to find the exact flash address

      char data = pgm_read_byte((uint16_t) testArray + 3 * i + j);

Or just use the "old fashioned way" of one dimensional arrays :wink:

const byte Rows = 10;
const byte Cols = 3;
const char testArray[Rows * Cols] PROGMEM = {
  '0', 'Z', 'z',
  '1', 'B', 'b',
  '2', 'C', 'c',
  '3', 'D', 'd',
  '4', 'E', 'e',
  '5', 'F', 'f',
  '6', 'G', 'g',
  '7', 'H', 'h',
  '8', 'I', 'i',
  '9', 'J', 'j',
} ;


void setup() {
  Serial.begin(115200) ;
  for (byte r = 0; r < Rows; r++) {
    for (byte c = 0; c < Cols; c++) {
      char data = pgm_read_byte(testArray + c + r * Cols);
      Serial.print(data);
      Serial.write(' ');
    }
    Serial.println();
  }
}

void loop() {}

Though it works, I must admit I like your solution more :wink:

yes and you can let the compiler compute the size of the array, as long as you fix one dimension for the math later on

const byte Cols = 3;
const char testArray[] PROGMEM = {
  '0', 'Z', 'z',
  '1', 'B', 'b',
  '2', 'C', 'c',
  '3', 'D', 'd',
  '4', 'E', 'e',
  '5', 'F', 'f',
  '6', 'G', 'g',
  '7', 'H', 'h',
  '8', 'I', 'i',
  '9', 'J', 'j',
} ;
const byte Rows = sizeof testArray / Cols ;

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.