"not declared in this scope"

I’m learning to use PROGMEM to store data (first, static data, then possibly dynamic data) in the program memory space. I have several large arrays and tons of free program memory.

I had a sketch successfully compiling, but when I tried to move the data definitions into an .h file to be included, I received errors that the variable references were “not declared in this scope”. I understood that the include statement merely copied to code inline into the sketch. Hence, I am confused why changing to an include file would cause the not declared error?

Any idea why the following errors happen"


My sketch is as follows:

// #include <SoftwareSerial.h> 
// #include <SPI.h>
// #include <SD.h> 
#include <avr/pgmspace.h>

// initialize move commands
#include <MoveCommands.h>

// setup tokenized program
#include <PeterLive5.h>

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

void loop()
{  
  for (int i = 0; i < 63; i++)
  {
    strcpy_P(MoveBuffer, (char*)pgm_read_word(&(MoveCommand[i]))); // Necessary casts and dereferencing, just copy. 
    Serial.println( MoveBuffer );
    delay( 10 );
  }

 }

and the contents of MoveCommand.h is as follows:

prog_char MoveString_0[] PROGMEM ="#0P1500#1P1500#2P1000#3P570#4P1500#5P2400#6P510#8P1500#9P1500#10P1500#11P1400T1000";
prog_char MoveString_1[] PROGMEM ="#2P1100";
prog_char MoveString_2[] PROGMEM ="#0P2000 #1P1100 T100";
prog_char MoveString_3[] PROGMEM ="#2P750";
prog_char MoveString_4[] PROGMEM ="#2P1000";
prog_char MoveString_5[] PROGMEM ="#2P1000 T3000";
prog_char MoveString_6[] PROGMEM ="#2P1500 T2000";
prog_char MoveString_7[] PROGMEM ="#2P1200";
prog_char MoveString_8[] PROGMEM ="#2P2000";
prog_char MoveString_9[] PROGMEM ="#2P2000 T3000";
prog_char MoveString_10[] PROGMEM ="#0P1500 #1P1500 T100";
prog_char MoveString_11[] PROGMEM ="#0P1100 #1P1100 T100";
prog_char MoveString_12[] PROGMEM ="#0P2000 #1P2000 T100";
prog_char MoveString_13[] PROGMEM ="#0P1100 #1P1100 T1500";
prog_char MoveString_14[] PROGMEM ="#0P1500 #1P1500 T1500";
prog_char MoveString_15[] PROGMEM ="#0P2000 #1P2000 T1500";
prog_char MoveString_16[] PROGMEM ="#9P1000S2000 T500";
prog_char MoveString_17[] PROGMEM ="#9P2250S2000 T500";
prog_char MoveString_18[] PROGMEM ="#8P2250S1667 T500";
prog_char MoveString_19[] PROGMEM ="#8P1500S1667 T500";
prog_char MoveString_20[] PROGMEM ="#8P750S1667 T300";
prog_char MoveString_21[] PROGMEM ="#11P1200S1000 T750";
prog_char MoveString_22[] PROGMEM ="#11P1800S1000 T750";
prog_char MoveString_23[] PROGMEM ="#10P1100S1667 T750";
prog_char MoveString_24[] PROGMEM ="#10P1900S1667 T750";
prog_char MoveString_25[] PROGMEM ="#9P860S3000 #11P2500S1500";
prog_char MoveString_26[] PROGMEM ="#9P900S2500 #11P1200S1500 #8P900S3000 #10P900S2500";
prog_char MoveString_27[] PROGMEM ="#9P1500S2000 #11P1500S1000 T500";
prog_char MoveString_28[] PROGMEM ="#9P2200S3000 #11P870S1500";
prog_char MoveString_29[] PROGMEM ="#10P1100S1667 #8P2250S1667 T500";
prog_char MoveString_30[] PROGMEM ="#10P1500S1667 #8P1500S1667 T500";
prog_char MoveString_31[] PROGMEM ="#10P2200S1667 #8P750S1667 T500";
prog_char MoveString_32[] PROGMEM ="#8P1500S1667 #9P1500S2000 #10P1500S1667 #11P1500S1000 T500";
prog_char MoveString_33[] PROGMEM ="#8P1500S1667 #9P1500S2000 #10P1500S1667 #11P1500S1000 T1500";
prog_char MoveString_34[] PROGMEM ="#5P1200 T100";
prog_char MoveString_35[] PROGMEM ="#5P1850 T100";
prog_char MoveString_36[] PROGMEM ="#5P2500 T100";
prog_char MoveString_37[] PROGMEM ="#6P1500 T100";
prog_char MoveString_38[] PROGMEM ="#6P950 T100";
prog_char MoveString_39[] PROGMEM ="#6P650 T100";
prog_char MoveString_40[] PROGMEM ="#6P1500 T100";
prog_char MoveString_41[] PROGMEM ="#5P1200 #61850 T100" ;
prog_char MoveString_42[] PROGMEM ="#5P1850 #6P950 T100";
prog_char MoveString_43[] PROGMEM ="#5P2500 #6P650 T100";
prog_char MoveString_44[] PROGMEM ="#4P2200";
prog_char MoveString_45[] PROGMEM ="#4P1500";
prog_char MoveString_46[] PROGMEM ="#4P750";
prog_char MoveString_47[] PROGMEM ="#4P2200T1000";
prog_char MoveString_48[] PROGMEM ="#4P1500T1000";
prog_char MoveString_49[] PROGMEM ="#4P750T1000";
prog_char MoveString_50[] PROGMEM ="#9P1500S2000 #11P1500S1000 #8P1000S1667 #10P1000S1667 T300";
prog_char MoveString_51[] PROGMEM ="#9P2100S2000 #11P1800S1000 #8P1000S1667 #10P1000S1667 T300";
prog_char MoveString_52[] PROGMEM ="#9P2100S2000 #11P1800S1000 #8P1500S1667 #10P1500S1667 T300";
prog_char MoveString_53[] PROGMEM ="#9P2100S2000 #11P1800S1000 #8P2000S1667 #10P2000S1667 T300";
prog_char MoveString_54[] PROGMEM ="#9P1500S2000 #11P1500S1000 #8P2000S1667 #10P2000S1667 T300";
prog_char MoveString_55[] PROGMEM ="#9P900S2000  #11P1200S1000 #8P2000S1667 #10P2000S1667 T300";
prog_char MoveString_56[] PROGMEM ="#9P900S2000  #11P1200S1000 #8P1500S1667 #10P1500S1667 T300";
prog_char MoveString_57[] PROGMEM ="#9P900S2000  #11P1200S1000 #8P1000S1667 #10P900S1667  T300";
prog_char MoveString_58[] PROGMEM ="#3P570";
prog_char MoveString_59[] PROGMEM ="#3P600";
prog_char MoveString_60[] PROGMEM ="#3P680";
prog_char MoveString_61[] PROGMEM ="#3P790";
prog_char MoveString_62[] PROGMEM ="#3P1005";
prog_char MoveString_63[] PROGMEM ="End";

