Declaring a HardwareSerial object?

Hi
I am currently writing a library that contains functions to operate the Openlog data logger. What i would like to do (if its possible) is to declare a public hardwareSerial object and initialize it according to the user’s requirements when the class constructor is called, instead of setting to a specific serial port. To be more specific see the code bellow.

//----------------------------------------------------------------------------------------------
//Datalog.cpp file (just a part of it)
//----------------------------------------------------------------------------------------------
Datalog::Datalog(HardwareSerial port, int sped)//Datalog constructor
{
	serialPort=port; //Initialize the global serial port according to user's req
	serialPort.begin(sped); //set the port speed
}
//----------------------------------------------------------------------------------------------
//Datalog.h file
//----------------------------------------------------------------------------------------------
#ifndef Datalog_h
#define Datalog_h

#include "WProgram.h"
#include "HardwareSerial.h"


class Datalog:public HardwareSerial
{
   
	public:
		typedef HardwareSerial serialPort; //here is the issue 
		Datalog(HardwareSerial port, int sped);//constructor
		void writedata(String msg);
		void appendFile(String file);
		void resetDatalogger();
		void enterCommandMode();
		void resetFileCounter();
		void newFile(String file);
		void readFile(String filename);


};
#endif
//----------------------------------------------------------------------------------------------
//Arduino file (part)
//----------------------------------------------------------------------------------------------
#include <Datalog.h>

Datalog datalog=Datalog(Serial1,115200); //can be Serial, Serial2, Serial3 depending on user

So the problem here is that the compiler is complaining about with the following message "Datalog.cpp:33: error: no matching function for call to ‘HardwareSerial::HardwareSerial()’ ", the 33 line is actually the declaration of the constructor (that i already posted) in the cpp file. I know that the problem is located on the way that i am declaring the HardwareSerial object. So the question is if this is possible and if it is, how is the correct way to do it.

Thanks

        typedef HardwareSerial serialPort; //here is the issue

What's with the typedef statement?

What i would like to do (if its possible) is to declare a public hardwareSerial object and initialize it according to the user's requirements when the class constructor is called, instead of setting to a specific serial port.

This doesn't make sense. If you are talking about other than an Mega, there is exactly one serial port. If you ARE writing this for a Mega, and want the user to indicate whether to use the existing Serial, Serial1, Serial2 or Serial3 instance, that's a different story. In any case, you should not be trying to CREATE a new instance of the HardwareSerial class.

So the question is if this is possible and if it is, how is the correct way to do it.

That isn't really the question, since you already have figured out that the answer to that question is no.

It's not exactly what you want, but in my OLED display library I'm passing a pointer to a Stream object in my constructor, so I can setup whichever serial port I want (hardware, or software) and then give it to my library object to use from them on.

@PaulS, Thanks for the reply. Indeed i am trying to create a library only for Mega.

That isn't really the question, since you already have figured out that the answer to that question is no.

Taken as granted that i should not create a new instance of the HardwareSerial class and referring to the above comment, you are saying that passing a selected Serial port to a Library's function is not possible in any way?

@extent, Thanks for the reply. That is a very interesting idea. Never thought about it. How do you declare the stream object?

SoftwareSerial mySerial(SOFT_RX, SOFT_TX);
G4D displaySoft(POWER_PIN,RESET_PIN,&mySerial);

#ifdef DEBUG
G4D display(POWER_PIN,RESET_PIN,&Serial1);
#else
G4D display(POWER_PIN,RESET_PIN,&Serial);
#endif

void setup(void)
{  
#ifdef DEBUG
	Serial1.begin(230400); 
#endif
	Serial.begin(115200); 
	mySerial.begin(9600);
//now you can send commands thru the display or displaySoft objects.
}

and the G4D constructor

  public:
    G4D(uint8_t pinPower, uint8_t pinReset, Stream * serialObj);

I use this to develop on a Mega and use Serial for debugging to the computer, when I compile for my 328 the serial display is hooked up to Serial instead of Serial1. Previously I was using software serial on an Uno to accomplish the same thing. This setup works with both boards interchangeably.

@extent, Thanks for the reply, :) I have tried to declare my object as Stream and to be more specific the object should be global in the library in order for all the function to be able to access it. Unfortunately due to my lack of knowledge i was unable to reach to a compiling result. :( Right now i am at work, ill try later to post my code in case someone figures out the bugs of my implementation.

Thanks again

I have tried to declare my object as Stream and to be more specific the object should be global in the library in order for all the function to be able to access it.

I don't think you mean global, and perhaps that is the source of the problem.

Any variable defined in the class body will be visible to all functions in that class. So, as long as the Stream pointer is defined in the header file, any function in the class can use it.

We do, however, need to see the code.

Sorry for the delay,
I 've been busy. :slight_smile: Anyways here is the code.

//Datalog.h
#ifndef Datalog_h
#define Datalog_h

#include "WProgram.h"
#include "Stream.h"


class Datalog
{   
	public:
		Stream *serialPort;	
		Datalog();
		void Start(long sped);
		void writedata(String msg);
		void appendFile(String file);
		void resetDatalogger();
		void enterCommandMode();
		void resetFileCounter();
		void newFile(String file);
		void readFile(String filename);				
};
#endif

//--------------------------------------------------------------------
//Datalog.cpp
/*********************************INCLUDES*************************************************/
#include "WProgram.h"
#include <Datalog.h>
#include "Stream.h"
/*********************************MACROS****************************************/
#define RSTLOG 32//OpenLog reset pin (pulling this line low will reset openlog

/*************************************************************************
*						Datalog(long sped)
*Description: Initializes the Serial communication with the Datalogger
*
*Arguments: long sped -> The speed selected
*
*Returns: nothing
*
*Notes: 
*************************************************************************/

Datalog::Datalog()
{}

void Datalog::Start(long sped)
{
	serialPort.begin(sped);
}

/*************************************************************************
*						appendFile(String file)
*Description: Appends the specified file or creates it if it doesn't exist.
*
*Arguments:String file -> The filename to open or create
*
*Returns: nothing
*
*Notes: 
*************************************************************************/
void Datalog::appendFile(String file){  
  delay(2000); //wait 2 sec for the data logger to initiate
  serialPort.println("append " + file); // send append command with the filename
  delay(100); //wait 100 ms to open the file
 }

.
.
.

Thanks for both your time and effort! :slight_smile:

Two questions.

  1. Where does the serialPort object get valued?
  2. Are you having a problem or needing help? Is there a question to be answered?

1) Where does the serialPort object get valued?

