Creating a custom class with Serial or Stream

Hello. I am working with GSM modem sim800 and want to create my custom library using classes. I have used TinyGSM library which worked fine but I am not able to follow it properly as it is too complicated and the library developers have been almost dead silent for the last couple of months.

I have come across this forum thread which talks about library with Serial and it has not been solved properly yet.

I am hoping someone might be able to help me here:

My custom_modem.cpp looks like:


#include "custom_modem.h"
#include "Arduino.h"

custom_modem::custom_modem(Stream& serial)
{
    _serial = serial


void custom_modem::send_AT_command(String command)
{
    _serial.write(command);

     while (_serial.available())
       {
          char c = _serial.read();
          Serial.print(c);
       }
}


and .h file:



#ifndef custom_modem_h
#define custom_modem_h

#include <Arduino.h>
#include <Stream.h>

 class custom_modem
 {
   public:
      custom_modem(Stream& serial);
      void send_AT_command(String command);

   private:
       
      Stream& _serial;
 };


 #endif

in the arduino .ino file I am creating a class object:

#define SerialAT  Serial1
custom_modem modem(SerialAT);

The errors I am getting:

sketch\src\custom_modem.cpp: In constructor 'custom_modem::custom_modem(Stream&)':

sketch\src\custom_modem.cpp:5:1: error: uninitialized reference member in 'class Stream&' [-fpermissive]

 custom_modem::custom_modem(Stream& serial)

 ^

In file included from sketch\src\custom_modem.cpp:2:0:

sketch\src\custom_modem.h:16:15: note: 'Stream& custom_modem::_serial' should be initialized

       Stream& _serial;

               ^

sketch\src\custom_modem.cpp: In member function 'void custom_modem::send_AT_command(String)':

sketch\src\custom_modem.cpp:13:26: error: no matching function for call to 'Stream::write(String&)'

     _serial.write(command);

                          ^

In file included from C:\Users\Lukas\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\cores\esp32/Stream.h:26:0,

                 from C:\Users\Lukas\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\cores\esp32/Arduino.h:147,

                 from sketch\src\custom_modem.h:5,

                 from sketch\src\custom_modem.cpp:2:

C:\Users\Lukas\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\cores\esp32/Print.h:61:20: note: candidate: virtual size_t Print::write(uint8_t)

     virtual size_t write(uint8_t) = 0;

                    ^

C:\Users\Lukas\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\cores\esp32/Print.h:61:20: note:   no known conversion for argument 1 from 'String' to 'uint8_t {aka unsigned char}'

C:\Users\Lukas\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\cores\esp32/Print.h:62:12: note: candidate: size_t Print::write(const char*)

     size_t write(const char *str)

            ^

C:\Users\Lukas\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\cores\esp32/Print.h:62:12: note:   no known conversion for argument 1 from 'String' to 'const char*'

C:\Users\Lukas\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\cores\esp32/Print.h:69:20: note: candidate: virtual size_t Print::write(const uint8_t*, size_t)

     virtual size_t write(const uint8_t *buffer, size_t size);

                    ^

C:\Users\Lukas\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\cores\esp32/Print.h:69:20: note:   candidate expects 2 arguments, 1 provided

C:\Users\Lukas\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\cores\esp32/Print.h:70:12: note: candidate: size_t Print::write(const char*, size_t)

     size_t write(const char *buffer, size_t size)

            ^

C:\Users\Lukas\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\cores\esp32/Print.h:70:12: note:   candidate expects 2 arguments, 1 provided

exit status 1
Error compiling for board ESP32 Dev Module.

I want to create a class object and then use this object with other class functions that I am going to create such as sending AT commands to the module, waiting for the response, sending USSD message and etc. Hoping someone can clarify how to properly create a class using Serial or Stream

Try
private:
Stream* _serial;
and in the constructor code use
_serial = *serial;
You will then need to use
_serial->print .. etc

You should use an initializer list for the reference.

custom_modem::custom_modem(Stream& serial) : _serial(serial) {}

First of all, thanks both for the responses. I have ditched the idea of using Stream and just Using Hardware serial for now as this is much more simple..
My cpp

#ifndef custom_modem_h
#define custom_modem_h

#include <Arduino.h>
#include <HardwareSerial.h>

#define MODEM_TX             27
#define MODEM_RX             26

 class custom_modem
 {
   public:
      //custom_modem(HardwareSerial* serial);
      custom_modem(HardwareSerial& serial);
      void start_modem();
      String send_AT_command();

   private:
      HardwareSerial _port;
 };


 #endif

and header file:


#include "custom_modem.h"
#include "Arduino.h"
#include "String.h"

/*
custom_modem::custom_modem(HardwareSerial* serial)
{
    _port = serial;
    _port(serial);
}
*/


custom_modem::custom_modem(HardwareSerial& serial): _port(serial)
{ 

}


void custom_modem::start_modem(){
    _port.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
}


String custom_modem::send_AT_command()
{
    String return_message; // Crate a string to store a return message
    _port.write("AT\n\r"); // Write an "AT" message to serial device. Expecting to receive "OK"
    delay(1);
     while(_port.available())
       {
          char c = _port.read(); // Read character at a time
          return_message.concat(c); // append a string with the character
       }
    return return_message;
}

This seems to work fine!.

I am not big expert with pointers, I have 2 questions.

1. What is the difference initialising a object using a pointers versus using a reference?

custom_modem::custom_modem(HardwareSerial& serial) : _port(serial) {}

vs

custom_modem::custom_modem(HardwareSerial* serial){
_portserial = serial
}

2.
And how does this object declaration works?, I have never seen this syntax:

custom_modem::custom_modem(HardwareSerial& serial) : _port(serial) {}

https://en.cppreference.com/w/cpp/language/constructor

  1. pointers can be assigned to, references can only be initialised.

  2. look up initializer lists

https://www.cplusplus.com/reference/initializer_list/initializer_list/

Excellent reading material from both of you... Thanks a lot

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