PROGMEM const prog_char* MoveCommand[] =
{
MoveString_0 ,
MoveString_1 ,
MoveString_2 ,
MoveString_3 ,
MoveString_4 ,
MoveString_5 ,
MoveString_6 ,
MoveString_7 ,
MoveString_8 ,
MoveString_9 ,
MoveString_10,
MoveString_11,
MoveString_12,
MoveString_13,
MoveString_14,
MoveString_15,
MoveString_16,
MoveString_17,
MoveString_18,
MoveString_19,
MoveString_20,
MoveString_21,
MoveString_22,
MoveString_23,
MoveString_24,
MoveString_25,
MoveString_26,
MoveString_27,
MoveString_28,
MoveString_29,
MoveString_30,
MoveString_31,
MoveString_32,
MoveString_33,
MoveString_34,
MoveString_35,
MoveString_36,
MoveString_37,
MoveString_38,
MoveString_39,
MoveString_40,
MoveString_41,
MoveString_42,
MoveString_43,
MoveString_44,
MoveString_45,
MoveString_46,
MoveString_47,
MoveString_48,
MoveString_49,
MoveString_50,
MoveString_51,
MoveString_52,
MoveString_53,
MoveString_54,
MoveString_55,
MoveString_56,
MoveString_57,
MoveString_58,
MoveString_59,
MoveString_60,
MoveString_61,
MoveString_62,
MoveString_63
};

char MoveBuffer[82];

Change the #include to:

#include "MoveCommand.h"

Ok, that worked, but why? The documentation doesn’t indicate a difference between using quotes and <>.
???

The MoveCommand.h file is in your work directory, I believe. When you want to include one file that is in your work directory you must use quotes. When you need to include that is in the “system”, or in this case, one file that is Arduino environment you use < >.

OK that makes sense, except...

"PeterLive5.h" is in my work directory. And if I include it in quotes, I receive several errors...

Arduino: 1.5.6-r2 (Windows 7), Board: "Arduino Uno"

