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

Create a QR code from the command line

Lindsay, my wife, has been working on her online shop (gestempelt & gedruckt — unique handicrafts inspired by nature) for the last few months. Now that it’s complete, she's eager to get the word out with flyers. For this, she needed a QR code with the shop's URL to make it easier for people to scan.

So how do you generate a white QR code with the rest being transparent without needing to sign up to a website?

Use qrencode and ImageMagick on the command line.

First, install the applications using:

brew install qrencode imagemagick

Then, generate the QR code:

# Create the QR code (white on black).
qrencode -s 20 --foreground=ffffff --background=000000 -l H -o "URL.png" "https://gestempelt-und-gedruckt.ch/"

# Replace black with "transparent".
convert URL.png -fuzz 10% -transparent black URL_transparent.png

Published: 2024-11-03

Tagged: TIL Tools QR code

Building a temperature sensor for Home Assistant with a DHT22 sensor, an ESP8266 and ESPHome

In order to better understand our temperature needs and to humour my interest to tinker with electronics I've decided to build some temperature and humidity sensors and have them installed both in- and outdoors. I'll be using ESPHome which talks to Home Assistant for this build.

I'm started off with a board from AliExpress containing a DHT22 temperature and humidity sensor with an attachable ESP8266 microcontroller.

Programming the ESP8266 microcontroller

To program the ESP8266 one needs an adapter (ESP-01 Adapter Board) which needs to be slightly modified with a button so that we can enable its programming mode (instructions).

ESP-01 Adapter Board used to program the ESP8266 Underside of the ESP-01 Adapter Board used to program the ESP8266 showing the pins used for wiring the button to

Assembly

All the parts required to assemble the temperature and humidity sensor

Having the parts ready I'm logging in to my Home Assistant and heading to the ESPHome view to add a new device. I create a new configuration and choose the ESP8266 as the device, then once it offers the "Install" option I insert the controller to be programmed into the adapter board, keep the button pressed and plug it into one of the USB ports of my Raspberry Pi running Home Assistant. Once plugged in I release the button again. At this stage I can then click the option to install the first version of ESPHome onto the controller via "Plug into the computer running ESPHome Dashboard" (be aware that this might take a while as it has to fetch dependencies and compile the custom build). This step will flash enough for the controller to be able to connect to the Wi-Fi and be updatable via ESPHome running on Home Assistant. It's important to note that the Raspberry Pi likely won't have enough juice to start the controller and hence it won't be doing anything after being programmed.

At this point I disconnect the programmer, take the controller out of the adapter, connect it with the board containing the DHT22 sensor and feed it with 5V from a power supply. One should see 2-3 LEDs light up. Shortly after the new device should appear as connected in ESPHome at which point the configuration of the device can be extended with options to tell the controller what kind of sensors are connected and with what kind of name it should be reporting the values to Home Assistant.

sensor:
  - platform: dht
    pin: GPIO2
    model: DHT22_TYPE2
    temperature:
      name: "Balcony Temperature"
    humidity:
      name: "Balcony Humidity"
    update_interval: 60s

Once added, save the configuration and click the "Install" button to remotely update the configuration on the device via the wireless connection. If you look at the logs of the ESPHome component for about 60s it should eventually log the temperature and humidity it just collected via the DHT22 sensor.

[13:13:26][D][dht:048]: Got Temperature=15.5°C Humidity=80.3%
[13:13:26][D][sensor:093]: 'Balcony Temperature': Sending state 15.50000 °C with 1 decimals of accuracy
[13:13:26][D][sensor:093]: 'Balcony Humidity': Sending state 80.30000 % with 0 decimals of accuracy

Assembled board & controller without the case

At this point I knew that the components and network connection worked as intended and that I can continue with the integration of it into the case. For the case I've used a modified version of Andreas Spiess's configurable 3d printable box with an arm that ensures the DHT22 sensor is far enough away from the controller and power supply to not be affected by it.

The case requires the DHT22 to be de-soldered and extended which is a bit finicky.

De-solder the DHT22 sensor from the board

After a bit of fiddling this is the end result just prior to clicking the box shut.

Finished integration of the DHT22 sensor board with ESP8266 and power supply into the 3D printed case

I've used some double-sided tape to fix the boards to the case, used a cable tie to ensure the power cord isn't pulling too much on the power supply and finally used some heat shrink tubing for the sensor connections just to be on the safe side. Worth noting, while I did write that this sensor goes onto the balcony, it's not intended to be operated in a wet environment as both the sensor is exposed and the 3d printed case isn't waterproof.

Published: 2024-10-13

Tagged: ESP8266 DHT22 Home Assistant Microcontroller ESPHome Smart Home

Archive