Tiny usb arduino

Tiny USB Windows® Key

In this post, you can see a tiny, yet quite useful, microcontroller-based USB key/Foot Pedal for Windows™ computers as a little do-it-yourself project. It is particularly geared as single function key, but other usages are also possible. This funny article is aimed at novices. As a flexible USB HID (USB human interface device) project, it can be weighed simple to medium on a scale from very simple to very difficult. Note that, HID (Human Interface Device) is one of the many defined USB device classes. Every USB device is assigned a device class, which defines what exactly its general purpose is. There are lots of classes –printers, hubs, and speakers to mention a few.

I chose the name “Tiny USB Windows ® Key” for this USB button/Foot pedal. The controller part is a Digispark Attiny85 development board. Surprisingly, the stamp-sized board offers a standard USB interface and good compatibility with the revered Arduino IDE. The concept is based on a dedicated library for Digispark to emulate a USB keyboard. When the user activates the device, it sends out a predefined keystroke (hide/show desktop) to the connected computer to control the desktop instantly. Well, get ready to set it right!

As can see from the above hardware prep diagram, the entire assembly is extremely simple. Just connect a normally-open momentary button switch between P0 and GND of Digispark board. That’s all. I used a Chinese clone Digispark board (Rev 3), and an Omron B3F-4055 tactile switch with red round cap as key the components in my quick test setup.

The code, in the form of Arduino Sketch, given below uses the “DigiKeyboard” library to emulate the USB keyboard. The code provided below can be compiled and uploaded using the Arduino IDE. The code simulates the keypress in a sequence of two keys at the same time and after a short delay, it releases them (that means only one keyboard shortcut after the key button has been pushed). You may checkout this GitHub link to get further details about the DigiKeyboard library https://github.com/digistump/DigistumpArduino/blob/master/digistump-avr/libraries/DigisparkKeyboard/DigiKeyboard.h

The construction should be a piece of butter bread even for novices. It is possible to use the ‘Digispark Button Shield’ for this project. Incase it’s not within easy reach, or you don’t want to buy one, just use a small piece of shipboard as an alternative (called for some dexterity though). This is the photograph of my quick test setup.

Plug the ready-to-use device to any vacant USB port of a Windows computer, and wait until the onboard red indicator (P1 LED) comes up. Thereafter you can push the key button to you’re your desktop. And, the desktop can be recalled through the next push of the same key button. Once everything is setup and working, you can even take it a step further by using a USB foot pedal in lieu of the small button switch. Simply make one USB foot pedal yourself at home with a cute 3D-printed enclosure and a 2-pin soft-touch momentary footswitch (look below). You probably won’t want such an external USB pedal, but if you occasionally need a ‘secret’ pedal for something odd, roll up your sleeves, and go on!

Note that at power up, Digispark’s onboard red power indicator (power LED) of the Digispark board lights up quickly, and after a few seconds another onboard red indicator (user LED) wakes up to notify that it’s ready for use. The connected Windows PC identified the key/pedal device as a USB HID Keyboard!

Human Interface Device (HID) class is one of the most frequently used USB classes. The HID class consists primarily of devices that are used by humans to control the operation of computer systems. Examples of HID class devices include keyboards, pointing devices, control devices, the devices that humans use to enter data directly into a computer, and other devices that may not require direct human interaction but provide data in a similar to HID class devices format.

USB defines class code information that is used to identify the functionality of a device and to nominally load a device driver based on that functionality. The information is contained in three bytes with the names Base Class (USB Class), SubClass, and Protocol. The Base Class 03h as seen here is defined for devices that conform to the HID (Human Interface Device) Device Class Specification found on the USB-IF website. The specification defines the usable set of SubClass and Protocol values. Values outside of that defined spec are reserved, and these class codes can only be used in Interface Descriptors. Further reading https://www.usb.org/defined-class-codes

On a side note, “USBlyzer” is a pretty great professional USB sniffer software for monitoring and analyzing the USB devices traffic. The program can be successfully employed for USB protocol analysis, debugging and reverse-engineering and USB-related application, device driver or hardware development. It is a very useful tool for anyone who needs a visual picture of the traffic passing through USB subsystem. This is a fully functional trial version pack of USBlyzer. You can evaluate this fully functional trial version free of charge for a limited period of 33 days http://www.usblyzer.com/files/USBlyzer.zip

Back to the basic design scheme, it is essentially, a USB keyboard with only one key. Plug it into any computer that can understand a basic USB HID – which means just about every Windows desktop or laptop computer will detect a new keyboard. By default, this single key/pedal is tailored to hide/show the desktop when you press it. But this little doodad can do considerably more than just that – see, you can bind any single key or standard Windows modifier keys to the pedal with any keystroke you like, and with any other modifiers you like (a modifier key is a special key on a computer keyboard that modifies the normal action of another key when the two are pressed in combination) which is probably all you want to do if you want the key/pedal to be an extra system control. Well, inspire others by telling the story about how you built this funny project. Good luck!