In file included from atest_2.ino:11:
/PeterLive5.h:1: error: expected constructor, destructor, or type conversion before '=' token
/PeterLive5.h:3: error: expected constructor, destructor, or type conversion before '=' token
/PeterLive5.h:4: error: expected constructor, destructor, or type conversion before '=' token
/PeterLive5.h:5: error: expected constructor, destructor, or type conversion before '=' token
/PeterLive5.h:6: error: expected constructor, destructor, or type conversion before '=' token
/PeterLive5.h:8: error: expected constructor, destructor, or type conversion before '=' token
/PeterLive5.h:9: error: expected constructor, destructor, or type conversion before '=' token
/PeterLive5.h:10: error: expected constructor, destructor, or type conversion before '=' token
/PeterLive5.h:11: error: expected constructor, destructor, or type conversion before '=' token
...omitted...
/PeterLive5.h:546: error: expected constructor, destructor, or type conversion before '=' token
/PeterLive5.h:548: error: expected constructor, destructor, or type conversion before '=' token
/PeterLive5.h:549: error: expected constructor, destructor, or type conversion before '=' token
/PeterLive5.h:550: error: expected constructor, destructor, or type conversion before '=' token
/PeterLive5.h:551: error: expected constructor, destructor, or type conversion before '=' token

You haven't shown us that file so I can't guess what might be causing those errors. It ought to be apparent if you look at the code around the lines which are reporting the error, though.

Ok. I'll get back to you.

Did you wrote the PeterLive5.h file too?

Yes... The contents of that file follows:

ScriptSize= 109;

ScriptAction[0] =  0;
ScriptDescription[0] =  0;
ScriptOption[0] =  0;
ScriptStack[0] =  0;
//
ScriptAction[ 1] =  0;
ScriptDescription[ 1] =  9;
ScriptOption[ 1] =  200;
ScriptStack[ 1] =  2;
//
ScriptAction[ 2] =  8;
ScriptDescription[ 2] =  100;
ScriptOption[ 2] =  100;
ScriptStack[ 2] =  3;
//
ScriptAction[ 3] =  0;
ScriptDescription[ 3] =  5;
ScriptOption[ 3] =  200;
ScriptStack[ 3] =  4;
//
ScriptAction[ 4] =  8;
ScriptDescription[ 4] =  100;
ScriptOption[ 4] =  100;
ScriptStack[ 4] =  5;
//
...omitted...
//
ScriptAction[ 109] =  3;
ScriptDescription[ 109] =  0;
ScriptOption[ 109] =  0;
ScriptStack[ 109] =  0;
//

I'm learning to use PROGMEM to store data (first, static data, then possibly dynamic data)

You cannot store dynamic data in the program flash memory.

Where is the declaration of all those arrays ?

The arrays are declared earlier in the program, just not in the code I posted. More later.

The assignments in PeterLive5.h are not intended to be stored in program flash memory, because in fact they are dynamic. The initializations in MoveCommand.h however are static and ARE what I was attempting to store in program flash memory.

It appears my problem occurs because while variable initialization can occur globally, value assignment MUST be done in a function. Once I move the assignment statements to the loop function, it compiles successfully.

Here is the LATEST incarnation of my test program:

// #include <SoftwareSerial.h> 
// #include <SPI.h>
// #include <SD.h> 
#include <avr/pgmspace.h>

// initialize move commands
#include "MoveCommands.h"

int ScriptSize= 109;
int ScriptAction[ 127];
int ScriptDescription[ 127];
int ScriptOption[ 127];
int ScriptStack[ 127];


void setup()
{
  // setup tokenized program
#include "PeterLive5.h"
Serial.begin(9600);
}

void loop()
{  
  for (int i = 0; i < 63; i++)
  {
    strcpy_P(MoveBuffer, (char*)pgm_read_word(&(MoveCommand[i]))); // Necessary casts and dereferencing, just copy. 
    Serial.println( MoveBuffer );
    delay( 10 );
  }

 }

MoveCommand.h