I am not quite sure what you mean, but if you are referring to where the object is initialized is done in the void setup function located in the sketch. If you mean where serialPort is used then you can see in the cpp file that a sample procedure exist (appendFile()) which uses that object as it would if that object was a common Serial, Serial1, etc.

2) Are you having a problem or needing help? Is there a question to be answered?

Yes i have a problem AND i need help. You see i am calling the library's serialPort object like this

//Arduino Sketch


Datalog datalog=Datalog();


void setup(){
  datalog.serialPort=&Serial1;
  datalog.Start(115200);
}

And the compiler says:

Datalog.cpp: In member function 'void Datalog::Start(long int)':
Datalog.cpp:37: error: request for member 'begin' in '((Datalog*)this)->Datalog::serialPort', which is of non-class type 'Stream*'
C:\Users\Xeon\arduino-0022\arduino-0022\libraries\Datalogger\Datalog.cpp: In member function 'void Datalog::appendFile(String)':
Datalog.cpp:41: error: request for member 'println' in '((Datalog*)this)->Datalog::serialPort', which is of non-class type 'Stream*'
Datalogger\Datalog.cpp: In member function 'void Datalog::writedata(String)':
Datalogger\Datalog.cpp:48: error: request for member 'print' in '((Datalog*)this)->Datalog::serialPort', which is of non-class type 'Stream*'
Datalogger\Datalog.cpp: In member function 'void Datalog::enterCommandMode()':
Datalog.cpp:61: error: request for member 'print' in '((Datalog*)this)->Datalog::serialPort', which is of non-class type 'Stream*'
Datalog.cpp: In member function 'void Datalog::resetFileCounter()':
Datalog.cpp:71: error: request for member 'println' in '((Datalog*)this)->Datalog::serialPort', which is of non-class type 'Stream*'
Datalog.cpp:72: error: request for member 'println' in '((Datalog*)this)->Datalog::serialPort', which is of non-class type 'Stream*'
Datalog.cpp: In member function 'void Datalog::newFile(String)':
Datalog.cpp:78: error: request for member 'print' in '((Datalog*)this)->Datalog::serialPort', which is of non-class type 'Stream*'
Datalog.cpp:79: error: request for member 'println' in '((Datalog*)this)->Datalog::serialPort', which is of non-class type 'Stream*'
Datalog.cpp: In member function 'void Datalog::readFile(String)':
Datalog.cpp:86: error: request for member 'print' in '((Datalog*)this)->Datalog::serialPort', which is of non-class type 'Stream*'
Datalog.cpp:87: error: request for member 'println' in '((Datalog*)this)->Datalog::serialPort', which is of non-class type 'Stream*'
Datalog.cpp:89: error: request for member 'available' in '((Datalog*)this)->Datalog::serialPort', which is of non-class type 'Stream*'
Datalog.cpp:90: error: request for member 'print' in '((Datalog*)this)->Datalog::serialPort', which is of non-class type 'Stream*'
Datalog.cpp:95: error: request for member 'flush' in '((Datalog*)this)->Datalog::serialPort', which is of non-class type 'Stream*'

So... the question now. What is wrong??? How this can be done???? :sweat_smile: :~ :cold_sweat:

I am currently writing a library that contains functions to operate the Openlog data logger. What i would like to do (if its possible) is to declare a public hardwareSerial object and initialize it according to the user's requirements when the class constructor is called, instead of setting to a specific serial port.

With this requirement, I'm not sure why serialPort is defined to be of type Stream *, instead of being defined to be of type HardwareSerial *.

Since the object in question IS a HardwareSerial instance, which has a begin(() method, which is derived from Stream, which does not have a begin() method, you would need to cast the serialPort object to a HardwareSerial instance, in order to use the begin method.

((HardwareSerial *)serialPort)->begin();

If serialPort were of the correct type, this would not be necessary.

I am not quite sure what you mean, but if you are referring to where the object is initialized is done in the void setup function located in the sketch.

How? It almost certainly is not being done correctly, since serialPort is a class member, and must be initialized somewhere in the (not shown?) class code.

Edit: I see, now, that serialPort is a public fieldof the class, so it is possible that the sketch CAN initialize the serialPort field. This is a bad design, though. The serialPort instance should be private, and there should be a method to initialize the instance.

What you want to do CAN be done, and you can get there.