Using WebUSB with Arduino and TinyUSB


New Subscription

Please sign in to subscribe to this guide.

You will be redirected back to this guide once you sign in, and can then subscribe to this guide.

This guide will show how the combination of the Open Source TinyUSB USB port software and the Chrome WebUSB browser capability provides programmers and users the ability to plug in microcontroller-based projects and have them interact with the user in a web browser. No additional code is required on the display computer other than a standard Chrome browser window (ie. no plug-ins, etc.)

This capability is ideal for schools, learning, ease of use, and assistive technology applications.

WebUSB is a recent standard for securely providing access to USB devices from web pages. It is available in Chrome 61 since September, 2017 and all current versions.

One of the reasons the WebUSB API has been created: to provide a way to expose USB device services to the Web. With this API, hardware manufacturers are able to build cross-platform JavaScript SDKs for their devices. But most importantly, this makes USB safer and easier to use by bringing it to the Web.

Let’s see what you can expect with the WebUSB API:

  1. Buy a USB device.
  2. Plug it into your computer.
  3. A notification appears right away, with the right website to go to for this device.
  4. Simply click on it. Website is there and ready to use!
  5. Click to connect and a USB device chooser shows up in Chrome, where you can pick your device.
  6. Tada!

What would this procedure be like without the WebUSB API?

  • Read a box, label, or search on line and possibly end up on the wrong website.
  • Have to install a native application.
  • Is it supported on my operating system? Make sure you download the «right» thing.
  • Scary OS prompts popup and warn you about installing drivers/applications from the Internet.
  • Malfunctioning code harms the whole computer. The Web is built to contain malfunctioning websites.
  • Only use the USB device once? On the Web, the website is gone once you closed tab. On a computer the code sticks around.

TinyUSB is an open-source cross-platform USB Host/Device stack for embedded system. It is designed to be memory-safe with no dynamic allocation and thread-safe with all interrupt events are deferred then handled in the stack’s task function.

While there are some other USB stacks for microcontrollers, notably the Arduino stack, TinyUSB is compatible with a wide range of microcontrollers, has better device support, and is MIT licensed.

The TinyUSB library is on Adafruit’s GitHub repo here.

Adafruit has worked to ensure TinyUSB works with WebUSB. Together, they allow Adafruit and compatible microcontrollers to work with WebUSB browsers like Chrome with no drivers on the host computer/tablet/phone/chromebook. Super simple and this works well in environments like schools.


TinyUSB is Awesome! And tutorial about how to use it in SAMD21 board

Unlike the Arduino Uno and Arduino Nano, the Seeeduino XIAO onboard USB is not supported by the common USB-to-serial chip. These chips are usually FT232, CP2102, CH340, and etc. The main chip ATSAMD21 of Seeeduino XIAO is natively supporting the USB protocol stack. This feature means that the USB function can be changed by the code.

Other boards with natively USB support:

  • ATMEGA32U4 chip:
    • Arduino Micro
  • ATSAMD21
    • Seeeduino XIAO
    • Adafruit Feather M0
  • ATSAMD51
    • Wio Terminal
    • Adafruit Feather M4.

With this feature, Seeeduino XIAO is very suitable as the controller of DIY USB devices, such as the DIY mechanical keyboard, it is time to say goodbye to the slow 8-bit ATMEGA32U4 development board.

Next, we use Seeeduino XIAO to try to run the powerful and popular TinyUSB software stack

For ATSAMD21 based development board like Seeeduino XIAO, we can use this Arduino TinyUSB library by Adafruit: https://github.com/adafruit/Adafruit_TinyUSB_Arduino

Download the Zip files, and include it in Arduino IDE

Let’s try to run this example, Adafruit TinyUSB Library → MassStorage → msc_ramdisk

Then, change the USB Stack of Arduino IDE from “Arduino” to “TinyUSB”

Hit Download button:

And the MassStorage Disk appeared !!

There is a README.txt inside.

Let us see what can we do with this powerful TinyUSB library:

  • Human Interface Device (HID): Generic (In & Out), Keyboard, Mouse, Gamepad, etc …
  • Mass Storage Class (MSC): with multiple LUNs
  • Musical Instrument Digital Interface (MIDI)
  • WebUSB with vendor-specific class


Getting Started¶

Add TinyUSB to your project¶

It is relatively simple to incorporate tinyusb to your (existing) project

Copy or git submodule this repo into your project in a subfolder. Let’s say it is your_project/tinyusb

