Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 10 of 10

Thread: Array of HardwareSerial objects

  1. #1
    Junior Member
    Join Date
    Dec 2018
    Posts
    17

    Array of HardwareSerial objects

    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!

  2. #2
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,136
    HardwareSerial* ports[] = { Serial1, Serial2, Serial3 };
    ports[0]->available();
    ?

    Untested but if theyre all in same class just create array of pointers

  3. #3
    Junior Member
    Join Date
    Dec 2018
    Posts
    17
    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

  4. #4
    Senior Member
    Join Date
    Feb 2017
    Posts
    321
    It's probably more flexible to use a an array of pointers to Stream objects.

  5. #5
    Junior Member
    Join Date
    Dec 2018
    Posts
    17
    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

  6. #6
    Senior Member
    Join Date
    Feb 2017
    Posts
    321
    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() {}

  7. #7
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,738
    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());
        }
      }
    }

  8. #8
    Senior Member
    Join Date
    Feb 2017
    Posts
    321
    Quote Originally Posted by KurtE View Post
    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.

  9. #9
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,738
    @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 by KurtE; 11-01-2019 at 05:11 PM.

  10. #10
    Junior Member
    Join Date
    Dec 2018
    Posts
    17
    Thanks, this is definitely what I was looking for.
    Just forgot the whole passing by reference thing in C++. Good reminder.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •