![]() |
OpenSourceSimWheelESP32
Open-source wireless steering wheel/button box for ESP32 boards
|
The whole sim wheel/button box system has been divided into pieces called subsystems. Each subsystem performs a particular function and is composed both by hardware and (sometimes) software. A description of each subsystem is available below. In order to build your own setup, follow a few simple steps:
Follow the links to get a detailed description of each subsystem:
This project support two kinds of clutch paddles:
Depending on how much space is available in the wheel's case, you have the choice to build all the subsystems in a single perfboard, or split them into several perfboards at the cost of extra wiring.
.diy file for each subsystem. Copy-paste whatever you need to your own project file. Use the "edit" menu since keyboard shortcuts does not seem to work. You may also start from a predefined setup.This project includes some PCB modules that you can benefit from. These will help to reduce build time and effort.
Arduino's sketch named CustomSetup is the place where you build your own firmware by modifying a few specific lines of code. You may want to make a copy first to prevent your customized code from being deleted after updating. To make a working copy:
src/Firmware folder.Then, there are a few steps:
Configure inputs:
As shown for each subsystem, a call to a function in the inputs namespace will enable them. You must also assign a unique "input number" to each input, in the range from 0 to 63. If you fail to provide valid input numbers, the firmware will not boot up. Each input number corresponds to a certain position in a pin header in your hardware design. Some input numbers have a certain meaning in the hosting PC.
inputHub namespace, as explained below. Edit the body of simWheelSetup() and place the required calls at the end of it. All of those mappings are optional, but take care not to build a non-functional firmware. Do not assign two functions to the same input numbers. Where available, do not use a combination of input numbers which can not be activated at the same time. Do not map a specific function to non-existent input numbers. If you choose not to map those specific functions, they are still available thanks to the companion app.Note: "..." means other code not explicitly shown.
A DPAD is optional. Despite this function is designed for funky switches and directional pads, it may be assigned to any input, including rotary encoders and push buttons. Place a call to inputHub::dpad::inputs():
For example, let's say the button matrix contains the input numbers 20, 22, 25 and 28:
Each time this function is activated, the working mode of the DPAD will move to the next one: navigation controls, regular buttons and back to the first mode. There is no point on this if there is no DPAD.
Assign a combination of input numbers to activate this function by placing a call to inputHub::dpad::cycleWorkingModeInputs(). There is one parameter: a sequence of input numbers between braces. All the inputs have to be active at the same time, and none of the others.
For example:
Clutch paddles are optional. You can have analog or digital clutch paddles. They work just the same.
Place a call to inputHub::clutch::inputs(). Each parameter (there are two) is the input number assigned to a clutch paddle. For example, let's say the button matrix contains input numbers 45 and 46:
Now, those input numbers may work as clutch paddles depending on user preferences.
It works the same for analog clutch paddles, but no existing input number is required, as shown in the following example:
Now, the analog clutch paddles may work as input numbers 45 and 46 depending on user preferences.
This feature is optional. Bite point calibration is also available in the companion app.
Place a call to inputHub::clutch::bitePointInputs():
For example (input numbers 34 and 35):
There is no point on this if there are no clutch paddles.
You may assign this function to any number of buttons (or none). Place a call to inputHub::altButtons::inputs(). There is one parameter: a sequence of input numbers between braces.
For example:
Any of the given input numbers will engage alternate mode when activated, except if they are set to work as "regular buttons" by the user.
Each time this function is activated, the working mode of the clutch paddles will move to the next one : F1-style clutch, autonomous axes, alternate mode, regular buttons, launch control (left paddle is master), launch control (right paddle is master) and back to the first mode. There is no point on this if there are no clutch paddles.
Assign a combination of input numbers to activate this function by placing a call to inputHub::clutch::cycleWorkingModeInputs(). There is one parameter: a sequence of input numbers between braces. All the inputs have to be active at the same time, and none of the others. For example:
Each time this function is activated, the working mode of the "ALT" buttons will move to the next one: alternate mode, regular buttons and back to the first mode. There is no point on this if there are no "ALT" buttons.
Assign a combination of input numbers to activate this function by placing a call to inputHub::altButtons::cycleWorkingModeInputs(). There is one parameter: a sequence of input numbers between braces. All the inputs have to be active at the same time, and none of the others.
Note that the following input numbers have a special meaning in Windows:
This project provides several connectivity choices:
To choose a connectivity option, locate the following lines in your copy of CustomSetup.ino:
Comment out all of them except for your choice. For example:
If your custom firmware is not based on CustomSetup.ino, place a call to hid::connectivity() and pass the connectivity option as parameter.
Connectivity::DUMMY: no connectivity (for troubleshooting).Connectivity::BLE: BLE-only.Connectivity::USB: USB-only. If your device does not support USB-OTG, it won't boot.Connectivity::USB_BLE: combined BLE and USB. This is the default and recommended option.Connectivity::USB_BLE_EXCLUSIVE: combined BLE and USB. The same as the previous option but...BLE connectivity is also available via the NimBLE wrapper from h2zero. You must install the h2zero/NimBLE-Arduino library in this case. This choice will be removed after ESP32-Arduino version 4.0.0 is released. USB connectivity does not work within this choice.
In order to use this:
hid_USB_BLE.cpp and replace with hid_h2zero.cpp Those file names are case-sensitive.For security concerns, the user can lock or unlock configuration changes coming from any PC application (including the companion app). This is a security precaution to stop unauthorized configuration modifications caused by rogue programs.
Assign a combination of input numbers to activate this function by placing a call to inputHub::securityLock::cycleWorkingModeInputs(). There is one parameter: a sequence of input numbers between braces. All the inputs have to be active at the same time, and none of the others. For example:
The state of the security lock is changed on each activation, then saved to flash memory after a short delay.
This feature is optional.
Regardless of the input numbers assigned to each input hardware, the end user can set up a custom input map using the companion application. Unlike firmware defined input numbers, user defined input numbers are in the range [0,127]. By default, the input map follows this rule:
If you have only a few buttons, their user-defined input numbers will be spread over 128 values. However, you can set a different default input map. To the end user, your custom input map is considered the "factory default". There are several, non-exclusive, options.
Make a single call to inputMap::setOptimal() (no arguments). The input map will follow this rule:
For example, let's say you have the input numbers 1, 3 and 5 (and no others) assigned to your input hardware. This method will set the following input map:
| firmware-defined | user-defined | user-defined (alternate mode) |
|---|---|---|
| 1 | 1 | 7 |
| 3 | 3 | 9 |
| 5 | 5 | 11 |
Make calls to inputMap::set() with the following parameters (from left to right):
Make as many calls as you need. For example:
When:
Make calls to inputMap::set() with the following parameters (from left to right):
This is a shortcut. Make as many calls as you need.
This feature is optional.
The neutral gear is an input number that is not assigned to any input hardware (but this is not mandatory). When the end-user presses a particular combination of buttons, the neutral gear is reported instead. The end-user must then fully release that combination for those buttons to behave normally.
Make a call to inputHub::neutralGear::set() with the following parameters (from left to right):
This function is intended for shift paddles, but you can assign this function to any combination of input numbers. "Neutral gear" is the intended use for this "virtual" button, but it is not a firmware function. You must assign the virtual button to neutral or any other function in-game.
Note that the neutral gear will be engaged if the button combination is pressed and any of the others.
The "virtual" input number is affected by the alternate mode and can be mapped to other user-defined input numbers.
Example:
Let's suppose this sequence of events:
Once both shift paddles are released, they will be reported as buttons 1 and 2 again.
Some of the circuit designs may show very small resistors and diodes which does not fit the real ones. This is not a mistake. They must be placed in "vertical" layout, so they lie in a minimal surface of the perfboard.

Note that some components may be placed on top of others to save more space.