Error when using TinyUSB

I’m trying to compile example serial_echo from ArduinoTinyUSB but get “TinyUSBDevice was not declared in this scope”, despite TinyUSB being selected in the USB Stack.

What could be wrong ?

what does "USB Stack" mean?
don't you need to include some library by specifying a header file?

Menu Tools\USB stack

The header file include is the first line of the example code

Not enough info at all.

What board are you compiling for? Screenshot of exact Arduino IDE -> Tools settings? Link to the sketch you're trying to upload?

Board is a Seeeduino XIAO (SAMD21)

Code below:

#include "Adafruit_TinyUSB.h"

/* This sketch demonstrates USB CDC Serial echo (convert to upper case) using SerialTinyUSB which
 * is available for both core with built-in USB support and without.
 * Note: on core with built-in support Serial is alias to SerialTinyUSB
 */

void setup() {
  // Manual begin() is required on core without built-in support e.g. mbed rp2040
  if (!TinyUSBDevice.isInitialized()) {
    TinyUSBDevice.begin(0);
  }
}

void loop() {
  #ifdef TINYUSB_NEED_POLLING_TASK
  // Manual call tud_task since it isn't called by Core's background
  TinyUSBDevice.task();
  #endif

  uint8_t buf[64];
  uint32_t count = 0;
  while (SerialTinyUSB.available()) {
    buf[count++] = (uint8_t) toupper(SerialTinyUSB.read());
  }

  if (count) {
    SerialTinyUSB.write(buf, count);
  }
}

Settings;

You don't need any of that stuff. The Arduino core that you're using for the Seeeduino Xiao already has native TinyUSB support. No need to call TinyUSBDevice.begin() or call into the task function.