prog_char MoveString_0[] PROGMEM ="#0P1500#1P1500#2P1000#3P570#4P1500#5P2400#6P510#8P1500#9P1500#10P1500#11P1400T1000";
prog_char MoveString_1[] PROGMEM ="#2P1100";
prog_char MoveString_2[] PROGMEM ="#0P2000 #1P1100 T100";
prog_char MoveString_3[] PROGMEM ="#2P750";
prog_char MoveString_4[] PROGMEM ="#2P1000";
prog_char MoveString_5[] PROGMEM ="#2P1000 T3000";
prog_char MoveString_6[] PROGMEM ="#2P1500 T2000";
prog_char MoveString_7[] PROGMEM ="#2P1200";
prog_char MoveString_8[] PROGMEM ="#2P2000";
prog_char MoveString_9[] PROGMEM ="#2P2000 T3000";
prog_char MoveString_10[] PROGMEM ="#0P1500 #1P1500 T100";
prog_char MoveString_11[] PROGMEM ="#0P1100 #1P1100 T100";
prog_char MoveString_12[] PROGMEM ="#0P2000 #1P2000 T100";
prog_char MoveString_13[] PROGMEM ="#0P1100 #1P1100 T1500";
prog_char MoveString_14[] PROGMEM ="#0P1500 #1P1500 T1500";
prog_char MoveString_15[] PROGMEM ="#0P2000 #1P2000 T1500";
prog_char MoveString_16[] PROGMEM ="#9P1000S2000 T500";
prog_char MoveString_17[] PROGMEM ="#9P2250S2000 T500";
prog_char MoveString_18[] PROGMEM ="#8P2250S1667 T500";
prog_char MoveString_19[] PROGMEM ="#8P1500S1667 T500";
prog_char MoveString_20[] PROGMEM ="#8P750S1667 T300";
prog_char MoveString_21[] PROGMEM ="#11P1200S1000 T750";
prog_char MoveString_22[] PROGMEM ="#11P1800S1000 T750";
prog_char MoveString_23[] PROGMEM ="#10P1100S1667 T750";
prog_char MoveString_24[] PROGMEM ="#10P1900S1667 T750";
prog_char MoveString_25[] PROGMEM ="#9P860S3000 #11P2500S1500";
prog_char MoveString_26[] PROGMEM ="#9P900S2500 #11P1200S1500 #8P900S3000 #10P900S2500";
prog_char MoveString_27[] PROGMEM ="#9P1500S2000 #11P1500S1000 T500";
prog_char MoveString_28[] PROGMEM ="#9P2200S3000 #11P870S1500";
prog_char MoveString_29[] PROGMEM ="#10P1100S1667 #8P2250S1667 T500";
prog_char MoveString_30[] PROGMEM ="#10P1500S1667 #8P1500S1667 T500";
prog_char MoveString_31[] PROGMEM ="#10P2200S1667 #8P750S1667 T500";
prog_char MoveString_32[] PROGMEM ="#8P1500S1667 #9P1500S2000 #10P1500S1667 #11P1500S1000 T500";
prog_char MoveString_33[] PROGMEM ="#8P1500S1667 #9P1500S2000 #10P1500S1667 #11P1500S1000 T1500";
prog_char MoveString_34[] PROGMEM ="#5P1200 T100";
prog_char MoveString_35[] PROGMEM ="#5P1850 T100";
prog_char MoveString_36[] PROGMEM ="#5P2500 T100";
prog_char MoveString_37[] PROGMEM ="#6P1500 T100";
prog_char MoveString_38[] PROGMEM ="#6P950 T100";
prog_char MoveString_39[] PROGMEM ="#6P650 T100";
prog_char MoveString_40[] PROGMEM ="#6P1500 T100";
prog_char MoveString_41[] PROGMEM ="#5P1200 #61850 T100" ;
prog_char MoveString_42[] PROGMEM ="#5P1850 #6P950 T100";
prog_char MoveString_43[] PROGMEM ="#5P2500 #6P650 T100";
prog_char MoveString_44[] PROGMEM ="#4P2200";
prog_char MoveString_45[] PROGMEM ="#4P1500";
prog_char MoveString_46[] PROGMEM ="#4P750";
prog_char MoveString_47[] PROGMEM ="#4P2200T1000";
prog_char MoveString_48[] PROGMEM ="#4P1500T1000";
prog_char MoveString_49[] PROGMEM ="#4P750T1000";
prog_char MoveString_50[] PROGMEM ="#9P1500S2000 #11P1500S1000 #8P1000S1667 #10P1000S1667 T300";
prog_char MoveString_51[] PROGMEM ="#9P2100S2000 #11P1800S1000 #8P1000S1667 #10P1000S1667 T300";
prog_char MoveString_52[] PROGMEM ="#9P2100S2000 #11P1800S1000 #8P1500S1667 #10P1500S1667 T300";
prog_char MoveString_53[] PROGMEM ="#9P2100S2000 #11P1800S1000 #8P2000S1667 #10P2000S1667 T300";
prog_char MoveString_54[] PROGMEM ="#9P1500S2000 #11P1500S1000 #8P2000S1667 #10P2000S1667 T300";
prog_char MoveString_55[] PROGMEM ="#9P900S2000  #11P1200S1000 #8P2000S1667 #10P2000S1667 T300";
prog_char MoveString_56[] PROGMEM ="#9P900S2000  #11P1200S1000 #8P1500S1667 #10P1500S1667 T300";
prog_char MoveString_57[] PROGMEM ="#9P900S2000  #11P1200S1000 #8P1000S1667 #10P900S1667  T300";
prog_char MoveString_58[] PROGMEM ="#3P570";
prog_char MoveString_59[] PROGMEM ="#3P600";
prog_char MoveString_60[] PROGMEM ="#3P680";
prog_char MoveString_61[] PROGMEM ="#3P790";
prog_char MoveString_62[] PROGMEM ="#3P1005";
prog_char MoveString_63[] PROGMEM ="End";

