Definition and type of object Serial

Now this might have been asked before but because of the numerous update I want to double check. I am writing a custom library for communication between Dynamixel xl320 servos and Arduino Mega. I want to use all instances Serial1, Serial2 and Serial3 corresponding to the hardware ports on the board.

Where are these defined? Which headers I need to include in my library? More importantly what is the name of their class? I want to be able to declare a pointer or reference to each Serial so that I can make my library work for any Serial port. To be able to do that, though, I need to specify a type for the pointer.

While on the subject I would like to ask another question. Some people suggested that it is not a good idea to use functions like Serial.read() and Serial.write() directly in a custom made library. As far as I know it would not make any difference to the compiler where I use the functions as long as I include the appropriate headers. Does anyone have experience with that and is it indeed safe?

HardwareSerial?

As far as I know it would not make any difference to the compiler where I use the functions as long as I include the appropriate headers.

As long as you are CERTAIN that the Serial, Serial1, Serial2, and Serial3 instance have been created before you try to use them, you are free to use them anywhere.

naikin:
Now this might have been asked before but because of the numerous update I want to double check. I am writing a custom library for communication between Dynamixel xl320 servos and Arduino Mega. I want to use all instances Serial1, Serial2 and Serial3 corresponding to the hardware ports on the board.

Where are these defined? Which headers I need to include in my library? More importantly what is the name of their class? I want to be able to declare a pointer or reference to each Serial so that I can make my library work for any Serial port. To be able to do that, though, I need to specify a type for the pointer.

If I’m understanding you correctly, this may be what you need:

static Stream *_stream_ptr; // global stream pointer

void openit (Stream &str)
{
    _stream_ptr = &str; // equate "stream pointer" to serial device
}

void sendit (const char *string)
{
    for (int x = 0; x < strlen (string); x++) {
        _stream_ptr->write (string[x]); // same as Serial.write()
    }
}

void setup (void)
{
    Serial.begin (115200);
    Serial1.begin (9600);

    openit (Serial); // setup stream pointer
    sendit ("Hello there\n"); // same thing as Serial.print ("Hello there\n")

    openit (Serial1); // now we point to Serial1
    sendit ("Hello there serial port 1\n"); // same code now talked to Serial1
}

void loop (void)
{
    // nothing
}

If this isn’t what you mean, let me know (with a more detailed description) and I’ll try to help.

(edit to add): For serial reading, do it the same as if you were using “Serial” directly… that is something like

if (_stream_ptr->available()) {
    return _stream_ptr->read();
}

Also, look at this little library I wrote that uses the same technique… may be of help:

Stdinout library on GitHub

Hello and welcome,

Here is another little example, maybe useful:

const Stream * streams[] = { &Serial, &Serial1, &Serial2, &Serial3 };

template <typename T> void printToStreams( T val );
template <typename T> void printToStreams( T val )
{

  Stream * stream;
    
  for ( uint8_t i = 0; i < sizeof( streams ) / sizeof( Stream * ); i++ )
  {
    stream = (Stream *) streams[ i ];
    stream -> print( val );
  }
}

Using function printToStreams will print to all streams defined in the “streams” array.

guix:
Hello and welcome,

Here is another little example, maybe useful:

const Stream * streams[] = { &Serial, &Serial1, &Serial2, &Serial3 };

template void printToStreams( T val );
template void printToStreams( T val )
{

Stream * stream;
   
 for ( uint8_t i = 0; i < sizeof( streams ) / sizeof( Stream * ); i++ )
 {
   stream = (Stream *) streams[ i ];
   stream → print( val );
 }
}




Using function printToStreams will print to all streams defined in the "streams" array.

Hey that’s clever! I like that idea.

I think though that the OP was looking for a way to pass any Serial[n] object to a common function or functions.

By the way, did you know that this can also be done with LiquidCrystal and other character based code?

All that’s necessary is to do two things:

(1) Change

