Pages: [1] 2   Go Down
Author Topic: Using serial.print to debug a library  (Read 973 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm trying to clean up some code I wrote by splitting it into separate files either in tabs or ultimately into a library. I have a lot of debug statements that print to the console and I'm wondering how to pass a serial object reference to the library. I found some simple examples (but can no longer find the thread) so I'll re-post them here.  The code compiles o.k. when it's all in the main tab but as I tried splitting it into 3 tabs (.ino, .c &.h) I get a compiler error.

myLibrary.c:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'MyLibrary'

Here's the whole piece of code.

Code:
class MyLibrary {
  public:
    //pass a reference to a Print object
    MyLibrary( HardwareSerial &print ) {
      printer = &print; //operate on the adress of print
      printer->begin(9600);
    }
    void test() {
      printer->println("Hello library with serial connectivity!");
    }
  private:
    HardwareSerial* printer;
};

MyLibrary myLibrary(Serial);

void setup() {
  myLibrary.test();
}
void loop() {}

Here's how I tried to split it up first the .ino file

Code:
#include "myLibrary.c"
MyLibrary myLibrary(Serial);

void setup() {
  myLibrary.test();
}
void loop() {
  delay(10);
  myLibrary.test();

}
Then the .h file
Code:
#ifndef _EXAMPLE_SPLIT_H
#define _EXAMPLE_SPLIT_H
#endif
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "HardwareSerial.h"

class MyLibrary {
  public:
    //pass a reference to a Print object
    MyLibrary( HardwareSerial &print );
    void test() ;
  private:
    HardwareSerial* printer;
};
and finally the .c file
Code:
class  MyLibrary {
  public:
    //pass a reference to a Print object
    MyLibrary( HardwareSerial &print ) {
      printer = &print; //operate on the adress of print
      printer->begin(9600);
    }
    void test() {
      printer->println("Hello library with serial connectivity!");
    }
  private:
    HardwareSerial* printer;
};

Any suggestions on how to pass the serial class by reference into a library in a separate file?

Cheers Kb
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 551
Posts: 46224
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

First question is why are you using a c file? The Arduino is programmed in C++, which uses cpp as the extension. There is a huge difference in the way the c compiler produces object code and the way that the cpp compiler produces object code.

C doesn't have classes, so putting the class implementation in a c file doesn't make sense.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well That's embarrassing, I've been working on Vex robots mostly, and when using the Arduino just worked in a single file.  I did switch to .cpp file extension and I get different (but somewhat similar) errors. I also noticed I posted the wrong example of my Library split amongst files.

The corrected posting is below:

.ino file
Code:
#include "MyLibrary.h"
MyLibrary myLibrary(Serial);

void setup() {
  myLibrary.test();
}
void loop() {}
.h file
Code:
#ifndef _EXAMPLE_SPLIT_H
#define _EXAMPLE_SPLIT_H
#endif
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "HardwareSerial.h"

class MyLibrary {
  public:
    //pass a reference to a Print object
    MyLibrary( HardwareSerial &print );
    void test();
  private:
    HardwareSerial* printer;
};
.cpp file
Code:
class MyLibrary {
  public:
    //pass a reference to a Print object
    MyLibrary( HardwareSerial &print ) {
      printer = &print; //operate on the adress of print
      printer->begin(9600);
    }
    void test() {
      printer->println("Hello library with serial connectivity!");
    }
  private:
    HardwareSerial* printer;
};

Errors reported by the compiler:
MyLibrary.cpp:3: error: expected `)' before '&' token
MyLibrary.cpp:11: error: ISO C++ forbids declaration of 'HardwareSerial' with no type
MyLibrary.cpp:11: error: expected ';' before '*' token
MyLibrary.cpp: In member function 'void MyLibrary::test()':
MyLibrary.cpp:8: error: 'printer' was not declared in this scope

I would appreciate any help resolving the first 2-3 errors The last error looks to be caused by the first error not being resolved.

Thanks - Kb
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 551
Posts: 46224
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The cpp file has no idea what a HardwareSerial is. You need to include the header file in the source file.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for your help PaulS,

I've included the Hardware serial header in the file but I still get errors.

HardwareSerialClassExampleSplit.cpp.o: In function `__static_initialization_and_destruction_0':
C:\Users\Kb\AppData\Local\Temp\build6312645766259194773.tmp/HardwareSerialClassExampleSplit.cpp:5: undefined reference to `MyLibrary::MyLibrary(HardwareSerial&)'
HardwareSerialClassExampleSplit.cpp.o: In function `setup':
C:\Users\Kb\AppData\Local\Temp\build6312645766259194773.tmp/HardwareSerialClassExampleSplit.cpp:8: undefined reference to `MyLibrary::test()'

I had another window open and had a typo including the MyLibrary.cpp file vs the MyLibray.h file and that version compiles.  I don't think that what I'm supposed to do though is it?

So the version which includes the .h file and spits out the above errors is:
Code:
#include "MyLibrary.h"
MyLibrary myLibrary(Serial);

void setup() {
  myLibrary.test();
}
void loop() {}

The one that compiled clean is:
Code:
#include "myLibrary.cpp"

MyLibrary myLibrary(Serial);

void setup() {

  myLibrary.test(); 
}
void loop() {
  delay(10);
  myLibrary.test();

}

In both cases I modified the .cpp file to read
Code:
#include "HardwareSerial.h"
class MyLibrary {
  public:
    //pass a reference to a Print object
    MyLibrary( HardwareSerial &print ) {
      printer = &print; //operate on the adress of print
      printer->begin(9600);
    }
    void test() {
      printer->println("Hello library with serial connectivity!");
    }
  private:
    HardwareSerial* printer;
};
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 551
Posts: 46224
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
#include "myLibrary.cpp"
You should not be including source files in sketches. You only include header files.

File names are case sensitive. myLibrary.cpp and MyLibrary.h don't play together.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
#include "myLibrary.cpp"
You should not be including source files in sketches. You only include header files.

File names are case sensitive. myLibrary.cpp and MyLibrary.h don't play together.

Agreed, That is not what I intended, so back to the current compilation errors;

HardwareSerialClassExampleSplit.cpp.o: In function `setup':
C:\Users\Kb\AppData\Local\Temp\build6312645766259194773.tmp/HardwareSerialClassExampleSplit.cpp:7: undefined reference to `MyLibrary::MyLibrary(HardwareSerial&)'
C:\Users\Kb\AppData\Local\Temp\build6312645766259194773.tmp/HardwareSerialClassExampleSplit.cpp:9: undefined reference to `MyLibrary::test()'

Any idea why I am getting an undefined reference to `MyLibrary::MyLibrary(HardwareSerial&) error?

Cheers Kb
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So just to recap I seem to be having linker errors for this example to use the Serial.print function from a library as coded in multiple tabs in a sketch:
.ino file
Code:
#include "MyLibrary.h"

MyLibrary myLibrary(Serial);

void setup() {

  myLibrary.test();
}
void loop() {}

.cpp file
Code:
#include "HardwareSerial.h"

class MyLibrary {
  public:
    //pass a reference to a Print object
    MyLibrary( HardwareSerial &print ) {
      printer = &print; //operate on the address of print
      printer->begin(9600);
    }
    void test() {
      printer->println("Hello library with serial connectivity!");
    }
  private:
    HardwareSerial* printer;
};
.h file
Code:
#ifndef _EXAMPLE_SPLIT_H
#define _EXAMPLE_SPLIT_H
#endif
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

class MyLibrary {
  public:
    //pass a reference to a Print object
    MyLibrary( HardwareSerial &print );
    void test();
  private:
    HardwareSerial* printer;
};

Errors:

HardwareSerialClassExampleSplit.cpp.o: In function `__static_initialization_and_destruction_0':
C:\Users\Kb\AppData\Local\Temp\build5255053454461430477.tmp/HardwareSerialClassExampleSplit.cpp:7: undefined reference to `MyLibrary::MyLibrary(HardwareSerial&)'
HardwareSerialClassExampleSplit.cpp.o: In function `setup':
C:\Users\Kb\AppData\Local\Temp\build5255053454461430477.tmp/HardwareSerialClassExampleSplit.cpp:11: undefined reference to `MyLibrary::test()'

Thanks in advance for advice on how to resolve this or if this is not allowed for some reason.

Cheers Kb
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 551
Posts: 46224
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There are many bugs in that last stuff you posted. The sketch looks fine. The source file looks like a header file. The header file has an include guard that is useless.

MyLibrary.h should look like:
Code:
#ifndef _MYLIBRARY_H
#define _MYLIBRARY_H
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

class MyLibrary {
  public:
    //pass a reference to a Print object
    MyLibrary( HardwareSerial &print );
    void test();
  private:
    HardwareSerial* printer;
};
#endif

It's hard to say what MyLibrary.cpp should look like, at this point. At a minimum, it needs to #include MyLibrary.h.
Logged

Offline Offline
Edison Member
*
Karma: 17
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Your .cpp file should not have the class definition. It should look like this:
Code:
#include "HardwareSerial.h"
//pass a reference to a Print object
MyLibrary::MyLibrary( HardwareSerial &print ) {
  printer = &print; //operate on the address of print
  printer->begin(9600);
}
MyLibrary::void test() {
  printer->println("Hello library with serial connectivity!");
}
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 551
Posts: 46224
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
It should look like this:
Really? No need to include MyLibrary.h?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks I will try these and re-post.  Just a quick response, when I included the MyLibrary.h file in the .cpp file I got duplicate class definitions.  That should have been telling in the first place. but I haven't used C++ in almost 15 years.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 551
Posts: 46224
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Just a quick response, when I included the MyLibrary.h file in the .cpp file I got duplicate class definitions.
The #ifndef/#define/#endif statements prevent multiple inclusions of the same code. That is why the class definition is between the ifndef statement and the endif statement. Moving the endif statement to the top of the file made the guard useless, since it was no longer guarding anything.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

O.k. Got the point on the guard, I actually needed 2 #endif at the end.  I got the code to compile, but it does not print to the serial port. I had to change the baud rate from the previous example to match my current setup:

Here's the final three pieces which compile. 
.ino ( I added a call to test and a delay in the loop)
Code:
#include "MyLibrary.h"

MyLibrary myLibrary(Serial);

void setup() {

  myLibrary.test();
}
void loop() {
  myLibrary.test();
  delay(1000);
}

.cpp (Corrected, thanks for the corrections, I did need to include MyLibrary.h)
Code:
#include "MyLibrary.h"
#include "HardwareSerial.h"

    //pass a reference to a Print object
    MyLibrary::MyLibrary( HardwareSerial &print ) {
      printer = &print; //operate on the address of print
      printer->begin(115200);
    }
    void MyLibrary::test() {
      printer->println("Hello library with serial connectivity!");
    }

And Header with the second #endif added to the bottom of the file
Code:
#ifndef _MYLIBRARY_H
#define _MYLIBRARY_H
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

class MyLibrary {
  public:
    //pass a reference to a Print object
    MyLibrary( HardwareSerial &print );
    void test();
  private:
    HardwareSerial* printer;
};
#endif

Now to try to find out why it doesn't output anything to the port. - Thanks again - Kb
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 551
Posts: 46224
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Now to try to find out why it doesn't output anything to the port.
Well, that's easy. When is your class constructor called? When is the HardwareSerial constructor called? You don't know, do you? Therefore, you should not write code that relies on them being called in the correct order.

You need a begin() method in your class. You pass nothing to the constructor. You pass a serial instance to the begin method. You call the begin method in the setup() function.
Logged

Pages: [1] 2   Go Up
Jump to: