Your current problem is that the USB Serial interface of the Leonardo isn't a hardware serial device, it's a CDC/ACM device, and the class for that isn't HardwareSerial, it's Serial_.
So you can't pass it to a function that expects a HardwareSerial.
What you should be using, instead, is the Stream class. That will allow you to pass any object that is based on the Stream class, such as HardwareSerial, Serial_, Client, etc. Many different things, including serial and networking protocols, use Stream as their base class.
It does have the down side, though, that you have to initialize the Stream objects in your sketch (that is, do the Serial.begin(...) and Serial1.begin(...) in your sketch not your class) because the Stream class doesn't have the concept of a baud rate, and so no begin(baud) function.
This is what I mean:
class Esp8266 {
public:
Esp8266();
void begin(Stream &wifiCom, Stream &debugCom);
private:
Stream *_wifiCom;
Stream *_debugCom;
};
Esp8266::Esp8266() {
}
void Esp8266::begin(Stream &wifiCom, Stream &debugCom) {
_wifiCom = &wifiCom;
_debugCom = &debugCom;
while (!_debugCom) {
;
}
}
Esp8266 esp;
void setup() {
Serial.begin(115200);
Serial1.begin(115200);
esp.begin(Serial, Serial1);
} // end of setup
void loop() {
} // end of
Note, as well, my use of pass-by-reference (Stream &whatever) so you don't have to pass a pointer in your begin function. Also notice the use of unique variable names in the class (I always prefix my member variables with _
) so you don't have to keep putting this->
in everywhere.
To be able to move the .begin()
function inside your class you will have to use both HardwareSerial
and Serial_
object types within your class. There's two ways this may be done.
First is dynamic casting:
void Esp8266::begin(Stream &wifiCom, Stream *debugCom) {
_wifiCom = &wifiCom;
_debugCom = &debugCom;
HardwareSerial *hard;
Serial_ *cdc;
if (hard = dynamic_cast<HardwareSerial*>(_wifiCom)) {
hard->begin(115200);
} else if (cdc = dynamic_cast<Serial_*>(_wifiCom)) {
cdc->begin(115200);
}
if (hard = dynamic_cast<HardwareSerial*>(_debugCom)) {
hard->begin(115200);
} else if (cdc = dynamic_cast<Serial_*>(_debugCom)) {
cdc->begin(115200);
}
}
I haven't tested this, and I don't know if the Arduino's cut-down C++ library is even capable of it, but it's worth a try.
The other method is to overload the .begin()
function of your class with multiple versions that take different parameters:
void Esp8266::begin(Serial_ &wifiCom, HardwareSerial *debugCom) {
_wifiCom = &wifiCom;
_debugCom = &debugCom;
wifiCom.begin(115200);
debugCom.begin(115200);
}
void Esp8266::begin(HardwareSerial &wifiCom, HardwareSerial *debugCom) {
_wifiCom = &wifiCom;
_debugCom = &debugCom;
wifiCom.begin(115200);
debugCom.begin(115200);
}
void Esp8266::begin(HardwareSerial &wifiCom, Serial_ *debugCom) {
_wifiCom = &wifiCom;
_debugCom = &debugCom;
wifiCom.begin(115200);
debugCom.begin(115200);
}
You're still storing them internally as Stream
objects in all cases, but within the begin()
function itself you also have them available as their child classes. It does mean you have duplicate code copied between the different versions of begin()
. You could modularize it a little more though by moving the duplicated code into functions which would only need to be duplicated twice, not three times - one to act on a single Serial_
object and one to act on a single HardwareSerial
object:
void Esp8266::initSerial(Serial_ *ser) {
ser->begin(115200);
}
void Esp8266::initSerial(HardwareSerial *ser) {
ser->begin(115200);
}
void Esp8266::begin(Serial_ &wifiCom, HardwareSerial *debugCom) {
_wifiCom = &wifiCom;
_debugCom = &debugCom;
initSerial(&wifiCom);
initSerial(&debugCom);
}
... etc x3 ...