@includes at compilation

New with Arduino, not with other uprocessors. When in Arduino I compile a file like this:

#define F_CPU 16000000L

String command;
String temp1,temp2;
char inByte;
char carray[6];
int a,b,c;

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

void loop()
{
while (1)
{
while (Serial.available() <= 0)
{}
while (Serial.available() > 0)
{
etc

it compiles nicely, without any error. However, when I store the variable declaration in a separate file in the same working directory and call that like this:

#define F_CPU 16000000L
#include "H:\Programming\ArduinoProgramming\tester\variabls.c"

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

void loop()
{
while (1)
{
while (Serial.available() <= 0)
{}
etc

then two things happen that are a wee bit mysterious:

1 if I compile before restarting Arduino, so that it does not take the include file in the files bar, it tells me that the variables are not declared

2 If I restart Arduino, so that it also picks up the file variabls.c in the files bar, the error message changes into:

variabls.c:o: error expected '=',.... 'asm' or 'attribute' before çommand and point to the first line of variables. All lines defining the variables show this error, of course.

I am rewriting a program from ARM to Arduino and in total there are abt. 5000 lines, divided into functional groups in separate include files. Putting all those into one big file will make things unreadable. It would also be something difficult to have a list of all necessary include files in each separate include file.

And how can I keep any c- and h-files in the working directory out of tha files bar if I do not want them in? When I am testing some includes, it is a waste of time to also have to compile all other ones, that may be ready or not

Any comment is welcome.

Forgot to say: the program with all includes compile well when I use AVR Studio4, but then I have to write a lot of standard Arduino libraries again myself.

That is the nature of the IDE. It needs to be restarted to add in new files. Otherwise they are skipped during compilation.
To get rid of tabs, put finished code in the libraries folder, like all the arduino provided libraries.
It sounds like you should do the translation in an IDE like VC++ for managing lots of files.

That makes sense, indeed, but why do I then get the second type of error message, "expected ..."? Why is variabls.c then treated differently from the main file and not just added in? The variable type is String, and the declaration "String command.." is recognised in the main file so it should not make a difference in the included one. Obviously I am wrong in thinking that way, but why?

VC-++ or Studio4/C++ seem indeed to be the answer if this doesn't go well. I am doing industrial automation and moving suited projects from ARM to Arduino because of $$ and overkill.

One thing I don't understand is people that work with many files and:

  • Still use the IDE.
  • Don't write libraries, to use in the IDE.

Wouldn't it be simple than including .c files?

I got around this type of madness by renaming my .c or .cpp includes to .ino (or .pde for pre 1.0).

Hope that helps!

bubu: in '85-'86 I build and ran my first complete set of all imaginable functions in assembler for the 8086 in order to run things a bit faster at the then usual 4.7MHz processor speed. I used that later on in C and translated it for all other processors I worked with, but never compiled them in a lib because rewriting incs has become an easy habit. Nevertheless, if I get the chance to avoid that work, like with Arduino, I take it with joy. I use an IDE as a lazy alternative for writing command lines.

j5: Of course! Brilliant and simple. Bedtime now in this region, so I am going to try that after my first cup of office coffee.

However, when I store the variable declaration in a separate file in the same working directory and call that like this:

#define F_CPU 16000000L
#include "H:\Programming\ArduinoProgramming\tester\variabls.c"

Several observations. First, the Arduino programming experience will be a lot smoother for you if you forget that it can sort of deal with .c files.

.h and .cpp are the way to go.

Second, one does not usually include source files. One includes header files, for which there may or may not be matching source files.

Third, if the file to be included is in the same directory as the sketch, you should not use fully qualified names to include it.

Ouch - use a .h suffix for included files. Always use a relative filename, not absolute. Perhaps:

#include "variables.h"

If variables.h is in the same directory...

That the #include points to this working directory is happenstance because of the testing. For the common routines I use one main directory INCLUDES with processor subdirectories, like H:\includes\arm\lpc2129 and H:\includes\arduino\duemilanove; that is the reason why I #include the whole path in order not to have to copy all of them into every working directory over and again. Of course, I can also set the include search path in the respective compilers, but then that always has to be done that each time we switch processor. Maybe not common, but we agreed on this standardisation, contrary to the number of processors.

OK, this respective case. Whatever file extension I gave variabls, be it .h or .c or .cpp or .ino, the compiler gives me the error " 'xxxx' was not declared in this scope " at the first variable in the project file tester.ino; the compiler just does not look whether something is declared later on, whether specifically "#include"d or not. I guess that means switching to VC++ or AVRStudio.

Thanks for the comments!

Whatever file extension I gave variabls, be it .h or .c or .cpp or .ino, the compiler gives me the error " 'xxxx' was not declared in this scope " at the first variable in the project file tester.ino; the compiler just does not look whether something is declared later on, whether specifically "#include"d or not. I guess that means switching to VC++ or AVRStudio.

Personally, I think it means learning what the heck you are talking about.

One does not give variables file extensions.

You need to quit waving your hands and ranting, and post your file being included (with the proper extension), the sketch that it is included in, and the EXACT error message that the compiler generates. And, ALL of the messages.

Most people are able to use include files with no problems.

And, if you think that switching to another IDE will make life easier, you are in for a major disappointment.

Hello Paul,

What I posted are the lines that show the problem; why would I bore anyone with a few hundred lines that do not matter? In my first post I gave the essential; if the "etc" is replaced with a few }s the file is complete. As I said there, the contents of the file to be included is nothing but the declaration of the variables.

The libraries for each specific processor are located in one central main folder that is called "includes", so e.g. H:\includes\arm\lpc2129 for the LPC2129 and H:\includes\pic\PIC32MX110 for that one. When compiling in the working directory those files are called with an #include with the full path name, whether they are .h for constants and basic settings or .c/.cpp for non-project specific routines or whatever. That functions very well with all the c- and c++ compilers that have been used up to now, but it does not with the Arduino; that does not even include a file that is in the working directory, although it is shown in the file bar. As you said that most people are able to include files, I suspect that it is caused by a lack of knowledge on my side and that is why I ask. No ranting, no waving hands, just asking something that is outside of my (our, 3 of us) experiences.

If I declare a variable, say char Statement[9], or a routine procedure, e.g. int GimMeTheASCII(char Input), in the .ino, no problem. When I put the variable declaration in a separate .h or the proc in a separate .c/.cpp file, the Arduino does not recognise the calls from within the project file of the variable or the proc, neither when the files are shown in the file bar and nor when the files are called with an #include directive. What I get is the error message that the variable was not declared within this scope and the proc is unknown. AVRStudio compiles fine in this case, but then I have to write again the processor-specific routines and why, if I could use the ones from inside Arduino. I myself have been using gcc and other c-compilers for over 20 years now, but I am mistyfied why Arduino does not function in the usual way.

I myself have been using gcc and other c-compilers for over 20 years now, but I am mistyfied why Arduino does not function in the usual way.

Well, I hate to say this, but this is more arm waving. Post the ino file and the header and source files that illustrate the problem. It is not necessary to read all the code in order to paste some files into the IDE to reproduce your issue, and help you figure out how to work within the confines of the IDE.

OK, here we go. The example is coded here: http://www.smacula.co.uk/2011/07/arduino-serial-communication.html

This first one compiles fine; everything is included in the .ino.

//Project tester.ino, whole

String command; 
String temp1,temp2; 
char inByte; 
char carray[6]; 
int a,b,c; 

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

void loop()
{
  while (1)
  {
    if (Serial.available() > 0)
    {
      inByte = Serial.read();
      if ((inByte >= 65 && inByte <= 90) || (inByte >=97 && inByte <=122) || (inByte >= 48 && inByte <=57) || inByte == 43 || inByte == 61 || inByte == 63) 
        command.concat(inByte);
    }
    if (inByte == 10 || inByte == 13)
    {
      inByte = 0;
      command.concat(inByte);
    }
    if (command.equalsIgnoreCase("hey"))
    {
      Serial.println("hello there!");
    }
    else if(command.indexOf('+') > 0)
    {
      temp1 = command.substring(0,command.indexOf('+'));
      temp2 = command.substring(command.indexOf('+')+1);
      temp1.toCharArray(carray,6);
      a = atoi(carray);
      temp2.toCharArray(carray,6);
      b = atoi(carray);
      c = a + b;
      Serial.print("The sum of ");
      Serial.print(a,DEC);
      Serial.print(" and ");
      Serial.print(b,DEC);
      Serial.print(" is ");
      Serial.println(c,DEC);
    }
    else if (command.startsWith("mynameis"))
    {
      temp1 = command.substring(8);
      Serial.print("Hello, ");
      Serial.println(temp1);
    }
    else 
    { 
      if (!command.equalsIgnoreCase(""))
        Serial.println("Invalid argument.");
    }
    command = "";
   }
}

Now this is the version with the variables declared in variabls.h

//Project tester1.ino, 

//#include "variabls.h" //#include commented out

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

void loop()
{
  while (1)
  {
    if (Serial.available() > 0)
    {
      inByte = Serial.read();
      if ((inByte >= 65 && inByte <= 90) || (inByte >=97 && inByte <=122) || (inByte >= 48 && inByte <=57) || inByte == 43 || inByte == 61 || inByte == 63) 
        command.concat(inByte);
    }
    if (inByte == 10 || inByte == 13)
    {
      inByte = 0;
      command.concat(inByte);
    }
    if (command.equalsIgnoreCase("hey"))
    {
      Serial.println("hello there!");
    }
    else if(command.indexOf('+') > 0)
    {
      temp1 = command.substring(0,command.indexOf('+'));
      temp2 = command.substring(command.indexOf('+')+1);
      temp1.toCharArray(carray,6);
      a = atoi(carray);
      temp2.toCharArray(carray,6);
      b = atoi(carray);
      c = a + b;
      Serial.print("The sum of ");
      Serial.print(a,DEC);
      Serial.print(" and ");
      Serial.print(b,DEC);
      Serial.print(" is ");
      Serial.println(c,DEC);
    }
    else if (command.startsWith("mynameis"))
    {
      temp1 = command.substring(8);
      Serial.print("Hello, ");
      Serial.println(temp1);
    }
    else 
    { 
      if (!command.equalsIgnoreCase(""))
        Serial.println("Invalid argument.");
    }
    command = "";
   }
}

and variabls.h:

String command; 
String temp1,temp2; 
char inByte; 
char carray[6]; 
int a,b,c;

This constellation stops compiling in tester1 with the indicator at the line
inByte = Serial.read();

Now, the compiler apparently does not allow copy and paste of the error messages, but this listing starts with:

tester1.cpp: In function 'void loop()':
tester1:15: error: 'command' was not declared in this scope

and then it continues mentioning all occurrences of the variables.

When now the #include is decommented and thus activated, the compiler gives a different result; it stops in variabls.h at the first line and the first three lines of the error messages are:

In file included from tester1.cpp:1:
variabls.h:1: 'String' does not name a type
variabls.h:2: 'String' does not name a type

And then the complete list of the previous faulty compilation, beginning again with "tester1.cpp: In function 'void loop():'" follows.

If I put an Arduino command in variabls.h, for example Serial.begin(9600); as the first line, then I get an additional error:

variabls.h:1: error: expected constructor, destructor, or type conversion before '.' token

All this is following the normal procedure with other compilers and does not give any problems there.

And yes, I know that loop() is called over and over again as you mentioned in Strange crashing behaviour, but while(1) and while(true) are standard loop in other compilers. Habit, you know.

Now, the compiler apparently does not allow copy and paste of the error messages, but this listing starts with:

tester1.cpp: In function 'void loop()':
tester1:15: error: 'command' was not declared in this scope

and then it continues mentioning all occurrences of the variables.

Two things. First, this is to be expected, since you commented out the include statement. Second, my version of the IDE does allow copy and paste. There is something weird with yours if yours does not.

When now the #include is decommented and thus activated, the compiler gives a different result; it stops in variabls.h at the first line and the first three lines of the error messages are:

In file included from tester1.cpp:1:
variabls.h:1: 'String' does not name a type
variabls.h:2: 'String' does not name a type

This is why I asked you to stop waving your arms and post some actual code and actual messages. This set of messages is COMPLETELY different from what we have been talking about, and completely understandable.

Within the context of the include file, String IS undefined. You need to include either WProgram.h or Arduino.h, depending on which version of the IDE you are using, in your include files, so that in the context of the include file String IS defined as a type.

If I put an Arduino command in variabls.h, for example Serial.begin(9600); as the first line, then I get an additional error:

variabls.h:1: error: expected constructor, destructor, or type conversion before '.' token

Same reason; same solution.

Thanks, Paul. Ergo, once declared, the Arduino compiler does not carry the necessary includes over the whole project but instead on a file to file basis. Doesn't this multiple inclusion bloat the compiled program? I will check that once compared with a compilation with AVRstudio. We have an extra-long weekend coming up here, so I'll not be able to try this before Wednesday. I will leave a reply then. Have a good week-end.

dutchinnz:
Ergo, once declared, the Arduino compiler does not carry the necessary includes over the whole project but instead on a file to file basis.

The behaviour you're finding strange (probably because AVRStudio doesn't work like this ?) is the -AFAIKT- totally standard concept of "compilation unit" one expects from any decent c or c++ compiler. Each .cpp/.h couple is compiled without looking at other .ccp/.h couples. The only exception is when a .h or .cpp file includes the .h file of another "couple" (i.e. compilation unit). The .cpp files are never mixed though.

What I find really strange instead is that you want to put all the variables in a separate file. Put those poor symbols where they belong, atop the .ino file! :slight_smile:

Your issues were all punctuation, a missing ';' in variables.h, a missing '{' and 2 missing '}' in the main program.

//Project tester1.ino, 

#include "variables.h" //#include commented out

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

void loop()
{
  while (1)
  {
    if (Serial.available() > 0)
    {
      inByte = Serial.read();
      if ((inByte >= 65 && inByte <= 90) || (inByte >=97 && inByte <=122) || (inByte >= 48 && inByte <=57) || inByte == 43 || inByte == 61 || inByte == 63)
       { 
        command.concat(inByte);
    }
    if (inByte == 10 || inByte == 13)
    {
      inByte = 0;
      command.concat(inByte);
    }
    if (command.equalsIgnoreCase("hey"))
    {
      Serial.println("hello there!");
    }
    else if(command.indexOf('+') > 0)
    {
      temp1 = command.substring(0,command.indexOf('+'));
      temp2 = command.substring(command.indexOf('+')+1);
      temp1.toCharArray(carray,6);
      a = atoi(carray);
      temp2.toCharArray(carray,6);
      b = atoi(carray);
      c = a + b;
      Serial.print("The sum of ");
      Serial.print(a,DEC);
      Serial.print(" and ");
      Serial.print(b,DEC);
      Serial.print(" is ");
      Serial.println(c,DEC);
    }
    else if (command.startsWith("mynameis"))
    {
      temp1 = command.substring(8);
      Serial.print("Hello, ");
      Serial.println(temp1);
    }
    else 
    { 
      if (!command.equalsIgnoreCase(""))
        Serial.println("Invalid argument.");
    }
    command = "";
   }
  }
}
#include "Arduino.h"
String command; 
String temp1,temp2; 
char inByte; 
char carray[6]; 
int a,b,c;

Doesn't this multiple inclusion bloat the compiled program?

No, it does not. If a data type is defined in a header file, and that header file is included in 1 file, there is one definition. If it is included in 47 files, there is still only one definition.

This is why header files are not supposed to contain executable code. Where executable code is contained in a file that is included, care needs to be taken to ensure that multiple copies of that code are not included.