[b]    class LiquidCrystal : public Print {
...to...
    class LiquidCrystal : public Stream {

...in the header file and:

(2) Add dummy functions for:
    available ();
    peek ();
    read ();
    flush ();[/b]

When I use my “Stdinout” library, I then can simply do this:

    STDIO.open (Serial);
    fprintf (stdout, "This goes to the serial port!\n");

    STDIO.open (LCD); // of course LCD was instantiated up top as usual
    fprintf (stdout, "This prints on the LCD");

It’s very handy to use Printf to send a formatted line of text to a device rather than building it up piece by piece using a bunch of XXX.print() calls.

BTW, I noticed you have a link to info for enabling floating point support in the IDE. It won’t work in the older IDE, but it’s a simple matter to add a checkbox in “Preferences” and then use the true/false value in the Preferences file to send (or not) the extra strings to the compiler to use floating point.

(click pic for full size)
preferences.jpg

Thanks a lot guys. Stream is the class I am looking for.

To use it in my library I have to include Arduino.h, right?

PaulS:
As long as you are CERTAIN that the Serial, Serial1, Serial2, and Serial3 instance have been created before you try to use them, you are free to use them anywhere.

I had a look at the github(https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/HardwareSerial1.cpp) and it seems like the instances are created at the very beginning and I should not worry about this, right?

it seems like the instances are created at the very beginning and I should not worry about this, right?

At the very beginning of what? You can not know what order constructors will be called in. If you assume, in your constructor, that the HardwareSerial constructor has already been called, you might get away with it. Or, you might not. Debugging such an assumption is a nightmare.

naikin:
Thanks a lot guys. Stream is the class I am looking for.

To use it in my library I have to include Arduino.h, right?

I had a look at the github(https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/HardwareSerial1.cpp) and it seems like the instances are created at the very beginning and I should not worry about this, right?

You can either include Arduino.h or if you need just serial support, HardwareSerial.h . I’m not sure, though, if HardwareSerial depends on anything included in Arduino.h, so it’s probably best to use Arduino.h instead (because HardwareSerial is included by it and unused code won’t cause an increase in your sketch size anyway).

And, to answer your other question, yes all Serial objects are preinstantiated (either just Serial for one UART boards or Serial, Serial1, 2 and 3 for parts like the 2560).

All you need to do is “Serial.begin (baud_rate);” and then “your_stream_function (Serial);” to pass the Serial object to your library code.

PaulS:
At the very beginning of what? You can not know what order constructors will be called in. If you assume, in your constructor, that the HardwareSerial constructor has already been called, you might get away with it. Or, you might not. Debugging such an assumption is a nightmare.

HardwareSerial preinstantiates all the Serial devices, so by the time you need it, it's already there.

Did you ever worry about this when you typed "Serial.begin (9600);"? Where did you think "Serial" came from?

HardwareSerial preinstantiates all the Serial devices, so by the time you need it, it's already there.

Are you absolutely certain that the Serial object is created BEFORE any other constructors are called? If so, HOW can you be so certain?

PaulS:
Are you absolutely certain that the Serial object is created BEFORE any other constructors are called? If so, HOW can you be so certain?

I'll ask again.... "Did you ever worry about this when you typed Serial.begin (9600)"

Obviously, the OP is going to include Arduino.h in his library, so when his code initializes (that is, initial C setup before main() is called) every preinstantiated object (Serial and any the OP may be using) will exist and be ready for use.

(edit): I don't know what ORDER objects are instantiated by the C startup code, and it may not be the same order that they exist in the user's SOURCE, but it doesn't matter because they are all instantiated BEFORE main() is called, so the order doesn't matter.

I'll ask again.... "Did you ever worry about this when you typed Serial.begin (9600)"

No, because I know that Serial.begin() belongs in setup().

If I needed to use Serial in my class, I know that I should not make use of Serial IN MY CONSTRUCTOR because I do not know if the Serial object has been created yet.

My point was that OP probably doesn't know,either, and you have not proved that you do know.

(edit): I don't know what ORDER objects are instantiated by the C startup code, and it may not be the same order that they exist in the user's SOURCE, but it doesn't matter because they are all instantiated BEFORE main() is called, so the order doesn't matter.

It most certainly DOES matter.

PaulS:
(1) No, because I know that Serial.begin() belongs in setup().

(2) If I needed to use Serial in my class, I know that I should not make use of Serial IN MY CONSTRUCTOR because I do not know if the Serial object has been created yet.

My point was that OP probably doesn't know,either, and you have not proved that you do know.
It most certainly DOES matter.

(1) It doesn't have to be in setup(). In fact, I don't even use the setup/loop configuration. I use int main void() like this:

int main (void)
{
    init (); // setup timers and such
    Serial.begin (115200); // if I'm using serial

    // all my code goes here...

    while (1) {
        // or in here if it needs to run repeatedly
    }

    while (1); // sits at the bottom if necessary
}

(2) I know Arduino is designed to allow noobs to have success programming, but really? setup and loop?

As far as constructors, I can't think of any reason to use the constructor of one class inside another class. Can you give me an example?

It seems to me that nesting classes would be poor programming practice (although I could be wrong and would appreciate the correct info if I am wrong).

If I were writing the program, I would have separate classes as needed then instantiate them and use them inside main().

As far as constructors, I can't think of any reason to use the constructor of one class inside another class. Can you give me an example?

Yes, but I'm not going to. There is NOTHING in my post that said that. What I said was that there is no way to know, IN THE CONSTRUCTOR OF MY CLASS, whether the instance(s) of HardwareSerial have already been created, or not.

It seems to me that nesting classes would be poor programming practice

Nonsense. I could be using a linked list in my class, and implement the linked list in another class. That does not constitute nesting of classes, in my opinion, but you seem to think that it does.

What about using String in my class? Is that poor programming? (Well, of course it is, but for entirely different reasons.)

Thanks a lot guys!

I am not absolutely sure when the Stream objects are created but I am 99% sure it is before I call any constructor of my own. In my library I simply use references to operate on a Stream object. This way I actually use functions defined in the Stream class. In my constructor I don't create a new Stream object, I create a reference to one that is passed as input.

If you check the git repository https://github.com/arduino/Arduino/tree/master/hardware/arduino/avr/cores/arduino, it seems like HardwareSerial objects are defined depending on the board used and this happens before the code in the sketch is run. What Krupski says that you never need to do any preconfiguration and just start using a port with Serial.begin(), really makes sense.