Trying to create a class that talks to Serial

Folks,
I am writing some code where I am trying to create a DriveTrain class. This DriveTrain class will contain two private members: controllerFront and controllerRear, both of which will be instances of the RoboClaw class. The problem is that in order for the RoboClaw classes to do their thing, and for the DriveTrain class to initialize serial, it needs to invoke:

Serial1.begin(38400);

Problem is Serial1 is not in scope inside DriveTrain.cpp. So, I want to pass the Serial1 instance on the DriveTrainā€™s constructorā€¦ but I canā€™t find the exact data type, nor can I find the header file in which the data type is defined. I have been through the Wiring programming reference and the Spark guides, but thereā€™s very little that tells me where all the ā€˜injected magicā€™ in the .ino file (like Serial, Serial1, etc) comes from.

Can someone help guide a n00b to properly encapsulating the serial controller logic I need to write?

OK, so I have discovered that if I include application.h, I get access to the USARTSerial class. I also discovered that writing Java by day and baremetal C++ by night is a bit like rollerskating with skates on your feet in the morning and on your hands at nightā€¦

So, I am trying to pass a reference to the Serial1 object into the DriveTrain class which in turn is passed to 2 different instances of the RoboClaw (motor controller) classesā€¦ Hereā€™s what that chain looks like:

DriveTrain driveTrain(&Serial1);

And in my .ino fileā€™s setup() method:

driveTrain.begin();

DriveTrain.cpp:

   #include "DriveTrain.h"

DriveTrain::DriveTrain(USARTSerial *serialBus) 
{
    serial = serialBus;
    frontController = new RoboClaw(0x80, serialBus);
    rearController = new RoboClaw(0x81, serialBus);
}

bool DriveTrain::begin()
{
    serial->begin(38400);
}

RoboClaw.cpp:

#include "RoboClaw.h"

RoboClaw::RoboClaw(uint8_t deviceaddress, USARTSerial *serialBus) {
    address = deviceaddress;
    serial = serialBus;
}

This all compiles, but it feels like Iā€™m doing something wrong here. In application.h, Serial1 is defined thusly:

extern USARTSerial Serial1;

Maybe Iā€™m just horribly underconfident given my lack of recent exposure to C++ā€¦ does this look like the right way to do this? Am I violating any rules, standards, practices? Is something going to blow up horribly?

UPDATE: So Iā€™ve verified that the above code works. But, I still remain skeptical. This crap canā€™t possibly have worked on the first try, so I feel like Iā€™ve done something stupid.

Hi @ZombieKiller

What you are doing will work fine but may be limiting the future, particularly on other platforms. I would have the pointer be of type Stream which is the Arduino Wiring class that the serial classes inherit from. Stream inherits from Print which brings a lot of output methods to the party, but Stream defines the interface you want to use, with available() read() peek() and flush() all virtual.

You are using the ā€œpass a pointerā€ method which is fineā€“there is also a pass by reference method which would also work. This is mostly a style issue with good points on both sides.

@bko Thanks for the tipsā€¦ I hadnā€™t ever considered running the code on anything other than the Spark Core, but I guess it kind of makes sense to make the libraries as flexible as possible. Iā€™ll refactor and see if that compiles/works.

Even on Spark, the USB serial class and USART serial classes do not have a common abstract class other than Stream, so this should let you do things like redirect the serial stream to a terminal program on your PC for debugging, while using the USART class directly will not allow that.

Good luck and have fun! Sounds like a cool project.

1 Like

Hmm, tried to drop everything to the lower common denominator of Stream, but thereā€™s no begin(baudRate) method on Stream, so Iā€™m unsure where to go from thereā€¦ For now Iā€™ve just moved the call to begin outside my DriveTrain class and into my .ino fileā€™s setup() function.

1 Like

Itā€™s alive!

2 Likes