PROGMEM e strcmp_P (risolto)

Ciao a tutti,
pensando a come aiutare un utente del forum, ho provato a buttare giù del codice per sfruttare la PROGMEM, una array e… strcmp_P

Senza array, okay ma con array non riesco a capire cosa non va:

#include <avr/pgmspace.h>
const char string_0[] PROGMEM = "GET /?out=AllTemp";
const char string_1[] PROGMEM = "GET /?out=all";
const char string_2[] PROGMEM = "GET /?out=0&value=";
const char string_3[] PROGMEM = "GET /?out=0&status=1";
const char string_4[] PROGMEM = "GET /?out=22&status=1";
const char string_5[] PROGMEM = "GET /?out=23&status=1";
const char* const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5};
char buf[30],buffer[30];
void setup()
{ delay(1000);
  Serial.begin(9600);
  Serial.println("go..");
}
void loop()
{ String readString = "GET /?out=all";          // prova
  readString.toCharArray(buf, 30);
  Serial.print("buf = "); Serial.println(buf);
  for (int i = 0; i < 6; i++)
  { Serial.print("i="); Serial.print(i);
    // A. copia da PROGMEM a buffer, okay strcmp
    strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // Necessary casts and dereferencing, just copy.
    Serial.print(" = "); Serial.println(buffer);
    if (strcmp(buf, buffer) == 0) Serial.println("found A");

    // B. singola stringa okay
    if ( strcmp_P(buf, string_1) == 0 ) 
    { Serial.print("found B"); 
    }

   // C. array in PROGMEM
   if ( strcmp_P(buf, (char*)&string_table[i])) == 0 )  
    { Serial.print("foundC="); Serial.println(i);
    }
   delay( 500 );
  }
}

Se copio da PROGMEM in un buffer (A) okay
Se strcmp_P singola stringa (B) okay
Se provo strcmp_P con array (C) non funziona. Sbaglio qualcosa ma non capisco cosa

Grazie, igor

Che pirla, ovviamente stessa sintassi della strcpy_P !!

if ( strcmp_P(buf, (char*)pgm_read_word(&(string_table[i])) ) == 0 )  // trovato

Meglio pgm_read_ptr() però, ti dà un minimo di portabilità.

Provato, funziona:

if ( strcmp_P(p_cmd, pgm_read_ptr(&string_table[i])) == 0 )

grazie @sukko

Certo, DEVE funzionare, è la cosa giusta da fare, visto che stai leggendo effettivamente un puntatore. È pgm_read_word() che invece funziona "per caso", solo perché un puntatore sul 328 occupa 2 byte (= una word).

E ovviamente nel 99% degli esempi in giro si usa pgm_read_word() :-X.

ciao,
sul modello suggerito, sto cercando di implementare una look-up table di N elementi, con un vettore di struct cosi' definito

struct myElemento {
 char regName[8]; 
 byte type;       
};

che inizializzo cosi' con dei #define

#define EL1   0
#define EL2   1
#define EL3   2
...

#define _ELEM1_ {"casa",1}
#define _ELEM2_ {"auto",1}
#define _ELEM3_ {"cantina",2}
...

const modbusRegister TFPRmodbusRegister[] PROGMEM  =  {  
 _ELEM1_,_ELEM2_,_ELEM3_  ....                 etc... etc... 
}

myElemento  miaStrutturaDati;
char tmpCharBuf[50];
int  tmpIntBuf;

per poi leggere con una funzione

void readStruct(uint16_t a){   
 strcpy_P(tmpCharBuf, (char*)pgm_read_ptr(&(miaStrutturaDati[a].regName)));   // non funziona nemmeno se pgm_read_word
 tmpIntBuf= pgm_read_word(&miaStrutturaDati[a].type);
 
 Serial.print(tmpCharBuf);Serial.print(" ");Serial.println(miaStrutturaDati(a));

 }

nel loop la invoco cosi'

  readStruct(EL1);

Mentre la lettura di 'type' funzione, quella del testo/stringa non funziona, anzi il programma si inizializza ogni volta (come se facessi un reset, immagino qualche violazione pesante della memoria che provoca il crash).
Sono sicuro che il problema sta nell'inizializzazione del vettore di struct e nelle varie conversioni dei char in const char e const char*, ma non riesco a venirne a capo.

Qualche suggerimento?

grazie 1000