Define Serial in sketch and use it in a library

Good afternoon.
I'm starting make an own libraries, because my projects begins be confused. But I don't understand them fully.
I need define right Serial port in a ino project and then use it in my library for print log messages.
Could You help me how to do it?

you can pass Serial, Serial1, Serial2 or Serial3 as an argument to a constructor (?)

You can pass a pointer to the Stream class, then the code will work with both hardware serial ports and software serial.

So always over class, defined in header file ? And after include header will be accessable in sketch. And cpp take it from header too. Undersand I good ?

So i'm not a winner. :roll_eyes:
As my first trial work with classes it ends poorly.
I think, that I must make an object with parent class Hardwareaserial to have the inheritance as a Serial objects and then define this object as Serial0, 1...
Think I good ?

Could You show me any example ?

A poorly written example:

sketch file:

#include "testclass.h"

TestClass tc;

void setup() {
  Serial.begin(9600);
  tc.begin(Serial);
  tc.prnt("hello\n");
}

void loop() {
}

testclass.h file:

#ifndef TESTCLASS_H
#define TESTCLASS_H

#include <Arduino.h>

class TestClass
{ 
  public:
    void begin(Stream& s) {
      stream = &s;
    }

    size_t prnt(const char* text){
      return stream->print(text);
    }

  private:
    Stream* stream;

};

#endif //TESTCLASS_H
1 Like

I finally had a time to work on mroject again and Your solution works perfectly! :grinning:
Thank You much David.
I did some modifications and extensions and now I use print and more functions in sketch and other my libraries too.
Thank You !

You can also maintain a reference to the Stream object. Then you won't have to switch to pointer notation inside the class:

Main .ino:

#include "testclass.h"

TestClass tc(Serial);

void setup() {
  Serial.begin(115200);
  tc.prnt("hello\n");
}

void loop() {
}

testclass.h

#ifndef TESTCLASS_H
#define TESTCLASS_H

#include <Arduino.h>

class TestClass
{
  public:
    TestClass(Stream &s) : stream(s) {}

    size_t prnt(const char* text) {
      return stream.print(text);
    }

  private:
    Stream &stream;
};

#endif //TESTCLASS_H
1 Like

Shorter == better. :slight_smile:
Thank You!

Now I must define all functions for this port as a"println, available, read..."
Is possible transfer anyhow all thes functions for stream to this "port" class ?
Or straight set this class as an member of stream ?

Perhaps using inheritance. Compiles but untested:

main.ino:

#include "Arduino.h"
#include "testclass.h"

TestClass tc(Serial);

void setup() {
  Serial.begin(115200);
  tc.println("hello");
}

void loop() {
}

testclass.h:

#ifndef TESTCLASS_H_
#define TESTCLASS_H_

#include <Arduino.h>

class TestClass: public Stream {
public:
	TestClass(Stream &s) : stream(s) {
	}

	virtual ~TestClass() {
	}

	virtual size_t write(uint8_t u) {
		return stream.write(u);
	}

	virtual int available() {
		return stream.available();
	}

	virtual int read() {
		return stream.read();
	}

	virtual int peek() {
		return stream.peek();
	}

private:
	Stream &stream;
};

#endif /* TESTCLASS_H_ */

Not works. Gives me an message "cannot declare variable 'tc' to be of abstract type 'TestClass'" ??
But works this:

class TestClass
{
public:
   TestClass(Stream &s) : stream(s) {}
   size_t print(String Text){
      return stream.print(Text);
   }
   size_t println(String Text){
      return stream.println(Text);
   }
   char read(){
      return stream.read();
   }
   String readStringUntil(char Char){
      return stream.readStringUntil(Char);
   }
   bool available(){
      return stream.available();
   }
private:
   Stream &stream;
};

The code I posted in #11 compiles fine for me.

May be an ESP32 issue ...?

Yes, ESP32 (which you did not state that you're using) requires flush() to also be implemented. This is clearly stated in the compiler error message. That's why you should post complete error messages, not your paraphrased version of them:

Arduino: 1.8.15 (Windows 10), TD: 1.55, Board: "Adafruit ESP32 Feather, 80MHz, 921600, None, Default"

sketch_jan10d:4:11: error: cannot declare variable 'tc' to be of abstract type 'TestClass'

 TestClass tc(Serial);

           ^~

In file included from C:\Users\TR001221\AppData\Local\Temp\arduino_modified_sketch_462870\sketch_jan10d.ino:2:

C:\Users\TR001221\AppData\Local\Temp\arduino_modified_sketch_462870\testclass.h:6:7: note:   because the following virtual functions are pure within 'TestClass':

 class TestClass: public Stream {

       ^~~~~~~~~

In file included from C:\arduino-1.8.15\portable\packages\esp32\hardware\esp32\2.0.1\cores\esp32/Arduino.h:160,

                 from C:\Users\TR001221\AppData\Local\Temp\arduino_modified_sketch_462870\sketch_jan10d.ino:1:

C:\arduino-1.8.15\portable\packages\esp32\hardware\esp32\2.0.1\cores\esp32/Stream.h:51:18: note: 	'virtual void Stream::flush()'

     virtual void flush() = 0;

                  ^~~~~

exit status 1

cannot declare variable 'tc' to be of abstract type 'TestClass'



This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Updated class declaration (compiles for ESP32):

#ifndef TESTCLASS_H_
#define TESTCLASS_H_

#include <Arduino.h>

class TestClass: public Stream {
public:
  TestClass(Stream &s) : stream(s) {
  }

  virtual ~TestClass() {
  }

  virtual size_t write(uint8_t u) {
    return stream.write(u);
  }

  virtual int available() {
    return stream.available();
  }

  virtual int read() {
    return stream.read();
  }

  virtual int peek() {
    return stream.peek();
  }

  virtual void flush() {
    stream.flush();
  }

private:
  Stream &stream;
};

#endif /* TESTCLASS_H_ */
1 Like

Works! Thank You! :grinning:
Yes, I'm sorry.
I don't thought in first time, that here can be any differences.
This necessity is based in Print.h library ?
2022-01-09T23:00:00Z Correction: Stream.h

Like an author, have You any Idea how to name this h file ?
For example: SerialPortAlias.h

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.