Experimenting: Wonder if GIGA can support multiple USB Serial objects

I am just sort playing around, and wondered if the GIGA (and probably other MBED based boards could support multiple USB (CDC ACM) type Serial objects, like the
different Teensy boards, with USB Types (Dual Serial, Tipple Serial)...

So I started hacking: So far I have it contained in one sketch, with header files and c++ files, which are modified versions of some of the USB code (PluggableUSBSerial, USBCDC).

Test sketch is a simple like copy of the USB Serial to Serial forwarder, where one of the USB Serial connects up to a Hardware Serial port and second one to second...

Looks like it is starting to work. Not sure how far I will take it.
Also my guess is that, it should be possible to simply modify, the actual MBED USB code to do this without this copy. I mainly needed to remove the assumptions, that there is only one and I know the name of it...
USBtoSerialMulti-241119a.zip (12.7 KB)

Now back to playing!

1 Like

tinyUSB will let you do this (eg on SAMD21) without MBed.
Sometime I'll finish the code to turn a Xiao into a 3port USB/Serial converter...

1 Like

Just wondering - in which situation 3 port USB would be useful? Do you want to make an USB-hub?

Currently I when I use multiple USB Serial ports on a Teensy, is suppose the main Serial connection is used to talk in some specific format to the PC. For example maybe the Teensy is setup for communication with Serial based servos... So that mostly uses up the Serial object.

Now suppose I wish to input and output Debug information to the program running on the MicroController. Old days I might use Serial1 (or other Serial object) and use a USB To Serial adapter, to then be able to communicate with the debug port. With the object like lets say SerialUSB1 (Teensy) or in my sketch where I define it like:
USBSerialX SerialUSB1(false);

I can now do it without any additional hardware...

Or suppose you have a Robot, with multiple sensors and the like, and you have drivers running on your PC (or RPI), maybe this is ROS or the like and some nodes are written in C++ or Python... You could now have different nodes communicating with each of the logical Serial ports, where each one is controlling some piece of hardware.

2 Likes

Three serial ports, one USB port. (actually 4 "Serial" devices on the Arduino side. Three tied to the HardwareSerial devices, and one for debugging/commands.)

2 Likes

Morning @KurtE
After synching up with the latest core changes I decided to go for broke and attach your changes to a sketch I use for the MPU9250 using Madgwicks fusion algorithm which works on the teensy.

This is running at 115200 baud just for reference.

A couple of things that I noticed is that if after Serial is opened and if I close it and then try to reopen it nothing shows and it hangs.

But when it works it looks like this:

Seems what I have to do get it working with the FUSION GUI is start it by sending the commands via USB1 and keep Serial closed and then open Serial in the GUI

1 Like

Looks like we have some debugging to do :smiley:

1 Like

If interested here is the sketch I have been using. You will need libprintf lib by the way.
MPU9250_Fusionv1_MPU9250_Fusionv1_GIGA_dual_serial.zip (18.1 KB)

If you want the GUI you can find it here:
x-IMU3 – x-io Technologies

1 Like

Easy way to achieve this:

#include <USB/PluggableUSBSerial.h>

arduino::USBSerial mySerial(false);

void setup() {
  // put your setup code here, to run once:
  mySerial.begin(115200);
}

:slight_smile:
The two serial ports will share the same VID/PID, so it might be a bit hard to recognize which one is Serial and which is mySerial.

The additional optional parameter of the constructor (like arduino::USBSerial mySerial(false, "myGIGA"); ) can be used to add a descriptor which can be parsed by particular tools.

2 Likes

Thanks,

I was trying that earlier and it did not appear to work for me. Maybe I had/have issue in test code.

My guessing and some of the stuff I changed included things like:

void USBSerial::begin(unsigned long) {
    this->attach(usbPortChanged);
    this->attach(::mbed::callback(this, &USBSerial::onInterrupt));
    t = new rtos::Thread(osPriorityNormal, 256, nullptr, "USBevt");
    t->start(waitForPortClose);
    onInterrupt();
}

Where:

void usbPortChanged(int baud, int bits, int parity, int stop) {
    if (baud == 1200) {
        event.set(1);
    }
}

would be common to all of the instances. likewise, there is only one event object
and another static function waitForPortClose. That is also linked to in each time an instance calls begin.

static void waitForPortClose() {

    event.wait_any(0xFF);
    // wait for DTR be 0 (port closed) and timeout to be over
    long start = millis();
    static const int WAIT_TIMEOUT = 200;
    while (_SerialUSB.connected() || (millis() - start) < WAIT_TIMEOUT) {
        // the delay is needed to handle other "concurrent" IRQ events
        delay(1);
    }
    _ontouch1200bps_();
}

Which is using hard code object _SerialUSB in it's code.

Maybe only _SerialUSB needs to process this? I am guessing that the change to 1200 baud is maybe a signal to reboot... In which case maybe the begin method could
simply check like:
if (this == &_SerialUSB) this->attach(usbPortChanged);
Ditto for the second one.
if (this == &_SerialUSB) t->start(waitForPortClose);

Maybe I should experiment again.

Thanks again

@facchinm - follow on, it appears like it might work as is... Not sure why it was not when I tried earlier, maybe it was when I had the begin method commented out.
(Earlier I tried to just include USBSerial.h)... and that did not work...

Will experiment more.
Thanks again!

1 Like

Thought I would mention, that I have been having fun playing with your IMU stuff, some of which uses the dual serial.

For this I have installed your version of:

Also your version of fusion library:
https://github.com/mjs513/Fusion.git
Note: you either need to copy to the Subdirectory Fusion.
kurte@RPI5:~/Arduino/libraries $ ln -s ~/github/Fusion/Fusion/

This requires some additional libraries, some of which you can use the library manager to
download:
Bolder Flight Systems: Eigen. Unit Conversions,
LibPrintf
Streaming

From github:

Maybe some others, but with this I can build the ICM29948_fusion... example for GIGA.