構造体には文字列データではなくポインターのみが含まれているため、文字列は引き続き RAM に格納されます。
また、データにアクセスするときに PROGMEM から読み取っていません。特定の状況で機能しているという事実は単なる運ですが、それでも正しくありません。
すべてのデータを PROGMEM に配置するには、構造体内に領域を割り当てる必要があります。最大の文字列は 11 文字 + null なので、長さを 12 にすることができます。
struct commandCode {
int code;
const char name[12];
};
const commandCode commands[] PROGMEM = {
{ CMD_DEMO, "DEMO" } ,
{ CMD_STOP, "STOP"} ,
{ CMD_FORWARD, "FORWARD"},
{ CMD_BACKWARD, "BACKWARD"},
{ CMD_TURN_LEFT, "TURN LEFT"},
{ CMD_TURN_RIGHT, "TURN RIGHT"},
{ CMD_WAIT, "WAIT"},
{ CMD_WAIT_DONE, "WAIT DONE"}
}
各構造体の内部は PROGMEM にあるため、特別な関数を使用してそれらを読み取る必要があります。それらを直接読み取ることはできません。
これはまた、あなたが行ったようにアイテムをコピーできないことを意味します:
CommandCodes::commandCode cmd = commands[i];
しかし、参照を使用することはできます。
const commandCode &cmd = commands[i];
ただし、上で述べたように、参照される構造体の要素には適切にアクセスする必要があります。
整数の場合は、 を使用する必要がありますpgm_read_word
。F()
文字列については、Serial クラスがフラッシュ文字列を処理するときに (マクロを使用する場合と同様に)、それを印刷するようにトリックすることができます。これは、ポインタを にキャストすることで実行できますconst __FlashStringHelper*
。
これは、各パーツに適切にアクセスする方法を示す作業スケッチです。それをテストして、私がやったことを試してみてください。いくつか質問があると思いますので、この回答のコメントに追加してください。回答を更新します。
struct commandCode {
int code;
const char name[12];
};
enum COMMANDS{
CMD_DEMO,
CMD_STOP,
CMD_FORWARD,
CMD_BACKWARD,
CMD_TURN_LEFT,
CMD_TURN_RIGHT,
CMD_WAIT,
CMD_WAIT_DONE,
};
const commandCode commands[] PROGMEM = {
{ CMD_DEMO, "DEMO" } ,
{ CMD_STOP, "STOP"} ,
{ CMD_FORWARD, "FORWARD"},
{ CMD_BACKWARD, "BACKWARD"},
{ CMD_TURN_LEFT, "TURN LEFT"},
{ CMD_TURN_RIGHT, "TURN RIGHT"},
{ CMD_WAIT, "WAIT"},
{ CMD_WAIT_DONE, "WAIT DONE"}
};
#define FIRST_COMMAND 0
#define LAST_COMMAND sizeof(commands) / sizeof(*commands)
#define FSH (const __FlashStringHelper*) //A helper to allow printing the PROGMEM strings.
void show() {
for (int i = FIRST_COMMAND; i < LAST_COMMAND; i++) {
const commandCode &cmd = commands[i];
showCommand(cmd);
}
}
void showCommand(const commandCode &cmd) {
if ( pgm_read_word( &cmd.code ) > FIRST_COMMAND) {
Serial.print(F("["));
Serial.print( pgm_read_word( &cmd.code ) );
Serial.print(F("] "));
Serial.println( FSH( cmd.name ) );
}
}
const char* name(int code) {
for (int i = FIRST_COMMAND; i < LAST_COMMAND; i++) {
const commandCode &cmd = commands[i];
if (pgm_read_word(&cmd.code) == code) {
return cmd.name; //As cmd.name resolves to a pointer it can be passed back as is.
//However to use the 'pointed to data' it will have to be accessed properly.
}
}
return NULL;
}
void setup() {
Serial.begin(9600);
Serial.println("Show test");
show();
Serial.println("Name test");
for (int i = FIRST_COMMAND; i < LAST_COMMAND; i++) {
Serial.println( FSH( name(i) ) );
}
Serial.println("Done");
}
void loop() {}