·Engineering

The Capstone Pivot: Real-World Specs, USB HID, and the ESP32-S3

Upgrading the learning roadmap into a full-stack capstone project by adopting a commercial Upwork specification and upgrading to the ESP32-S3.

In my last post, I laid out a foundational roadmap to shake off the rust and get back into the rhythm of ESP-IDF and embedded C/C++.

But let's be real: standard tutorials only take you so far. To build Hikmatron Systems into a company capable of delivering complete, end-to-end hardware and software solutions, I needed a project that forced me out of the microcontroller vacuum and into full-stack device integration. I needed a real-world problem.

The Catalyst: A Commercial Blueprint

While browsing Upwork the other day, I stumbled across a job posting that perfectly fit the bill. A UK-based sim racing hardware startup was looking for a C++ developer to build the backend utility for their flagship direct-drive steering wheel.

The requirements were highly specific:

  • Robust USB HID communication supporting 1000Hz polling.
  • A Firmware Update Manager to flash the wheel.
  • A Calibration Module for dual-clutch bite points and button mapping.
  • A Profile Manager to save settings directly to the wheel's onboard memory.
  • A cross-platform C++ UI using the Qt framework.

I am not applying for the job. Instead, I am stealing the specification.

Using a real, paid job description as a blueprint for a capstone project is the ultimate way to prove capability. It removes the guesswork of "what should I build?" and replaces it with strict, commercially viable constraints. It bridges the gap between raw electrical engineering and high-level software design—exactly the domain Hikmatron Systems operates in.

The Hardware Pivot: Enter the ESP32-S3

To build this MVP accurately, I hit an immediate hardware bottleneck. The classic ESP32 boards I have lying around my workspace do not have native USB hardware; they communicate with my Mac via a USB-to-UART bridge chip.

To achieve the true USB HID communication that the spec demands, serial over UART won't cut it. So, I am pivoting the hardware. I am getting my hands on an ESP32-S3. Because the S3 features native USB OTG support, it will allow me to utilize the TinyUSB stack to configure the board as a genuine Custom USB HID device, just like a commercial racing wheel.

The Capstone Roadmap

This new goal effectively supercharges my original learning plan. The basics are still there, but they are now directed toward a concrete final product. Here is the revised, end-to-end roadmap for this capstone:

Phase 1: Bare Metal & Acquisition

We still start with the physical inputs. I’ll wire up potentiometers and tactile switches to simulate the steering, clutch, and wheel buttons. The focus here is writing FreeRTOS tasks in C to continuously read ADC values and apply software debouncing, passing that data safely using FreeRTOS queues.

Phase 2: The 1000Hz USB Pipeline

This will be the proving ground. Using the ESP-IDF TinyUSB component, I will configure the ESP32-S3 as a custom HID device. The challenge will be packing the SimState structs (steering angle, clutch, buttons) into HID reports and optimizing the FreeRTOS tasks to push packets at that aggressive 1ms (1000Hz) polling rate over to my Mac.

Phase 3: Non-Volatile Storage (NVS) & State

The spec requires users to save calibration settings directly on the wheel. I’ll dive into the ESP-IDF NVS library to store min/max/center calibration values, allowing the board to normalize the raw ADC data before it even hits the USB cable.

Phase 4: The C++/Qt Desktop Utility

Switching hats from firmware engineer to desktop developer. I’ll fire up Qt Creator on macOS to build the configuration utility. This means integrating hidapi or Qt's native HID classes to catch that 1000Hz stream, and building a functional UI to handle center calibration, bite-point setting, and live telemetry.

Phase 5: The Bootloader (Boss Level)

The spec asks for a firmware update manager. While ESP-IDF makes Wi-Fi OTA updates fairly straightforward, executing a wired update over that same USB connection to flash new code into the application memory space will be the final, most complex hurdle of the project.

Time to Build

This is no longer just an exercise in shaking off the rust; it is a full-scale prototype build. The environment is ready, the ESP32-S3 is on its way, and the commercial spec is locked in.

Next stop: wiring up the hardware and getting the FreeRTOS acquisition tasks running. Stay tuned.