Printing array. Garbage being printed

I’m having a odd problem I can’t figure out. I’ve got a multidimensional array
numRows and numCols is correctly printing out, 3 and 8

However when I try and loop through the array or getsstuck in a loop and prints out garbage.

const char* const dictionary[3][8] PROGMEM = {
  {"Account", "Date and Time", "Idle", "Language", "Main Menu", "Prescription", "Settings", "Sound"},
  {"Cuenta", "Fecha y Hora", "Espera", "Idioma", "Menu Principal", "Receta", "Configuracion", "Sonido"},
  {"Compte", "Date et heure", "Idle", "Langue", "Main Menu", "prescription", "Parametres", "Son"}
};


void setup() {

  Serial.begin(9600);
  Serial.println("Setup");

  int numRows = sizeof(dictionary) / sizeof(dictionary[0]);
  Serial.print("Rows: ");
  Serial.println(numRows);

  int numCols = sizeof(dictionary[0]) / sizeof(dictionary[0][0]);
  Serial.print("Cols: ");
  Serial.println(numCols);

  for (int i = 0; i < numCols; i++) {
    Serial.print("Entry: ");
    Serial.println(dictionary[0][i]);
  }



}

void loop() {
  // put your main code here, to run repeatedly:

}

If I replace

Serial.println(dictionary[0][i])

with

     Serial.println(dictionary[0][1]);

or

Serial.println(dictionary[0][2])

it prints the correct value, but not when using a variable.

Any ideas what I’m missing?

Using Arduino IDE 1.8.9 on Debian.
Building on the mega 2560.

I would expect
Account, Date and Time, Idle …etc to be printed.

The question is why it works at all.

edit: Perhaps because w/ constant indices the whole thing is hanlded at compile time.

You need to handle PROGMEM storage strings differently. I googled, so can you but

// your declaration

      const char* const dictionary[3][8] PROGMEM = {...


// worked fine in the loop with 

      char *x = (char *)pgm_read_word(&(dictionary[0][i]));
      Serial.print("         >"); Serial.println(x);

HTH

a7

const char* const dictionary[3][8] PROGMEM = {
  {"Account", "Date and Time", "Idle", "Language", "Main Menu", "Prescription", "Settings", "Sound"},
  {"Cuenta", "Fecha y Hora", "Espera", "Idioma", "Menu Principal", "Receta", "Configuracion", "Sonido"},
  {"Compte", "Date et heure", "Idle", "Langue", "Main Menu", "prescription", "Parametres", "Son"}
};

This declaration is putting pointers to the text elements in PROGMEM not the elements themselves. You can see that by checking the memory usage of the two declarations

const char* const dictionary[3][8] PROGMEM = {
const char* const dictionary[3][8] = {

Check these references. https://www.nongnu.org/avr-libc/user-manual/pgmspace.html

http://www.gammon.com.au/progmem

https://www.arduino.cc/reference/en/language/variables/utilities/progmem/

Thanks for the links. That pointed me in the right direction.

Learnt a new command today....pgm_read_word :)

So what would the declaration and access look like for this case of a 2D array of pointers?

Or what did you end up doing?

I assume at least the intent is to have the char strings in PROGMEM, can the table of pointers also be? And then how do we get at one at i, j?

a7

See http://forum.arduino.cc/index.php?topic=607462.0

UKHeliBob:
See http://forum.arduino.cc/index.php?topic=607462.0

Right, as mentioned in that post, getting a jagged array of c-strings into PROGMEM and accessing it via an array of pointers is rather inconvenient and difficult to maintain:

#include "Arduino.h"

const char dict00[] PROGMEM = "Account";
const char dict01[] PROGMEM = "Date and Time";
const char dict02[] PROGMEM = "Idle";
const char dict03[] PROGMEM = "Language";
const char dict04[] PROGMEM = "Main Menu";
const char dict05[] PROGMEM = "Prescription";
const char dict06[] PROGMEM = "Settings";
const char dict07[] PROGMEM = "Sound";

const char dict10[] PROGMEM = "Cuenta";
const char dict11[] PROGMEM = "Fecha y Hora";
const char dict12[] PROGMEM = "Espera";
const char dict13[] PROGMEM = "Idioma";
const char dict14[] PROGMEM = "Menu Principal";
const char dict15[] PROGMEM = "Receta";
const char dict16[] PROGMEM = "Configuracion";
const char dict17[] PROGMEM = "Sonido";

const char dict20[] PROGMEM = "Compte";
const char dict21[] PROGMEM = "Date et heure";
const char dict22[] PROGMEM = "Idle";
const char dict23[] PROGMEM = "Langue";
const char dict24[] PROGMEM = "Main Menu";
const char dict25[] PROGMEM = "prescription";
const char dict26[] PROGMEM = "Parametres";
const char dict27[] PROGMEM = "Son";

const uint8_t numCols = 8;
const char * const dictionary[][numCols] PROGMEM = {
  { dict00, dict01, dict02, dict03, dict04, dict05, dict06, dict07 },
  { dict10, dict11, dict12, dict13, dict14, dict15, dict16, dict17 },
  { dict20, dict21, dict22, dict23, dict24, dict25, dict26, dict27 }
};

const uint8_t numRows = sizeof(dictionary) / sizeof(dictionary[0]);

void setup() {
  Serial.begin(115200);
  delay(1000);
  for (uint8_t i = 0; i < numRows; i++) {
    for (uint8_t j = 0; j < numCols; j++) {
      Serial.print((__FlashStringHelper *) pgm_read_word(&(dictionary[i][j])));
      if (j < (numCols - 1)) {
        Serial.print(F(", "));
      }
    }
    Serial.println();
  }
}

void loop() {
}

If you’re willing to waste some flash space, using a rectangular array makes things simpler and easier to maintain:

#include "Arduino.h"

typedef const char ProgmemString[16];

const uint8_t numCols = 8;

ProgmemString dictionary[][numCols] PROGMEM = {
  { "Account", "Date and Time", "Idle", "Language", "Main Menu", "Prescription", "Settings", "Sound" },
  { "Cuenta", "Fecha y Hora", "Espera", "Idioma", "Menu Principal", "Receta", "Configuracion", "Sonido" },
  { "Compte", "Date et heure", "Idle", "Langue", "Main Menu", "prescription", "Parametres", "Son" }
};

const uint8_t numRows = sizeof(dictionary) / sizeof(dictionary[0]);

void setup() {
  Serial.begin(115200);
  delay(1000);
  for (uint8_t i = 0; i < numRows; i++) {
    for (uint8_t j = 0; j < numCols; j++) {
      Serial.print((__FlashStringHelper *) (&(dictionary[i][j])));
      if (j < (numCols - 1)) {
        Serial.print(F(", "));
      }
    }
    Serial.println();
  }
}

void loop() {
}

I think that’s a pretty good tradeoff in most cases.

Try changing your baudrate on serialmonitor that usual works.