Per the Arduino core (https://files.seeedstudio.com/arduino/core/samd/ArduinoCore-samd-1.8.5.tar.bz2), it has a builtin version of Adafruit TinyUSB 1.18.3. Use example sketches that expect that version.

https://github.com/adafruit/Adafruit_TinyUSB_Arduino/tree/1.18.2

Also, if you set the stack to TinyUSB, then Serial will already be just a SerialTinyUSB, no need to create a new object or reference that. Your sketch should just be

#include <Adafruit_TinyUSB.h>
void setup() {
  Serial.begin(9600);
}

void loop() {
  uint8_t buf[64];
  uint32_t count = 0;
  while (Serial.available()) {
    buf[count++] = (uint8_t) toupper(Serial.read());
  }

  if (count) {
    Serial.write(buf, count);
  }
}

You can test out other Adafruit TinyUSB sketches like two USB Serial devices with https://github.com/adafruit/Adafruit_TinyUSB_Arduino/blob/1.18.2/examples/CDC/cdc_multi/cdc_multi.ino

I suspected that it was the same as using Serial but…

I'm trying to connect the Seeed to another device (a motor controller) that is acting as an USB host, through their USB-C ports.

The purpose is to send some Ascii command strings from the Seeed to the device.

I tried to establish a connection using Serial but it isn't working. It doesn't go past the available() step.

However if I connect the Seeed to a terminal window, the strings do appear.

That's why I tried tinyUsb on the hope that it might work at a “lower “ level.

There are many reasons why that motor controller couldn't be detecting the Seeed as a USB serial. Maybe it's looking for the right USB VID:PID to make sure only specific devices can connect to it? Maybe the USB host does not assert the "DTR" virtual signal line that the Arduino implementations expect the host to set so that if ( Serial ) return true?

Do you have known working device that acts a USB CDC and can plug into that motor controller? What if you connect that to just your PC? Under what USB VID:PID does it show up? Is it really acting as a USB serial port or are there are other USB devices (HID, ..) too?

I think what you want to test first is if the USB serial device is mounted / connected at all.

With whatever USB stack, that should be just

#define LED LED_BUILTIN /* or another pin */
void setup() {
  Serial.begin(9600);
  pinMode(LED, OUTPUT);
}

void loop() {
  if ( Serial ) {
   digitalWrite(LED, HIGH); // indicate USB serial connection state via LED 
  } else {
   digitalWrite(LED, LOW); 
  }
}

Thanks Max

When I connect my PC to the host, I use a terminal app - Moba Xterm - and just open the COM for the USB port and I'm able to send a string of characters and they get recognised.

How can I check the VID:PID?

I think it's best to look at the device in the Windows device manager with View -> Device by container.

You will be able to see all USB devices that that device presents.

With right click -> properties -> details -> Hardware-IDs, the vendor ID (VID) and product ID (PID) are also displayed. For example, with my ESP32S3, I can see it hosts a USB serial and a HID game controller, with a VID of 0xCAFE and PID of 0x4001.

The Zadig tools should be able to show you the same.

Wait, but this makes no sense to me.

Your PC is a USB host.

How can you connect a USB host to a USB host?

Is it USB-OTG that can switch between device roles and host roles?

This is what I get:

USB\VID_1f3a&PID_efe8

Okay, that is indeed USB OTG.

Still my question remains, is the device you want to emulate a USB device or USB host? When you connect that thing to your PC it surely acts like a USB device, not a USB host.

I believe it's a host but I might be wrong. It's a Odrive Micro (odriverobotics.com)

When I connect it to the PC, I can open a terminal session and issue text commands to it

Your PC is always a USB host. If the device shows up in your device manager, then the Odrive Micro acts as a USB device here.

Fundamentally different to how you think it should work.

If you want your Seeeduino XIAO M0 to act like your PC, then it too must act as a USB host. The XIAO host should then accept the Odrive board as a USB serial adapter device.

The Arduino core, supporting the native and the TinyUSB USB stack, is able to act like a USB host. The example libraries -> USBHost -> USB_desc.ino is one example of that. Though the USBHost library does not feature an abstraction to accept USB CDC devices. TinyUSB has that.

Similiarly, TinyUSB has a USB enumeration example examples/DualRole/device_info_rp2040/device_info_rp2040.ino and even better an example for the usage of the critical Adafruit_USBH_CDC ("USB Host CDC") class here. These exact sketches are meant for an RP2040 though, you'll have to adapt them.

In general, in order to be able to debug such a setup at all, with the USB-C port of the XIAO being used as a USB host now, you should use the hardware UART (Serial1) to print out debugging information, meaning you need another dedicated USB-to-UART adapter (like an FTDI / CH340 / CP2102). Then you will be able to read the debug info on whether the XIAO detects any incoming USB devices at all and whether communication is okay.

This can be done, but is of course some work.

There's also the question of the cable.

Both the Seeed and the motor controller have USB-C.

I tested the connection with both a c-c cable and two USB-C/USB-A cables.

The result was the same

This will absolutely not work unless the Xiao is running the right code.

But setting that completely aside, wouldn't it be much easier to give the Xiao a CAN module so it can talk over CAN to the ODrive?

They have dedicated libaries for controlling the ODrive over UART and CAN, and your ODrive Micro seems to have CAN.

That is a million times easier than implementing a USB host.

Yes, CAN is the option they really propose for something like this.

But as this might become a commercial product I would like to keep costs and complexity down, so if I could get away with USB it would be better.

Would TinyUsb allow me to configure the xiao USB as a host?

Paulo Rebordão

A sábado, 11/10/2025, 18:58, Maximilian Gerhardt via Arduino Forum <notifications@arduino.discoursemail.com> escreveu:

Actually, TinyUSB does not support the USB Host stack for SAMD21 devices.

https://github.com/hathach/tinyusb?tab=readme-ov-file#supported-cpus

Which means that the only supported USB host library in that Arduino core is USBHost

https://github.com/arduino/ArduinoCore-samd/tree/master/libraries/USBHost

Which does not have builtin host capability for USB CDC devices. It only has support for HID keyboard, mouse and Android ADK.

This can impossibly be cost effective. You would have to gain significant USB CDC protocol knowledge to implement either of those paths. A cheap microcontroller with a CAN controller/PHY, and there are even microcontrollers that have builtin CAN controllers and even PHYs, must be several orders of magnitude cheaper and more robust than going through the entire USB protocol stack. Sending CAN messages seems much more reliable to me.

The second best thing would be to switch from a Xiao M0 (ATSAMD21) to an RP2040 based device, for which TinyUSB has an actual USB host implementation. (example Adafruit)

The first best thing would be like a CH32V003 with a CAN module or a STM32 with builtin CAN.