Creating a virtual USB keyboard with the ESP32-S3

Introduction

The idea for this project began during a casual lunch conversation, where were wondering about how challenging it might be to build a virtual keyboard from scratch these days. That sparked my curiosity, especially since the ESP32-S3 natively supports USB OTG. I was eager to try it out for myself and see what was possible.

Choosing the Right Hardware

ESP32-S3 DevKit

Before making any purchases, I watched a helpful video by Andreas Spiess that explores the different ways ESP32 controllers handle USB functionality (13-minute video: https://youtu.be/hJSBTFsOnoA?si=-KlphLdLC01w7r4N). Based on what I learned, I chose the ESP32-S3 DevKit. It comes with two USB ports and requires no soldering, making it ideal for quick experimentation.

When the board arrived, I decided to set things up using my old Windows laptop, now running Ubuntu. This way, if anything went wrong (and released the infamous magic smoke), I wouldn't risk my main machine. Plus, I prefer a setup that's easy to reproduce without specialised gear.

Installing the Arduino IDE

To keep things simple, I approached the setup as a new user would. I installed the Arduino IDE directly from the Ubuntu Software Center. However, my first attempt at compiling code resulted in a GLIBC_2.29 missing error.

GLIBC error in Arduino IDE

After checking with ldd --version, I discovered that my system actually had a newer version of glibc (2.39) already installed.

Troubleshooting Installation Issues

Seeking a solution, I consulted Perplexity and tried running arduino.pip install --upgrade esptool, hoping it would resolve the issue. Unfortunately, that didn't work.

After several unsuccessful attempts to upgrade the snap versions, I decided to switch strategies. I removed the snap installation: sudo snap remove arduino

Then, I downloaded the Arduino IDE AppImage from the official documentation and installed libfuse2 as recommended.

Flashing the ESP32-S3

With the IDE up and running, I asked an LLM for an example sketch to send "Hello World!" as keyboard input to any connected computer. After selecting the appropriate port, I flashed the code, connected the second USB cable, and waited five seconds. Sure enough, the device typed "Hello World!" virtually, just as expected.

Here's the code I used:

#include <USB.h>
#include <USBHIDKeyboard.h>

USBHIDKeyboard Keyboard;

void setup() {
  USB.begin();
  Keyboard.begin();
  delay(5000);
  Keyboard.println("Hello World!");
}

void loop() {
  // put your main code here, to run repeatedly:
}

Conclusion

This simple experiment opens up a world of possibilities. With an ESP32-S3, you can create your own stream deck, game controller, or even a custom keyboard—all without complex hardware modifications.

Published: 2025-06-16

Tagged: Electronics ESP32 Microcontroller USB

Archive