HardwareSerial or NewSoftSerial in argument

Hi

I’m using C328R cam library, but this lib hardcodes Serial for sending data on uart (Serial.print(), Serial.read()…)
However my cam is not on uart, so i would prefer to use NewSoftSerial

So i’m finding a way to make this lib generic.
For example, would be nice to create an object for the cam by giving it as an argument the object O to use for doing O.print(), O.read, O.available() and so on

Any idea if this is possible to do that ?

Otherwise, i’ll have to hardcode NewSoftSerial in this lib instead of HardwareSerial…
(and i don’t know either how to do this…)

Thanks

Maybe something like this: ?

class MyClass{ public*:* MyClass( Print* p){ printer = p; }; inline void debug() { printer->println("test"); } private*:* Print* printer; };

MyClass printMe = MyClass( &Serial );

void setup(){ Serial.begin(9800); printMe.debug(); }

void loop(){}

Hum you're sure it would work ?

Because you use Print for the class, it doesn't contain available(), read()

In fact if i want to use NewSoftSerial, I should call MyClass(&NewSoftSerial) and if i want to use Serial, I should call MyClass(&HardwareSerial)

But NewSoftSerial and HardwareSerial are 2 different classes

This is an interesting discussion. It does suggest the idea that HardwareSerial and NewSoftSerial should ultimately inherit from the same "Serial" base class (which in turn derives from Print).

But as they don't, I think the best strategy is probably to embed a reference to a NewSoftSerial object in your class. (You could probably accomplish the generic goal with a template, but the syntax may get tricky.)

To embed a reference, you'd declare a member like this:

class MyClass
{
  private:
  NewSoftSerial &nss;
  ...

Then your constructor would look something like this:

  public:
  MyClass(NewSoftSerial &_nss) : nss(_nss) {} // initialize the reference here
  ...

Then replace all the references in your library of Serial with nss. To create an object, you'd do something like this:

NewSoftSerial nssconnection(3, 2);
nssconnection.begin(4800);
MyClass myclass(mynss);

// use myclass here

Mikal

Building upon the idea of mikalhart you could also overload the constructor to accept both, a HardwareSerial& AND a SoftwareSerial&.

When the user then uses your class the compiler will automatically pick the correct constructor and fill the correct reference. This does however, demand a lot of if-statements in your code.

You could ofcourse also write your own adapter class (say MySerial) which you construct with either hwSerial or softSerial and which translates all calls you use in your lib to either hardware or softserial calls (depending on which was supplied duing construction). This is probably the most elegant manner.

E.g.:

class MyClass
{
public:
   MyClass(SoftwareSerial& serial);
   MyClass(HardwareSerial& serial);

private:
   SoftwareSerial* m_pSoftSerial;
   HardwareSerial* m_pHardSerial;

// Further code.
}

MyClass::MyClass(SoftwareSerial& serial): m_pSoftSerial(&serial), m_pHardSerial(0)
{
}

MyClass::MyClass(HardwareSerial& serial): m_pSoftSerial(0), m_pHardSerial(&serial)
{
}

MyClass::doStuff()
{
   if(m_pSoftSerial)
   {
      m_pSoftSerial->read......
   }
   else
   {
      m_pHardSerial->read......
   }
}

I know it's not exactly what you're looking for, but some my find this helpful.

I've been working on a number of projects lately that will have an Arduino in stand-alone mode talking to a serial interface to control external devices and read status information. So my stand-alone boards are built similarly to the old serial Arduino with a MAX232 doing the RS-232 conversion to the hardware serial pins (0,1).

During development and debugging I got tired of repeatedly disonnecting my external device, reconnecting to the computer serial port to program, reconnecting to test, etc. It also makes debugging a pain when you can't do diagnostic Serial.prints and watch them in the serial monitor.

So I started using compiler directives to "redirect" the serial port of my external device interface. Here's some example code that uses NewSoftSerial for the device when in development, and switches to hardware serial when in production.

// Example using compiler directives to "switch" between
// hardware and software based serial

#include "WProgram.h"

#define DEVELOPMENT_MODE true  // Set to "false" for production

#if DEVELOPMENT_MODE
// Use "software-based" serial to communicate with the external interface.
// This allows the hardware serial to be used for debugging and
// remain connected to the computer for program upload.
#include "NewSoftSerial.h"
#define SerialPort nss
NewSoftSerial nss(2,3);
#else
// For "production" mode, the external interface will be connected to
// the hardware serial pins.
#define SerialPort Serial
#endif


void setup() {
  SerialPort.begin(9600);
  SerialPort.println("Hello World!");
}

void loop() {
}

So instead of referencing "Serial" in my code, I always use "SerialPort" to communicate with the device. When DEVELOPMENT_MODE is true, SerialPort is connected to NewSoftSerial. When false, hardware serial is used.

The #include "WProgram.h" is important. It prevents the compiler from optimizing out the hardware serial library because it doesn't see any references to it. If you use the hardware serial for debugging, then you won't need to include this (but it doesn't hurt anything to be there).

Hopefully someone will find this useful.

Very nice, etracer. This is a useful technique.

Thanks,

Mikal