Array of HardwareSerial objects

Status
Not open for further replies.

Robbert

Active member
I'm making a project that involves a lot of communication to boards. (driving a lot of octoWS2811).
Therefore I'm using the Teensy hardware serial. I was planning to put those into an array and then select which board is being send over in the function as to make it more flexible;

Setting the array;
Code:
int setPort; // Data-type for correct port-handling
setPort = 4;
serialArray[setPort-1].begin(9600); // RX31 TX32 - Teensy 3.5
setPort = 5;
serialArray[setPort-1].begin(9600); // RX34 TX33 - Teensy 3.5

Example function;
Code:
void SerialHandler::sendDataSnippet(unsigned int _port, int _pixel, int _color, int _value) {
    serialArray[_port-1].print(STX);
    serialArray[_port-1].print('S');
    serialArray[_port-1].print(String(_pixel));
    serialArray[_port-1].print(String(_color));
    serialArray[_port-1].print(String(_value));
    serialArray[_port-1].print(ETX);
}

This doesn't seem to work. However, when I would just use things like Serial4.begin(9600); and then call Serial4.write("test"); it does work.
Would anyone have any pointer if there is a correct way to handle this, or is this just not a way that Teensy allows. Thanks in advance! :)
 
HardwareSerial* ports[] = { Serial1, Serial2, Serial3 };
ports[0]->available();
?

Untested but if theyre all in same class just create array of pointers
 
This actually just fixed it;

Code:
int setPort; // Data-type for correct port-handling
setPort = 4;
serialArray[setPort-1] = Serial4; // RX31 TX32 - Teensy 3.5
serialArray[setPort-1].begin(9600);
setPort = 5;
serialArray[setPort-1] = Serial5; // RX34 TX33 - Teensy 3.5
serialArray[setPort].begin(9600);

No clue why stuff didn't work before. Maybe there was just some other stuff blocking it.
This solution is fine, just allows me to only set the needed ports in the constructor and from there on use them more flexible :)
 
Could you maybe post a simple example of this? Can't seem to figure it out;

I've been trying to push the initiated Serials into an HardwareSerial* serialArray[6];
But doesnt seem to work :)
 
Something like this. Compiles for a T3.5, but I don't have one to test it.
Code:
Stream *streamArray[] = {&Serial, &Serial1, &Serial2, &Serial3, &Serial4, &Serial5, &Serial6};
const uint8_t numSerials = sizeof(streamArray) / sizeof(streamArray[0]);

void setup() {
  Serial.begin(115200);
  Serial1.begin(115200);
  Serial2.begin(115200);
  Serial3.begin(115200);
  Serial4.begin(115200);
  Serial5.begin(115200);
  Serial6.begin(115200);
  delay(1000);

  for (uint8_t i = 0; i < numSerials; i++) {
    streamArray[i]->print("Hello World, Serial # ");
    streamArray[i]->println(i);
  }
}

void loop() {}
 
This compiles as well, I have not run it:
Code:
HardwareSerial *serials[] = {&Serial1, &Serial2, &Serial3};
const uint8_t numSerials = sizeof(serials) / sizeof(serials[0]);
void setup() {
  for (uint8_t i=0; i < numSerials; i++) {
    serials[i]->begin(1000000);
  }
}

void loop() {
  for (uint8_t i=0; i < numSerials; i++) {
    while (serials[i]->available()) {
      Serial.printf("%d:%02x\n", i, serials[i]->read());
    }
  }
}
 
This compiles as well,
Yes, an array of HardwareSerial pointers works fine as long all “SerialX” objects are instances of that class. The advantage there is that HardwareSerial defines the .begin() method so you can loop through the array in setup() rather than calling .begin() separately on each object.

But, it won’t work if you want to include “Serial” as it’s not an instance of HardwareSerial but rather of usb_serial_class. In that case, polymorphism lets you use an array of Stream pointers since both HardwareSerial and usb_serial_class inherit from that class. The downside is that Stream doesn’t define a .begin() method as not all Stream objects need it.
 
@gfvalvo - Yes you are correct, but I was trying to answer the question asked: Array of HardwareSerial objects ;)

I have personally done it both ways... Again it may depend on your usage patterns and what it is you need...

For example: I may wish to have an array of N Hardware Serial objects, where I internally keep buffers of data to output to each of them, and I don't want any blocking....

So I may have my array and wish to do things like, call pserial->availableForWrite() to constrain how much stuff I try to write out, for that loop cycle as to not have the code wait for enough room available to output without blocking, and unfortunately, some functions like this are only available on higher level objects than stream.

But I have hacked some code before that I like use used Stream* pstream;
It ain't pretty, but ended up doing something like:
Code:
 if (pstream == &Serial1) {
    Serial1.begin(1000000);
}
And yes you can do this external this as well. But I have done this for example supporting DXL servos. As there is more code involved on initialization.
Like if the user passed in a direction pin, then I setup the transmitterEnable pin, else, I set the serial port into Half duplex mode, and then setup elsewhere to
again check that it is hardware port, and if necessary again muck register to turn into Tx or Rx mode...

But as you mentioned, it is nice in some/many cases to also allow Serial and other potential Stream objects.

EDIT: I forgot we actually did add the availableForWrite to the Print class, so again don't need it in that case..
 
Last edited:
Thanks, this is definitely what I was looking for.
Just forgot the whole passing by reference thing in C++. Good reminder.
 
Status
Not open for further replies.
Back
Top