How to attach software serial to a library

I am building a hardware module that communicates over serial. I am writing a library for it, but I would like to allow the use of "software serial" to control it and I am trying to figure out how to "attach" it in my library. Do I simply provide a function that creates a pointer to the softwareserial library functions? Are there any examples of other libraries that do this?

Thanks in advance!

What chip is running the hardware module?

Mark

If you want your library to be configured with an instance of SoftwareSerial then I suggest you either accept that as a constructor argument (if your library is implemented as a class) or provide a begin() function to install the SoftwareSerial instance to be used.

Assuming that your using an ATMega chip then it should be just an "include".

Mark

I am not sure what you are asking, exactly, Holmes. The library is for an Arduino. Whatever is on the other end just accepts serial commands, I'm not sure that really matters.

The idea is to make a library to control the hardware module over serial, but I don't want to lock it to using only the hardware serial. I would like to allow the library to use softwareserial instead if preferred. I don't want to lock into either, I just want to figure out how to allow it if the user wants to do that.

I was thinking along the lines of how printf works where you just specify an output. As I understand, you just pass a pointer to a buffer with that. After initializing it without your output device, the rest of the library is just transparent.

Peter,

In your suggestion, I would need to provide conditions that didn't break things if the user is not using the software serial, right? There is no way to do it like a printf library?

OK, sorry I read your post as meaning you where building/designing the hardware module.

Mark

Retroplayer:
In your suggestion, I would need to provide conditions that didn't break things if the user is not using the software serial, right? There is no way to do it like a printf library?

Well, there are plenty of ways to deal with alternative configurations. If this is intended to act as a debug/trace stream then I'd suggest that the output should only occur when the output destination is specified. If it's something that is necessary for the operation of the library then you could generalise the library to access a Stream rather than tying it to be a hardware or software serial port.

holmes4:
OK, sorry I read your post as meaning you where building/designing the hardware module.

Mark

Oops, I reread my OP and it does sound like that. My apologies for the confusion.

Peter,

The module is an MP3 module from MDFLY. You send it various serial commands to play files, stop, change folders, pause, etc... there are two commands that return something, but typically the module is quite during operation, only using a BUSY status signal.

So, the serial part of it is important to the function of the module. I am just trying to create a wrapper for the module so you can call something like mp3.play(10) and it will play the tenth MP3 file. This is really simple to do if I were just using the arduino serial port, but I would like to keep that port free if possible and use a software serial or one of the other ports on the mega if used on that.

I just need to determine how to specify which port to use. Maybe I am doing the whole thing wrong and there is a better way?

Does that make sense?

nm, I don't think software serial is going to work anyway. Apparently you can't send serMP3.write(0); It compiles with an error that it is "too ambiguous." That works with the hardware serial, though. A command of 0 is needed to tell the module to play a random file from the root folder. Now, how it distinguishes that command, I don't know.

Don't lose hope yet, read this post about the write(0):

liudr:
Don't lose hope yet, read this post about the write(0):

How to update codes and libraries for arduino 1.0 | LiuDr Electronic Solutions LLC Official Blog

Thanks! Weird though, because I only get an error when I try to do that with the softserial. The regular serial doesn't complain.

But that suggestion worked...

So back to trying to figure out how to redirect the output. I am hoping for an example somewhere...

I don't think that HardwareSerial and SoftwareSerial have a common base class that supports bidirectional I/O. (They do have a common superclass that provides an input stream ,but I assume you need output too.

In that case I would overload the constructor/configuration function to accept either a hardware or software serial object, store whichever is provided within the library (as an instance member or static variable, depending how your library is implemented) and in all the places where your library needs to read or write to it, do that via a utility function that checks which type of serial object you're using and does the read/write to it. It means a bit of indirection within the library, but unless you're particularly performance critical I wouldn't expect that to be an issue. (If it is an issue, there are ways round it but at the cost of more code and complexity.)

Peter,