Add all the .c in the tinyusb/src folder to your project

Add your_project/tinyusb/src to your include path. Also make sure your current include path also contains the configuration file tusb_config.h.

Make sure all required macros are all defined properly in tusb_config.h (configure file in demo application is sufficient, but you need to add a few more such as CFG_TUSB_MCU, CFG_TUSB_OS since they are passed by IDE/compiler to maintain a unique configure for all boards).

If you use the device stack, make sure you have created/modified usb descriptors for your own need. Ultimately you need to implement all tud descriptor callbacks for the stack to work.

Add tusb_init() call to your reset initialization code.

Call tud_int_handler() (device) and/or tuh_int_handler() (host) in your USB IRQ Handler

Implement all enabled classes’s callbacks.

If you don’t use any RTOSes at all, you need to continuously and/or periodically call tud_task()/tuh_task() function. All of the callbacks and functionality are handled and invoked within the call of that task runner.


For your convenience, TinyUSB contains a handful of examples for both host and device with/without RTOS to quickly test the functionality as well as demonstrate how API() should be used. Most examples will work on most of the supported boards. Firstly we need to git clone if not already

Some TinyUSB examples also requires external submodule libraries in /lib such as FreeRTOS, Lightweight IP to build. Run following command to fetch them

Some ports will also require a port-specific SDK (e.g. RP2040) or binary (e.g. Sony Spresense) to build examples. They are out of scope for tinyusb, you should download/install it first according to its manufacturer guide.


To build example, first change directory to an example folder.

Before building, we need to download MCU driver submodule to provide low-level MCU peripheral’s driver first. Run the get-dpes target in one of the example folder as follow. You only need to do this once per mcu

Some modules (e.g. RP2040 and ESP32s2) require the project makefiles to be customized using CMake. If necessary apply any setup steps for the platform’s SDK.

Then compile with make BOARD=[board_name] all , for example

Note: BOARD can be found as directory name in hw/bsp , either in its family/boards or directly under bsp (no family). Note: some examples especially those that uses Vendor class (e.g webUSB) may requires udev permission on Linux (and/or macOS) to access usb device. It depends on your OS distro, typically copy /examples/device/99-tinyusb.rules file to /etc/udev/rules.d/ then run sudo udevadm control —reload-rules && sudo udevadm trigger is good enough.

Port Selection¶

If a board has several ports, one port is chosen by default in the individual board.mk file. Use option PORT=x To choose another port. For example to select the HS port of a STM32F746Disco board, use:

Port Speed¶

A MCU can support multiple operational speed. By default, the example build system will use the fastest supported on the board. Use option SPEED=full/high e.g To force F723 operate at full instead of default high speed

Size Analysis¶

First install linkermap tool then linkermap target can be used to analyze code size. You may want to compile with NO_LTO=1 since -flto merges code across .o files and make it difficult to analyze.


To compile for debugging add DEBUG=1 , for example

Should you have an issue running example and/or submitting an bug report. You could enable TinyUSB built-in debug logging with optional LOG= . LOG=1 will only print out error message, LOG=2 print more information with on-going events. LOG=3 or higher is not used yet.


By default log message is printed via on-board UART which is slow and take lots of CPU time comparing to USB speed. If your board support on-board/external debugger, it would be more efficient to use it for logging. There are 2 protocols:

Cons: requires jlink as the debugger.

Pros: work with most if not all MCUs

Software viewer is JLink RTT Viewer/Client/Logger which is bundled with JLink driver package.

LOGGER=swo : Use dedicated SWO pin of ARM Cortex SWD debug header.

Cons: only work with ARM Cortex MCUs minus M0

Pros: should be compatible with more debugger that support SWO.

Software viewer should be provided along with your debugger driver.


flash target will use the default on-board debugger (jlink/cmsisdap/stlink/dfu) to flash the binary, please install those support software in advance. Some board use bootloader/DFU via serial which is required to pass to make command

Since jlink can be used with most of the boards, there is also flash-jlink target for your convenience.

Some board use uf2 bootloader for drag & drop in to mass storage device, uf2 can be generated with uf2 target

IAR Support¶

IAR Project Connection files are provided to import TinyUSB stack into your project.

A buldable project of your MCU need to be created in advance.

Take example of STM32F0:

You need stm32l0xx.h , startup_stm32f0xx.s , system_stm32f0xx.c .

STM32L0xx_HAL_Driver is only needed to run examples, TinyUSB stack itself doesn’t rely on MCU’s SDKs.

Open Tools -> Configure Custom Argument Variables (Switch to Global tab if you want to do it for all your projects)

Click New Group … , name it to TUSB , Click Add Variable … , name it to TUSB_DIR , change it’s value to the path of your TinyUSB stack, for example C:\tinyusb