Teensy 4.1 USB Host - Serial init to connected devices right after boot

ohoomens

Member
Hey everyone,
The last couple of days I spent figuring out how to use the USB host function for communication between MCUs and I encountered a problem I could need some help with :)

Here we go:
A Teensy 4.1 is the main unit. It acts as USB Host and later is the brain of a gaming console. Additionally I have 4x ESP32 (DevKit C) which are the brains of self-made gamepads. Those are supposed to be connected as simple USB devices to the Teensy. As they are super proprietary in terms of used hardware and thus need to talk to the main unit bidirectionally I figured the easiest way is to use simple serial communication - so I used the serial example from the git repo. It all works (at least for 2 devices simultaneously) when I connect the devices while the Teensy is already running. However when I boot up the Teensy while the devices are already connected, the serial connection won't be established. I've tried to wait for the serial connection on the ESPs side but that does not work. Has anyone any idea how to solve this? Thanks in advance :)

Code for the main unit (Teensy 4.1) (What you see here is a simple handshake. The ESP requests an answer from the Teensy which then triggers the ESPs to jump to the main loop. This works and is not part of the problem I think.
Code:
#include <Arduino.h>
#include "USBHost_t36.h"
#define USBBAUD 115200

uint32_t baud = USBBAUD;
uint32_t format = USBHOST_SERIAL_8N1;
USBHost myusb;
USBHub hub1(myusb);
USBSerial userial1(myusb);
USBSerial userial2(myusb);
USBDriver *drivers[] = {&hub1, &userial1, &userial2};
#define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0]))
const char *driver_names[CNT_DEVICES] = {"Hub1", "USERIAL1", "USERIAL2"};
bool driver_active[CNT_DEVICES] = {false, false, false};

USBSerial *serials[2] = {&userial1, &userial2};
String inputFromGamepad[2];

void setup()
{
  while (!Serial && (millis() < 5000));
  myusb.begin();
}

void loop()
{
  myusb.Task();

  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;
        if (drivers[i] == &userial1) {
          userial1.begin(baud);
        } else if (drivers[i] == &userial2) {
          userial2.begin(baud);
        }
      }
    }
  }

  for (uint8_t i = 0; i < 2; i++) {
    if (serials[i]->available()) {
      inputFromGamepad[i] = serials[i]->readStringUntil('\n');
      Serial.println("Length: " + String(inputFromGamepad[i].length()) + " | Content: " + inputFromGamepad[i]);
      if (inputFromGamepad[i].indexOf("req:1:online") >= 0) {
        serials[i]->println("1:ok");
        Serial.println("1:ok");
      } else if (inputFromGamepad[i].indexOf("req:2:online") >= 0) {
        serials[i]->println("2:ok");
        Serial.println("2:ok");
      }
    }
  }
}

Code for the ESPs
Code:
#include <Arduino.h>
#define RETRY 1000

String inputFromConsole;
bool loggedOn = false;
int count;

void setup() {
  Serial.begin(115200);
  while (!Serial);

  while (!loggedOn) {
    Serial.println("req:2:online");

    if (Serial.available() > 0) {
      inputFromConsole = Serial.readStringUntil('\n');
      
      if (inputFromConsole.indexOf("2:ok") >= 0)
      {
        Serial.println("ack:2:online");
        loggedOn = true;
      }
    }

    delay(RETRY);
  }
}

void loop() {
  Serial.println("Gamepad 2 online... " + String(count++));
  delay(500);
}
 
I've tried a few different MCUs as USB Serial devices and it seems that some ESP32 boards don't reset automatically. With a ESP32-S2 or an UNO it works perfectly. Resets neatly and opens the serial monitor when needed. Does anyone know how I can reset through the RTS pin like the ESP-Tool does?
 
Back
Top