Thanks again for your help! Any chance you have an example of doing something like this available so that I can understand it? I don't expect you to write something up just for me, but if you know of a similar example, it would help me understand how to implement what you are suggesting. I understand the terms and the concepts you are talking about, but I don't have enough experience with C to figure out how to implement it without seeing an example.

The module is locked at 4800 baud, so the speed isn't too high. All commands are single bytes between 0x00 and 0xFF. So, the demand is not really high. There is only one command that actually returns something, which is a count of folders present on the card (just one byte) and the datasheet says it is not available in new modules anyway (it works on mine.)

So you could easily get away with only a TX pin and send commands.

Hmm... maybe some bit-banging, shift out or something else would be more appropriate. Then I don't need to worry about this.

The module expects 4800,8,1 formatted serial, so I don't think it will be super-simple, but perhaps I could copy-pasta some code over from the softwareserial library with some modifications and tie this to a pin rather than trying to redirect output.

What do you thik?

Is your library class based, or plain old 'C'?

I am just beginning, so I could go either way. But I plan to use class based for the simplicity of using it. I have written only one library so far and I started with a "close-enough" example and modified it heavily. It was for a custom 3 wire interface to an IC. I modified a softwareTWI library for that (3rd pin was just chip select.)

So, that is the extent of my experience so far. Doing anything advanced, I would need to see some examples because I am not familiar with what the code looks like.

Retroplayer:

liudr:
Don't lose hope yet, read this post about the write(0):

How to update codes and libraries for arduino 1.0 | LiuDr Electronic Solutions LLC Official Blog

Thanks! Weird though, because I only get an error when I try to do that with the softserial. The regular serial doesn't complain.

But that suggestion worked...

So back to trying to figure out how to redirect the output. I am hoping for an example somewhere...

Which IDE version are you using? I wrote that post for 1.0 and things may have been changed. I'll check the core code and provide an update.

Retroplayer:
I am just beginning, so I could go either way. But I plan to use class based for the simplicity of using it. I have written only one library so far and I started with a "close-enough" example and modified it heavily. It was for a custom 3 wire interface to an IC. I modified a softwareTWI library for that (3rd pin was just chip select.)

So, that is the extent of my experience so far. Doing anything advanced, I would need to see some examples because I am not familiar with what the code looks like.

Let's see your code.

Personally I prefer the class-based approach, since it results in a cleaner isolation IMO.

In that case you can pass in the serial object to the constructor for your library's main class. Provide two constructors, one accepting a HardwareSerial and the other accepting a SoftwareSerial. Have a member variables to hold a pointer to each of them, set the unused one to null. Provide a method to read from the input stream which tests which serial object is set, and reads from it. Similarly provide a method to write to whichever serial object was set. It's a bit messy, but I think this is the best you can reasonably get given the existing HardwareSerial and SoftwareSerial implementations. (No kudos for the people who designed this part of the Arduino API.)

liudr:
Let's see your code.

Which code? My modified TWI library (for a different chip) or what code I have for the MP3 module already? Right now, it is just a sketch directly using the softserial library. I haven't started to assemble it into a library yet because this part (redirecting output) seemed like the most important part.

PeterH:
Personally I prefer the class-based approach, since it results in a cleaner isolation IMO.

In that case you can pass in the serial object to the constructor for your library's main class. Provide two constructors, one accepting a HardwareSerial and the other accepting a SoftwareSerial. Have a member variables to hold a pointer to each of them, set the unused one to null. Provide a method to read from the input stream which tests which serial object is set, and reads from it. Similarly provide a method to write to whichever serial object was set. It's a bit messy, but I think this is the best you can reasonably get given the existing HardwareSerial and SoftwareSerial implementations. (No kudos for the people who designed this part of the Arduino API.)

You're right, that is probably the best I can do. Of course, I would need to go further and provide a way to use the other hardware serial ports on a Mega. I am beginning to think the simplest and cleanest way may be to pull over chunks of the softwareserial library and just hardwire it into my own code. Since the module will only work at 4800bps and only realistically need a write() routine, I don't really need many of the extras in the library anyway.