T41 USB host detects any T41 device but not serial-only

ithinu

Active member
I have a T41 with USB host. I connect another T41 as device. If the other T41 is configured as Serial or Dual serial, the SerialTest example does not detect anything, unless the program button is pressed - then it finds the programming serial but it is another thing. Similarly, the host T41 cannot connect to that device T41 via USB serial, even if a PC host can.

But if the same device T41 is configured as Serial/Keyboard/Mouse/Joystick, not only all four are detected:

*** Device HID3 16c0:487 - connected ***
manufacturer: Teensyduino
product: Serial/Keyboard/Mouse/Joystick
Serial: 158564
*** Device HID1 - disconnected ***
*** Device HID2 - disconnected ***
*** Device HID3 - disconnected ***

but the host T41 can now connect to the device via USB Serial.

So I need to to configure the device as Serial + something not needed only to use that Serial with a host Teensy (as said, for a host PC Serial-only T41 is enough).
 
It should work, however, by default, the USBSerial object only supports those Serial ports that are USBLS or USBFS (i.e. buffer size == 64)
So if you plug in a T4.x into it, it probably won't connect.

However if you change: to using USBSerial_BigBuffer,
It handles the 512 byte records... However by default it won't connect to any other Serial devices with buffer sizes < 65

But you can tell it that it can connect to Serail objects with smaller transfers, using the optional parameter...
Code:
USBSerial userial(myusb);  // works only for those Serial devices who transfer <=64 bytes (like T3.x, FTDI...)
//USBSerial_BigBuffer userial(myusb, 1); // Handles anything up to 512 bytes
//USBSerial_BigBuffer userial(myusb); // Handles up to 512 but by default only for those > 64 bytes
That is use the one, with the , 1 ...
 
Kurt, it is the same with Examples/USBHost_t36/Serial/SerialTest on host and a blank project on the device. There is no detection of the serial port mode by T41 host if Serial is not accompanied by something like Keyboard/Mouse/Joystick.
 
Unless someone else like @PaulStoffregen beats me to it, I will try to take a look soon.

Currently playing around with the GIGA, and seeing how hard it would be to support something like Dual Serial...
I now have a test sketch with copies of some lower-level code, and it appears like it starting to work :D
Having some fun. Sort of trying to learn about their pluggable USB, where you can simply add an object and the startup
code computes interface numbers and end points...

But just having some fun.
 
Quick and dirty experiment.

I programmed a T41 with:
C++:
uint32_t loop_count = 0;
elapsedMillis emBlink;

void setup() {
    // put your setup code here, to run once:
    pinMode(LED_BUILTIN, OUTPUT);
    while (!Serial && millis() < 4000) {}
    Serial.begin(115200);
    emBlink = 0;
}


void loop() {
    if (emBlink > 500) {
        digitalToggleFast(LED_BUILTIN);
        Serial.printf("Loop Count: %u\n", loop_count++);
        emBlink = 0;
    }
    int ch;
    while ((ch = Serial.read()) != -1 ) Serial.write(ch);
}

Here is the USBtoUSBHostSerial sketch, modified for large buffer, running on a MicroMod
C++:
//=============================================================================
// Simple USBHost USBSerial test
// This sketch is very much like the main teensy example: USBtoSerial.ino
// but instead of going to hardware serial port it forwards the data
// between the USB Serial and a USB Serial device connected to the USB Host
// port.
//
// This example is in the public domain
//=============================================================================

#include <USBHost_t36.h>
#define USBBAUD 1000000 //115200
uint32_t baud = USBBAUD;
uint32_t format = USBHOST_SERIAL_8N1;
USBHost myusb;

// Optional if you use are possibly going to plug your USB Serial device
// into a USB Hub, you should include one or more USB Hub objects.
// How many? depends as some HUB chips support lets say 4 ports, so if the HUB
// actuall has more than this, than internally it may be made up using multiple
// HUBs and you may need one of the hub objects for each one of these.
USBHub hub1(myusb);
//USBHub hub2(myusb);
//USBHub hub3(myusb);