PROGMEM const prog_char* MoveCommand[] =
{
MoveString_0 ,
MoveString_1 ,
MoveString_2 ,
MoveString_3 ,
MoveString_4 ,
MoveString_5 ,
MoveString_6 ,
MoveString_7 ,
MoveString_8 ,
MoveString_9 ,
MoveString_10,
MoveString_11,
MoveString_12,
MoveString_13,
MoveString_14,
MoveString_15,
MoveString_16,
MoveString_17,
MoveString_18,
MoveString_19,
MoveString_20,
MoveString_21,
MoveString_22,
MoveString_23,
MoveString_24,
MoveString_25,
MoveString_26,
MoveString_27,
MoveString_28,
MoveString_29,
MoveString_30,
MoveString_31,
MoveString_32,
MoveString_33,
MoveString_34,
MoveString_35,
MoveString_36,
MoveString_37,
MoveString_38,
MoveString_39,
MoveString_40,
MoveString_41,
MoveString_42,
MoveString_43,
MoveString_44,
MoveString_45,
MoveString_46,
MoveString_47,
MoveString_48,
MoveString_49,
MoveString_50,
MoveString_51,
MoveString_52,
MoveString_53,
MoveString_54,
MoveString_55,
MoveString_56,
MoveString_57,
MoveString_58,
MoveString_59,
MoveString_60,
MoveString_61,
MoveString_62,
MoveString_63
};

char MoveBuffer[82];

PeterLive5.h

ScriptAction[0] =  0;
ScriptDescription[0] =  0;
ScriptOption[0] =  0;
ScriptStack[0] =  0;
//
ScriptAction[ 1] =  0;
ScriptDescription[ 1] =  9;
ScriptOption[ 1] =  200;
ScriptStack[ 1] =  2;
//
ScriptAction[ 2] =  8;
ScriptDescription[ 2] =  100;
ScriptOption[ 2] =  100;
ScriptStack[ 2] =  3;
//
ScriptAction[ 3] =  0;
ScriptDescription[ 3] =  5;
ScriptOption[ 3] =  200;
ScriptStack[ 3] =  4;
//
...omitted...
ScriptAction[109]=3;
ScriptDescription[109]=0;
ScriptOption[109]=0;
ScriptStack[109]=0;
//

djsfantasi: Yes... The contents of that file follows:

You can't assign a value to a variable unless it's in a function, or it is being initialized.

Arrch:

djsfantasi: Yes... The contents of that file follows:

You can't assign a value to a variable unless it's in a function, or it is being initialized.

Isn't that what I said?

djsfantasi: Isn't that what I said?

That's not what your code says.

Setup() and loop() are considered functions. The variable assignment occurs in the former. Hence, it compiles successfully.

Or have I missed something?

djsfantasi: PeterLive5.h

ScriptAction[0] =  0;
ScriptDescription[0] =  0;
ScriptOption[0] =  0;
ScriptStack[0] =  0;
//
ScriptAction[ 1] =  0;
ScriptDescription[ 1] =  9;
ScriptOption[ 1] =  200;
ScriptStack[ 1] =  2;
//
ScriptAction[ 2] =  8;
ScriptDescription[ 2] =  100;
ScriptOption[ 2] =  100;
ScriptStack[ 2] =  3;
//
ScriptAction[ 3] =  0;
ScriptDescription[ 3] =  5;
ScriptOption[ 3] =  200;
ScriptStack[ 3] =  4;
//
...omitted...
ScriptAction[109]=3;
ScriptDescription[109]=0;
ScriptOption[109]=0;
ScriptStack[109]=0;
//

Not in setup() or loop()

Why do you say its not in setup()?

void setup()
{
  // setup tokenized program
  #include "PeterLive5.h"
  Serial.begin(9600);
}
void setup()
{
  // setup tokenized program
  #include "PeterLive5.h"
  Serial.begin(9600);
}

So it's worse than I thought...

As a general rule, it's not a good idea to have any include preprocessor directives in a function. If there are global data definitions in the include file, their scope would be limited to that fnction.