// There is now two versions of the USBSerial class, that are both derived from a common Base class
// The difference is on how large of transfers that it can handle.  This is controlled by
// the device descriptor, where up to now we handled those up to 64 byte USB transfers.
// But there are now new devices that support larger transfer like 512 bytes.  This for example
// includes the Teensy 4.x boards.  For these we need the big buffer version.
// uncomment one of the following defines for userial
//USBSerial userial(myusb);  // works only for those Serial devices who transfer <=64 bytes (like T3.x, FTDI...)
USBSerial_BigBuffer userial(myusb, 1); // Handles anything up to 512 bytes
//USBSerial_BigBuffer userial(myusb); // Handles up to 512 but by default only for those > 64 bytesUSBHost myusb;
// We also now have an optional set of parameters for the constructor that allows you to pass in a Vendor ID,
// product ID, what it maps to and the like, to handle USB objects which have underlying USB to serial converters,
// that are known, but not in our list.
//USBSerial_BigBuffer userial(myusb, 1, 0x10c4, 0xea60, USBSerialBase::CP210X, 0); // Handles anything up to 512 bytes


// Define the buffer to use to copy between the two devices
// I am using 512 bytes as that is the largest one that can happen between two T4.x
// if other type devices could easily reduce to something like 64 bytes
char buffer[512];
uint32_t led_on_time=0;

// This sketch can optionally print out when some of these devices are inserted and removed.
// Comment out this define if you do nowant this.
#define PRINT_DEVICE_INFO
#ifdef PRINT_DEVICE_INFO
// If you add devices you may want to extend these structures to include them as well.
USBDriver *drivers[] = {&userial, &hub1};
#define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0]))
const char * driver_names[CNT_DEVICES] = {"USERIAL1", "Hub1"};
bool driver_active[CNT_DEVICES] = {false, false};
#endif

// Optional Debug output uncomment the next line to enable debug prints
//#define DEBUG_OUTPUT
#ifdef DEBUG_OUTPUT
#define DBGPrintf Serial.printf
#else
// not debug have it do nothing
inline void DBGPrintf(...) {
}
#endif


//=============================================================================
// Setup - only runs once
//=============================================================================
void setup() {
  myusb.begin();
  // pre-Configure the USB Host Serial adapter at startup time
  // Note: versions up till now, this needed to be done after the device connects
  // and at that time the connecton defaulted to 115200
  // In both of these begins below, the actual baud rate specified does not impact the USB communications.
  // it is simply a hint to the devices that allow them to configure other parts of their device.  Example
  // USB to serial devices use this to figure their hardware USART or UART.
  userial.begin(USBBAUD);
  Serial.begin(USBBAUD);

  pinMode(LED_BUILTIN, OUTPUT);

}

//=============================================================================
// loop: continuously called.
//=============================================================================
void loop() {
  myusb.Task();

  uint16_t rd, wr, n;

  // check if any data has arrived on the USB virtual serial port
  rd = Serial.available();
  if (rd > 0) {
    // check if the USB Host serial port is ready to transmit
    wr = userial.availableForWrite();
    if (wr > 0) {
      // compute how much data to move, the smallest
      // of rd, wr and the buffer size
      if (rd > wr) rd = wr;
      if (rd > sizeof(buffer)) rd = sizeof(buffer);
      // read data from the USB port
      n = Serial.readBytes((char *)buffer, rd);
      // write it to the USB Host serial port
      DBGPrintf("S-U(%u %u)\n", rd, n);
      userial.write(buffer, n);
      // turn on the LED to indicate activity
      digitalWrite(LED_BUILTIN, HIGH);
      led_on_time = millis();
    }
  }

  // check if any data has arrived on the USBHost serial port
  rd = userial.available();
  if (rd > 0) {
    // check if the USB virtual serial port is ready to transmit
    wr = Serial.availableForWrite();
    if (wr > 0) {
      // compute how much data to move, the smallest
      // of rd, wr and the buffer size
      if (rd > wr) rd = wr;
      if (rd > 80) rd = 80;
      // read data from the USB host serial port
      n = userial.readBytes((char *)buffer, rd);
      // write it to the USB port
      DBGPrintf("U-S(%u %u):", rd, n);
      Serial.write(buffer, n);
      // turn on the LED to indicate activity
      digitalWrite(LED_BUILTIN, HIGH);
      led_on_time = millis();
    }
  }

  // if the LED has been left on without more activity, turn it off
  if (led_on_time && (millis() - led_on_time > 3)) {
    digitalWrite(LED_BUILTIN, LOW);
    led_on_time = 0;
  }

  // check if the USB virtual serial wants a new baud rate
  // ignore if 0 as current Serial monitor of Arduino sets to 0..
  uint32_t cur_usb_baud = Serial.baud();
  if (cur_usb_baud && (cur_usb_baud != baud)) {
    baud = cur_usb_baud;
    DBGPrintf("DEBUG: baud change: %u\n", baud);
    if (baud == 57600) {
      // This ugly hack is necessary for talking
      // to the arduino bootloader, which actually
      // communicates at 58824 baud (+2.1% error).
      // Teensyduino will configure the UART for
      // the closest baud rate, which is 57143
      // baud (-0.8% error).  Serial communication
      // can tolerate about 2.5% error, so the
      // combined error is too large.  Simply
      // setting the baud rate to the same as
      // arduino's actual baud rate works.
      userial.begin(58824);
    } else {
      userial.begin(baud);
    }
  }

  // Optional check for defice changes
  #ifdef PRINT_DEVICE_INFO
  check_for_usbhost_device_changes();
  #endif
}

// Optional check for defice changes
#ifdef PRINT_DEVICE_INFO
void check_for_usbhost_device_changes() {
  // Print out information about different devices.
  for (uint8_t i = 0; i < CNT_DEVICES; i++) {
    if (*drivers[i] != driver_active[i]) {
      if (driver_active[i]) {
        Serial.printf("*** Device %s - disconnected ***\n", driver_names[i]);
        driver_active[i] = false;
      } else {
        Serial.printf("*** Device %s %x:%x - connected ***\n", driver_names[i], drivers[i]->idVendor(), drivers[i]->idProduct());
        driver_active[i] = true;

        const uint8_t *psz = drivers[i]->manufacturer();
        if (psz && *psz) Serial.printf("  manufacturer: %s\n", psz);
        psz = drivers[i]->product();
        if (psz && *psz) Serial.printf("  product: %s\n", psz);
        psz = drivers[i]->serialNumber();
        if (psz && *psz) Serial.printf("  Serial: %s\n", psz);
        if (drivers[i] == &userial) {
          userial.begin(baud);
        }
      }
    }
  }

}
#endif


Plugged the T4 into Micrmod and output:

Output:
Code:
*** Device USERIAL1 16c0:483 - connected ***
  manufacturer: Teensyduino
  product: USB Serial
  Serial: 9706410
Loop Count: 0
Loop Count: 1
Loop Count: 2
Loop Count: 3
Loop Count: 4
Loop Count: 5
...

And it appeared to work the same when I turned the power on, while the T4.1 is plugged into it.

So not sure what you are seeing.
 
Kurt, I couldn’t connect to the device in Serial-only mode, and SerialTest wasn’t detecting the device serial in Serial-only mode either. So, I presumed that Serial-only mode may be the cause. However, your code both detects and opens the device in Serial-only mode. I’ll look into the differences tomorrow.
 
Just did that here the other day and it worked - with the BIGBUFFER edit as noted - T_4.1 default is 512 and the code in the example won't connect - once I swapped those lines it worked.
Code:
// USBSerial userial(myusb);  // works only for those Serial devices who transfer <=64 bytes (like T3.x, FTDI...)
USBSerial_BigBuffer userial(myusb, 1); // Handles anything up to 512 bytes
 
Back
Top