# WELCOME

Welcome to SimHub manual.\ <br>

Do not hesitate to reports bugs or features requests [here](https://github.com/zegreatclan/SimHub/issues)

Downloads : <http://www.simhubdash.com/>

> <mark style="color:red;">We are slowly migrating the documentations to this website. You can find all the unmigrated documentations on the SimHub's</mark> [<mark style="color:red;">Wiki</mark>](https://github.com/zegreatclan/SimHub/wiki)<mark style="color:red;">. Thanks for your understanding.</mark>


# Getting started

## Introduction

The SimHub Motion Addon is an addon that takes advantage of the wide range of simulators supported by SimHub. A dedicated license is required to use the addon in addition to SimHub licence.

> <mark style="color:red;">For evaluation purposes, limited-time sessions are available so you can test it and judge for yourself.</mark>

## Enabling the addon

The SimHub motion addon can be enabled in a few simple steps

Download and install the latest Simhub from <https://www.simhubdash.com/download-2/>

Once SimHub is installed and running go into "Add / Remove features" in the left menu

<figure><img src="/files/7qMET7gMBplMNs1wdzc4" alt=""><figcaption></figcaption></figure>

Enable the motion addon

<figure><img src="/files/whjPBkBmSAvuuAvYgiFx" alt=""><figcaption></figcaption></figure>

The motion Add-on is now enabled, you can find it in the left menu !

## Addon licence activation

If you already own a SimHub and an Addon licence [you can follow the instructions here to activate it](https://manual.simhubdash.com/motion-addon/addon-licence-activation)

## Geometry and controller(s) choice

It's now time to configure your platform.

Go into the motion addon

<figure><img src="/files/tIVjSbn5XogHlj9MPIo8" alt=""><figcaption></figcaption></figure>

Click on Configure your platform

<figure><img src="/files/yj3sLhj7hOevYoSiKzNi" alt=""><figcaption></figcaption></figure>

The configuration assistant will now start

### Choose your platform geometry

The platform is described as a primary geometry and "accessories." At this stage, even if your setup uses multiple controllers or devices, just select all the options you own (e.g., 3DOFs + traction loss + belt tensioner) and click OK.

A few examples:

* An Eracing Lab RSMEGA+ is a 3DOFs 4-corner platform.
* A DOF Reality H3 platform is a 2DOFs left/right setup with a dedicated rear traction loss axis.

> <mark style="color:red;">To maintain correct geometry, only a single primary geometry (3DOFs/2DOFs) is supported. Stacked setups, such as a seat mover on top of a 3DOFs platform, are not supported.</mark>

<figure><img src="/files/9MVq99oPVvT2h7yyWtBq" alt=""><figcaption></figcaption></figure>

### Choose your controllers

A list of standard controllers will be displayed. Pick the one you need. If you require multiple controllers, select the first one you need and validate (you can add more controllers later).

Some additional controller presets are available separately for warranty or licensing reasons. You can download them from <https://github.com/SHWotever/SimHubMotionPresets>.

> <mark style="color:red;">If you own any discontinued Thanos controllers (MDBOX, Nano, etc.), please use the Thanos AMC Open Hardware Controller.</mark>
>
> <mark style="color:red;">Dof Reality M2/H2/H3/P2/P3 are using a standard SMC3 controller.</mark>

<figure><img src="/files/rBFFWQQ1JxilEBXgiPsE" alt=""><figcaption></figcaption></figure>

### **Settings Review**

Simhub will now ask you for every components the essentials settings : critical dimensions, serial ports ...

Those views are filtered on what matters for a quick start.

You'll be asked

* Your hardware critical dimensions : see [#geometry-configuration](#geometry-configuration "mention")
* Your controller(s) serial port port and axis mapping if relevant : see [#controller-configuration](#controller-configuration "mention")

<figure><img src="/files/8xepoWnArH7gUFCgFO1V" alt=""><figcaption></figcaption></figure>

**Congratulations ! You have now "created" your motion platform.**

<figure><img src="/files/3NhcAEIztYvB0RdZbeLe" alt=""><figcaption></figcaption></figure>

## Setup Essentials

During the setup and or later you can adjust some aspects of your hardware.

### Controller configuration

> <mark style="color:red;">The following instructions may vary slightly depending on the specific controller used and its features. The steps must be repeated for each controller.</mark>

#### Assign all the axis

In a controller Click on "Edit Axis Assignment" and assign each output of your controller to the corresponding axis and direction (reverse if necessary).

If you're unsure about the direction of an axis, you can test it in the next step.

<figure><img src="/files/ny74JCCWk9TDBSOOYIRu" alt=""><figcaption></figcaption></figure>

#### Test your axis by clicking on test all platform axis

It's extremely important to verify the directions of all the axes on this screen.

During testing, **they must move in the direction specified in the legend**. SimHub assumes you configure them correctly. If any directions are incorrect, close and adjust the reverse direction in the previous screen, then try again.

> <mark style="color:red;">Pay special attention to the directions of the</mark> <mark style="color:red;">**TRACTION LOSS**</mark><mark style="color:red;">,</mark> <mark style="color:red;">**SURGE**</mark><mark style="color:red;">,</mark> <mark style="color:red;">and</mark> <mark style="color:red;">**2DOFs Left and Right**</mark> <mark style="color:red;">axes (e.g., seat movers).</mark>

<figure><img src="/files/LRPxXViMH0VKmzO2u9bh" alt=""><figcaption></figcaption></figure>

### Geometry configuration

It's now time to specify your platform and actuators dimensions. This step ensures two main objectives:

* Accurate reproduction of real angles and distances.
* Avoidance of frame over-constraints: incorrect geometry and dimensions can "twist" your simulator, which we want to avoid!

#### Actuators and frame dimensions

For all parts of your motion platform, ensure the dimensions and actuator stroke are set accurately.

All dimensions are expressed in millimeters !

> <mark style="color:red;">The belt is a special axis that only works in percentages, so no dimensions are required. A specific calibration assistant is provided.</mark>

<figure><img src="/files/itq8YwHDaWiPuAJrogx9" alt=""><figcaption></figcaption></figure>

## Your first moves

### Enable motion

You can now activate your motion platform by clicking "Enable Motion".

> <mark style="color:red;">At this point, nothing will move. SimHub will only connect to the controller and check the configuration integrity.</mark>

<figure><img src="/files/Qiw6lLRxCFbYTcSnHd9O" alt=""><figcaption></figcaption></figure>

### Manual testing

You can now open the manual control panel and test all your orientations,Pitch, roll, belt, heave ...

> <mark style="color:red;">If any axis moves in the wrong direction, please revisit</mark> [#assign-all-the-axis](#assign-all-the-axis "mention")

<figure><img src="/files/fIjOpTLrvmIAbV09duLz" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/PbkvC7852LpRq0Idt4ic" alt=""><figcaption></figcaption></figure>

### Success !

You can now, close all the dialogs

## Before your first game launch

### Reduce the gain at first

Before taking your first "ride", it's highly recommended to reduce the gain to 40\~50%. The motion will be intentionally dampened, but it's easier to handle weak motion than motion that's too strong.

> <mark style="color:red;">Increase the gain progressively as you gain confidence and experience.</mark>

<figure><img src="/files/BGNfk4g7WZ5V1TcszX4y" alt=""><figcaption></figcaption></figure>

### Enable the effects you need

<figure><img src="/files/YhdbDDkINavkF35bUpUc" alt=""><figcaption></figcaption></figure>

You are now ready to start and test your game.

## Reconfigure the platform

If you made a mistake during the setup, or simply added / changed some hardware you can reconfigure it easily.

Use the output settings button to enter the configuration dialog

<figure><img src="/files/2A06pfoeDAfzdP9fXXDv" alt=""><figcaption></figcaption></figure>

> <mark style="color:red;">Most of the settings will be locked if the motion platform is active, click on "Disable motion" to get access to all the settings</mark>

### Change the geometry or add/remove an axis

<figure><img src="/files/DlUvYa0PsLG2YMU0NnKr" alt=""><figcaption></figcaption></figure>

### Add a new controller

Click on "Add controller"

<figure><img src="/files/HbcwzOzMbEH3UQ2FmzOJ" alt=""><figcaption></figcaption></figure>

### Remove a controller

Open the controller menu you need and click on delete controller

<figure><img src="/files/7135zQRmjoQnvTdD304U" alt=""><figcaption></figcaption></figure>


# Addon licence activation

## Prerequisites

Since Motion is an addon, you will need the following:

* The main SimHub license. If you don't already own it, [it can be purchased here](https://www.simhubdash.com/get-a-license/).
* The Motion Addon license, which can be purchased [here if you don't own it yet](https://www.simhubdash.com/simhub-motion-addon-licence/).

If you don't own already any of those, you can buy a 2-in-1 licence (Motion pack) here : <https://www.simhubdash.com/simhub-motion-addon-licence/>

Each license will be delivered as a ".lic" file attachment to your purchase email. If you don't receive it within 24 hours, please check your spam folder. If you still haven’t received it, please contact us at <https://www.simhubdash.com/simhub-contact/>, and we’ll resolve the issue promptly.

Once received, save the files to your device (depending on your email client, you may need to right-click the attachment and select "Save As").

## Activation

Open SimHub and go to the Motion Addon "Global Settings" section. Here, you will see the current status of your two licenses.

<figure><img src="/files/m6rFu36oAQiH7c7w2TBM" alt=""><figcaption></figcaption></figure>

Click on "Manage Licenses" then "Add licence"

<figure><img src="/files/qhrTiF5VNAehxDXW895r" alt=""><figcaption></figcaption></figure>

Select your SimHub license file and click OK

<figure><img src="/files/hhJgZIu30fRiO0pFxkkP" alt=""><figcaption></figcaption></figure>

Repeat the same operation for the second licence

You can now verify that both licenses are installed.

<figure><img src="/files/bMIukUeS6eSrqRZWhBUy" alt=""><figcaption></figcaption></figure>

Once done, you can close this dialog. SimHub and the Motion Addon are now successfully activated.

<figure><img src="/files/fWPppN0iUsYEcmNqoPpL" alt=""><figcaption></figcaption></figure>

**Thanks again for using SimHub.**


# Supported motion setups

Simhub considers the platform as one "primary" platform and "addons" (**Additional supported axes)**

If needed the "primary" platform can be disabled (For instance Belt tensioner only setups)

### Supported primary platforms

* **6DOF Stewart platforms**\
  Linear or rotary actuators with real-time 3D configuration preview

<figure><img src="/files/IR8ITyadqNvcdzKIok8O" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/iaRPzOzwEeys4chXx6EJ" alt=""><figcaption></figcaption></figure>

* **3DOF platforms**\
  4-corner setups, 2-front + 1-rear or 1-front + 2-rear configurations

<figure><img src="/files/TTvuHbWru5yG3yQXa7SW" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/J2NnvOqlOGFya2GBMOwR" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/vCZ3kHkxQGs9ZeBzOqP9" alt=""><figcaption></figcaption></figure>

* **2DOF setups \***\
  Left/right actuators at the front or rear

<figure><img src="/files/gBictqoghWcrWV1vtBrO" alt=""><figcaption></figcaption></figure>

* **4Dofs linear setups**\
  Using four linear actuators, the rear actuators arrangement provides a Yaw capability.

<figure><img src="/files/HRLjJ3ezra4zzmVuc91s" alt=""><figcaption></figcaption></figure>

* **YawVR geometry**\
  A geometry dedicated to YawVR yaw/pitch/roll structure and supoporting infinite yaw

<figure><img src="/files/NxvVdcLwyBGEFJdpoTqt" alt=""><figcaption></figcaption></figure>

* **6Dofs pose output**\
  A kinematic bypass for hardware supporting a direct 6dofs pose output without any kinematic actuators positions

<figure><img src="/files/E0tjoZZj6NtUeIlOuop3" alt=""><figcaption></figcaption></figure>

> \* This covers setups like DofReality H2/H3/M2/M3\* and most two actuators seat movers

### **Additional supported axes/components**

* **Stacked seat mover**\
  Another complete seat mover setup can be stacked on your primary platform (IE 3Dofs etc ...).<br>
* **Dedicated surge axis (Up to two)**\
  Installed on top or below the primary platform \*\*<br>
* **Dedicated sway axis**\
  Installed on top or below the primary platform \*\*<br>
* **Dedicated heave axis**\
  **One heave actuator allowing to move the platform up and down independently**<br>
* **Rear traction loss axis**\
  Installed below the primary platform<br>
* **Dual front/rear traction loss**\
  Installed below the primary platform \*<br>
* **Belt tensioners**\
  Single or dual motor setups<br>
* **Wind**\
  **1,2 or 3 wind channels supported with complete profiles and settings (Left and/or right, and/or center channels)**

> \*\* If the platform is installed on top of the primary platform (moving when 3/2 dofs moves) the motion compensation computation will be altered and provide inaccurate results


# Supported controllers

SimHub offers support for a growing number of motion and feedback controllers. While not every device is supported out of the box, the platform includes native integration for several popular controllers and provides flexible options for integrating custom or unsupported hardware through serial or UDP output.<br>

* Thanos AMC : [link](https://www.thanos-motion.com/products/thanos-amc-controller-rgb-v1-4/)
* Thanos T4U : [link](https://www.thanos-motion.com/products/thanos-4-u/)
* Thanos AMC MDBOX and Open Hardware (Discontinued)
* VNM Controller : [link](https://vnmsimulation.com/vnm-motion-controller)
* PT-Actuator CAN Controller : [link](https://www.pt-actuator.com/)
* SimHub DIY belt tensioner : [link](https://www.simhubdash.com/diy-belt-tensionner/)
* SMC3 controller : [link](https://www.xsimulator.net/community/threads/smc3-arduino-3dof-motor-driver-and-windows-utilities.4957/)
* Trak Racer 3DOF Motion System support : To be released
* Thermaltake GM5 3DOF Motion System support : [link](https://www.thermaltake.com/gm5-3dof-motion-system.html)
* Cammus Dynamic racing simulator : To be released
* Dyadic SCN5/6
* Configurable serial output for DIY or unsupported controllers : [how to](/motion-addon/supported-controllers/generic-serial-controller)
* Generic UDP output for DIY or unsupported controllers \*
* And more incoming !

**If needed simhub can support controllers aggregation :** Multiple controllers can be used to provide a single motion platform and motion experience

> **\* Note:** Some controllers may require custom configuration or firmware. If your hardware is not listed, it may still be possible to integrate it using the generic serial or UDP output features — but only if the communication protocol is known and documented. Integration requires either manufacturer-provided documentation or a clear understanding of how the device expects to receive data.

Some Controllers presets are available separately in respect of their own licence or future proof warranty reasons : [Repository](https://github.com/SHWotever/SimHubMotionPresets)

* SimFeedback-AC-Servo controller (SFX100)

#### Not Supported (and unlikely to be)

These controllers use closed or proprietary protocols and/or do not allow (new) third-party software integration:<br>

* Next Level Racing Motion Platforms
* Motion Systems (e.g., Qubic System)
* DBox
* ProSimu (PRS Range), older "SCN5/6 based" ProSimu are supported
* Simrig.se
* Simxperience (Gseat, GBelt, etc ...)


# Generic serial controller

This guide explains how to configure and interface a custom motion controller using serial communication. It is intended for users integrating third-party hardware or building DIY motion systems.

> ⚠️ This system cannot drive arbitrary hardware. You must know and understand the serial protocol expected by your controller (message structure, command format, required timing, etc.).

## Add a New Controller

Start by creating a new Generic serial output<br>

<figure><img src="/files/R1ng7kWusRKcPCsMkeyg" alt=""><figcaption></figcaption></figure>

Assign the serial port and enter the Serial commands configuration\ <br>

<figure><img src="/files/IUXJOd7eXKYXQRwCyoUR" alt=""><figcaption></figcaption></figure>

## Protocol configuration

### Serial Settings

Configure the serial port settings to match your controller:

| Setting                                       | Description                                                                                                                                |
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| **Baudrate**                                  | Common values include 9600, 38400, 115200, etc.                                                                                            |
| **Stop bits**                                 | Usually set to `1` or `2`, depending on the controller.                                                                                    |
| **Data bits**                                 | Typically set to `8`.                                                                                                                      |
| **Parity**                                    | Choose `None`, `Even`, or `Odd` as required.                                                                                               |
| **Idle delay after serial port opening (ms)** | Optional delay (in milliseconds) after opening the serial port before sending any commands. Useful if the device needs time to initialize. |
| **RTS / DTR**                                 | Enable these only if your device requires them to boot or begin communication.                                                             |

> Many modern USB-to-serial chips require **RTS** to be enabled, and sometimes **DTR** as well, to properly trigger communication.\
> However, on older usb to serial-based Arduino boards, enabling **DTR** will often cause the board to **reset** on connection, making it temporarily unavailable.\
> In such cases, you can use the **Idle delay after serial port opening** setting to allow the device enough time to fully reboot before any data is sent.

### Protocol Settings

#### 3.1 Number of Controlled Axes

Set how many axis values you want to send to the controller (e.g., 6 for a 6DOF platform).

#### 3.2 Axis Output Format

Choose how axis values are formatted in the serial output:

* **Binary** – Sent as raw bytes (e.g., `0xFF`)
* **Decimal (string)** – Sent as text (e.g., `"127"`)
* **Hex (string)** – Sent as hex-encoded string (e.g., `"7F"`)

#### 3.3 Axis Resolution (Bit Range)

Defines the numeric resolution of each axis. It affects the value range produced by placeholders like `<Axis1>`. Choosing a higher resolution than the hardware is capable of improves flexibility and avoids future limitations.

| Bits | Range   | Center Value | Bytes (Binary Format) | Typical Use                                              |
| ---- | ------- | ------------ | --------------------- | -------------------------------------------------------- |
| 8    | 0–255   | 127          | 1 byte                | Only if your hardware explicitly requires 8-bit values   |
| 10   | 0–1023  | 511          | 2 bytes               | Arduino analog resolution; reasonable for smooth control |
| 12   | 0–4095  | 2047         | 2 bytes               | Balanced precision and compatibility                     |
| 16   | 0–65535 | 32767        | 2 bytes               | Recommended for most new custom protocols                |

**Recommendation:** Use 16-bit resolution if you're designing your own firmware/protocol. The slight increase in data size is worth the precision and ease of scaling.

### Command Phases

You can define different messages for three phases of controller activity:

| Phase                      | Description                                                                                                                 |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| **Startup Commands**       | Sent once when the controller is activated (e.g., SimHub motion connects, axis test starts). Often used for initialization. |
| **Motion Update Commands** | Sent repeatedly during active motion updates (typically once per frame).                                                    |
| **Shutdown Commands**      | Sent once when the controller is deactivated (e.g., SimHub disconnects, test stops). Used for safe shutdown or reset.       |

> #### When are commands Sent?
>
> Commands are only transmitted when the controller is actively in use:
>
> * When **axis assignation testing** is running
> * When **manual control** is enabled
> * When **game effects** are running
>
> If none of these are active, **no commands are sent**, even if the serial port remains open.
>
> SimHub may keep the port open while idle to:
>
> * Prevent other applications from taking control of the port
> * Allow for faster resume when motion is reactivated
>
> No serial data is sent during this idle period.

Each command allows:

* A customizable command string
* An optional delay (in ms)
* An optional "wait for response" before continuing

### Command Syntax

Use placeholders to insert dynamic data into your command strings.

#### Axis Placeholders

Axis values represent the computed actuator positions based on platform geometry and motion logic. The controller configuration in SimHub is purely focused on **communication** — it does not define or interpret motion roles (like surge, heave, or roll).

Each controller simply receives the values it is told to expect. The actual computation of those values is handled earlier in the SimHub pipeline using the platform's geometry and motion profile.

Use the following placeholders to represent axis values:

* `<Axis1>`, `<Axis1a>`, `<Axis1b>`, etc.

Repeat for each axis (e.g., `<Axis2>`, `<Axis3>`) depending on your axis count.

These placeholders reflect the current values of each axis in the selected output format (binary, decimal, or hex). They are case sensitive.

Two additional shortcuts for compatibility with other software exits

* `<Left>` shorthand for `<Axis1>`
* `<Right>`shorthand for `<Axis2>`

#### Hex Character Placeholders

You can insert literal byte values using the following syntax:

* Decimal byte: `<13>` (carriage return)
* Hex byte: `<0xFF>` (sync byte, for example)

These are inserted as raw bytes in binary output.

#### Setting Placeholders

If you define settings via the Protocol Control Panel (see below), you can insert them using:

```
<Setting,settingname,settingformat>
```

For example:

```
<Setting,speed,0.0>
```

### Examples

| Example                          | Description                                                                |
| -------------------------------- | -------------------------------------------------------------------------- |
| `<0xFF>Update<Axis1><Axis2><13>` | Sends a sync byte, followed by axis 1 and 2 values, then a carriage return |
| `Start<0xAA><0xBB>`              | Typical startup command using two header bytes                             |
| `Stop<10><13>`                   | Ends with a line feed and carriage return                                  |

### Protocol Control Panel (Optional)

You can define custom parameters that can be reused in your messages.

Available UI elements:

* **Textbox** – Free-form text
* **Checkbox** – Boolean flag
* **Slider** – Range selector
* **Combobox** – Dropdown menu
* **Group** – Logical grouping
* **Computed setting** – Dynamically calculated values

Use these with the `<Setting,...>` placeholder.

### Best Practices and Recommendations

* Use **higher resolution (12 or 16 bits)** for most new projects
* When debugging:
  * Use a **serial monitor** (e.g., RealTerm, Arduino Serial Monitor) for early testing
  * For deeper diagnostics, consider using a **serial sniffer** to observe actual communication without interfering (e.g., <https://freeserialanalyzer.com/> \* )
* Include **start/sync bytes** if your controller expects a specific header
* Use **delays** if your controller cannot handle rapid updates
* Avoid optimizing for byte count too early; prioritize readability and compatibility

> \* We’ve used Free Serial Analyzer for years (in its paid version); the free version (with some limitations) is often sufficient for basic troubleshooting.

### Limitations

* This feature does **not** automatically adapt to unknown hardware
* You must:
  * Know your controller’s protocol
  * Understand its timing and formatting
  * Test it manually during development

Failure to configure the protocol correctly may result in no movement or unexpected behavior.

## Axis assignment

Once the protocol configured, you can assign and test the axis with "Axis assignment"

<figure><img src="/files/lMVAt1IG0cdweainrJA1" alt=""><figcaption></figcaption></figure>

***


# Motion profile tuning

This guide explains how to tune a motion profile step by step, starting from a clean base and gradually layering effects in a controlled and predictable way.

<figure><img src="/files/M7AcPbmUBasiARjRRVzI" alt=""><figcaption></figcaption></figure>

### Prerequisite: Start from a Clean Baseline

Before tuning, reset all gains to remove hidden scaling:

* Set **Global Motion Gain** to **100%**
* Set **Effect Gain** for each motion effect to **100%**

This ensures you see the true response of your input tuning without amplification or damping. You'll reintroduce gain if needed later, but start clean.

<figure><img src="/files/yZmYUbH11I8aF6C6ctIb" alt=""><figcaption></figcaption></figure>

### Basic Effect Tuning

#### Adjust the Motion Scaling

> The most important step in tuning.

Motion scaling defines how game data is turned into movement.

> **"Take up to this much from the game → give up to that much on the platform."**

Each effect has:

* **Input Limit**: how much data it expects from the game
* **Motion Range**: how far the platform can move for that effect

<figure><img src="/files/BhzufKmV51O7YaNXylqS" alt=""><figcaption></figcaption></figure>

**🡐 Input Limit – Responsiveness**

* **Lower input** → more responsive (max motion reached quickly)
* **Higher input** → less responsive (requires more signal for full movement)

Tuning input is a balance between **reactivity** and **saturation risk**.

**🡒 Motion Range – Motion Contribution**

* Higher range = more physical movement
* Lower range = smaller effect presence (more room for others to mix)

This defines **how strong the effect feels,** not how quickly it reacts.

#### The Rule of 3 : A Practical Example

Let’s say the car reaches ±6° pitch while braking:

* Set **Input Limit** = 6
* Set **Motion Range** = 2 or 3

That gives realistic motion, avoids saturation, and leaves headroom for other effects like surge or heave.

**Pose-Based Effects (Pitch & Roll)**

For **Pitch** and **Roll**, game values represent a physical pose and your simulator mirrors that.

> Keep **Input Limit ≥ Motion Range**. You're not boosting the pose, just reproducing it.

This prevents exaggerated motion and keeps the experience grounded.

#### Tune the Smoothing

<figure><img src="/files/8utB4o7pRXi5tzfYXEpg" alt=""><figcaption></figcaption></figure>

Smoothing controls how clean or raw the motion feels:

* **Lower smoothing** = fast, detailed, potentially jittery
* **Higher smoothing** = soft, clean, but may feel lazy

Start with moderate values and adjust based on the effect type:

* Pitch/Roll: usually benefit from some smoothing
* Heave/Road vibration: better with less smoothing

#### Soft Limiter (Per-Effect)

The **Soft Limiter** applies to each effect individually.

It fades out motion smoothly when an effect reaches its limit, avoiding harsh clipping.

<figure><img src="/files/NaG4MCwEtMzxmNnE41VE" alt=""><figcaption></figcaption></figure>

**When to Use:**

* **Rare overflow?**\
  → Set a **lower range** (10–15%) for gentle damping
* **Frequent overflow?**\
  → Use a **higher range** (up to 50%) for smooth cushioning

> Use this to clean up individual effects. Not for total platform protection.

**Flight Sim Tip:**

Especially helpful for **Pitch and Roll** in flight sims **without washout** — allows continuous attitude motion without hitting a hard stop.

#### Repeat – Add Effects One by One

Enable your next effect and isolate it for tuning:

* Use **"Isolate this effect"** while tuning
* Repeat: **scale → smooth → test in mix**

Un-isolate when ready and see how it blends with existing effects.

> Rebalance if one effect dominates or disappears in the mix.

### Final Balance

Once all effects are active:

* If everything feels too strong, reduce the **Global Motion Gain**
* Avoid pushing each effect to 100% travel
* Use **Soft Limiters** to soften individual saturation
* Let **Pose Overflow / IK** handle global motion limits

### Flight Sim Specific : Washout Resetting Pose Safely

In flight simulators, aircraft can stay pitched or rolled for long periods. Without a reset mechanism, the simulator can eventually run out of travel. That’s where **Washout** comes in.

Washout is available on eligible effects and provides a way to **gradually return the platform to center** — even if the game is still in a pitched or rolled state.

> Think of it as a slow recentering force that works behind the scenes, invisible to the pilot.

#### How It Works

* The effect continues to respond as usual
* But over time, the **platform recenters** gradually when motion is sustained
* The washout speed determines **how fast this return happens**

#### Tuning Washout

Washout must be fast enough to prevent platform overflows… But **slow enough to be invisible** — you should never feel the platform "pulling back."

Typical tuning advice:

* Use on **Pitch**, **Roll**, and **Yaw** in flight sims
* Tune for a **gentle return** (slow smoothing) to keep realism

Washout can be added in "More effects option"

<figure><img src="/files/vRwrf0bkztFjqVE64VgU" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/HFYOLCzGVlk6QyHa7yN7" alt=""><figcaption></figcaption></figure>

> Washout is often unnecessary in racing — but essential in aircraft, where attitudes are held longer.

### Game-to-Game Portability

Good news: if you've followed this tuning method, your effects are already **based on real-world motion scales,** not arbitrary values.

That means switching to a different game of the **same category** (e.g. racing sim to racing sim) **won’t require starting from scratch**.

#### 🛠 What to Adjust:

* **Input Limits** may need light tweaking depending on how each game outputs data.
* **Smoothing** might be worth adjusting if the new game is noisier or more stable.

> ⚠️ Switching between **very different game types** (e.g. car sims vs flight sims) will likely require more than a light touch, especially due to sustained motion, lack of washout, or fundamentally different effect types.

As long as you're within the same simulation domain and the game provides meaningful telemetry, most of your tuning should carry over cleanly with just a quick adjustment pass.

### Understanding Gains and Global Controls

Once your tuning is solid, it's useful to understand how gain controls work across the system.

#### Gains Are Multiplicative

The final output of any effect is the result of **multiple gain layers multiplied together**. Understanding this helps avoid confusion when motion feels stronger or weaker than expected.

Gains are organized by hardware category:

* **Motion Gain** (Global) → Affects all motion platform output
* **Haptics Gain** → Affects tactile output (vibration, rumble, etc.)
* **Belt Gain** → For specific belt tensioner systems (if present)

Each category then has its own sub-gains. For example:<br>

* **Motion**\
  **Per platform component** (e.g. surge platform vs traction loss platform)\
  Recommended: keep these at **100%** for clarity, and do your tuning via effect scaling or the global gain.
* **Effect Gain**\
  Found on each effect block : Allows you to rebalance one effect's presence after scaling is tuned

#### Global Motion Smoothing

Above all effects, there’s also a **Global Motion Smoothing** setting. This adds a uniform extra layer of smoothing on top of all motion effects — useful for quickly taming a profile that feels too sharp or aggressive.

<figure><img src="/files/gM15YxXIvjSNSCMjlLdf" alt=""><figcaption></figcaption></figure>

Start low (10-20%) to soften things slightly without losing detail. You can always increase if needed.

### Bonus Tips

* Use **Live Charts** to visualize how effects behave in real-time
* Test in multiple driving scenarios (braking, curbs, slopes)
* A great profile is not about size — it’s about **clarity**, **blend**, and **control**

### Motion effects reference

SimHub automatically filters out any motion effects not supported by your hardware. Only compatible and usable effects are shown — so what you see is exactly what your platform can handle.

> Haptics effects are bound to the hardware capabilities to reproduce short high frequency movements. This characteristic can't be known and effects won't be filtered based on such hardware limits

The effect name always describes the **input source**. When converted to a different platform motion, it uses a "to" name (e.g. *Surge to Pitch* means using surge input and converting it to pitch movement).

Some effects are **only visible in flight simulators,** like pitch/roll rate, because they’re not meaningful in racing sims. Don’t worry if you don’t see them in every profile.

#### Pitch

Tilt forward/backward **based on the vehicle or aircraft's pose,** not acceleration.

* Racing: car body tilt when braking or cresting a hill.
* Flight: aircraft nose-up or nose-down orientation.

#### Roll

Tilt left/right from the vehicle or aircraft’s pose.

* Racing: car leaning into corners.
* Flight: bank angle during turns.

#### Surge

Forward/backward movement **from acceleration or braking forces**, not orientation.\
Simulates the push or pull you feel when speeding up or slowing down.

#### Surge to Pitch

Converts surge (acceleration/braking forces) into pitch angle.\
Useful when the platform can’t move linearly but can tilt.

#### Sway

Side-to-side movement **from lateral forces :** cornering, side wind, or skidding.\
Represents the feeling of being pushed sideways in your seat.

#### Sway to Roll

Converts sway forces into roll tilt.\
A workaround for platforms without direct sway capability.

#### Heave

Vertical movement.\
Simulates bumps, road texture, turbulence, and elevation changes.

#### Yaw

Rotation around the vertical axis.

* Racing: oversteer, traction loss, or rapid changes in heading.
* Flight: rudder input and coordinated turns.

> 💡 **Washout is always required** for yaw to prevent the platform from drifting off-center over time, since yaw can be sustained in both racing and flight.

#### Rear Traction Loss to Yaw

Uses slip angle (difference between travel direction and heading) to simulate rear-end sliding as yaw rotation.

> 💡 **In flight sims it will trigger during aggressive yawing using rudder pedals.**

#### Rear Traction Loss to Roll

Same slip angle cue as above, but expressed as a sideways tilt instead of rotation.


# Integrated utilities

## 3D View

For 6Dofs start platform a 3D view option is available allowing to visualize your platform motion in real time

<figure><img src="/files/dM5R5ykNoegHIEzP3O4s" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/bNgJPKXHZ81G3xBRqR7l" alt=""><figcaption></figcaption></figure>

## General utilities

Along the profiles you will find a set of utilities allowing to understand how your platform or the game behaves, click on tools on the right of the profile list

<figure><img src="/files/qEzh2hXtht3T9nX0gzVC" alt=""><figcaption></figcaption></figure>

### Profile compact view

This views allows to visualize effects activity and basic settings in a compact half transparent format allowing to visualize it while you drive/flight

<figure><img src="/files/oo0ByEFXmJLzZoElbIAc" alt=""><figcaption></figcaption></figure>

### Effective motion simulator orientation view

This view shows the simhub computed position for your simulator (it's not the game metrics) as well as your actuators positions and "overflows"

Overflows are mitigated by Simhub some punctual overflows are not critical and just means you are using your whole platform capacity

<figure><img src="/files/Hzd7tAEzHt1an6L9J9yu" alt=""><figcaption></figcaption></figure>

### Game data view

Shows all the game telemetry channels as it gives it. This does not represent your motion platform position but the real-time data the sim is providing.

<figure><img src="/files/4QDBSUDnWeyuVT5wajsn" alt=""><figcaption></figcaption></figure>


# OpenXR Motion compensation

## Introduction

Motion compensation is designed to cancel out the VR headset movements caused by your motion platform. For example, if the platform rolls to the left, motion compensation will apply a virtual roll to the right, keeping your viewpoint stable in VR.\
\
As of now, no official method for motion compensation is provided by VR frameworks. For Open XR BuzzteeBear aka Sebastian Veith does provide us a motion compensation layer.

Motion compensation on OpenXR wouldn’t exist without his work. Don’t hesitate to support BuzzteeBear’s efforts [in any way you can!](https://github.com/BuzzteeBear/OpenXR-MotionCompensation#contact)

> <mark style="color:red;">SimHub only provides motion data to external motion compensation software. We are not responsible for how these tools behave, nor can we guarantee their stability or compatibility. Results may vary depending on the game, the VR headset, and the motion compensation software itself. Use at your own risk.</mark><br>
>
> <mark style="color:red;">For simplicity, in this guide we will use the following abbreviations:</mark>
>
> * *<mark style="color:red;">**"Open XR motion compensation"**</mark>* <mark style="color:red;">to "</mark>*<mark style="color:red;">**MC" or "MC layer"**</mark>*
> * *<mark style="color:red;">**"Open XR motion compensation center or rotation" to "COR"**</mark>*

## SimHub and Open XR MC roles

SimHub provides the "computations": based on your dimension inputs and the current motion target position, it estimates the required compensation (Heave, Sway, Surge, Yaw, Pitch, Roll). Those computations can be mixed with a physical sensor (see [WitMotion sensor for Motion compensation](/motion-addon/witmotion-sensor-for-motion-compensation))

This estimation is based on your seat base position and sent to the OpenXR Motion Compensation layer.

The OpenXR Motion Compensation layer performs the key compensation step: it applies the received values to the VR view, using the "COR" as the reference point (see [#cor-cor-cor](#cor-cor-cor "mention") below).

## Open XR what is it ?

OpenXR is a modern, open standard for Virtual Reality that works across all major headsets. It replaces older systems like OpenVR and offers better performance, smoother visuals, and more advanced features like motion compensation.\
\
Keep in mind: for OpenXR to work, the game you’re playing must support it. iRacing and EA WRC are examples of games that support OpenXR, among many others.

## COR ? COR ? COR ?

Accurate motion compensation relies heavily on the COR .... COR stands for "center of rotation". It’s a reference point in space that must align between your VR view and your motion software’s computations.

Since complex platforms often don't have a single center of rotation, SimHub uses the seat base as the COR and computes all compensation around it.

**Don't assume the COR must be set at the same location as the other softwares in the game. In SimHub the in-game COR must be set to the seat base.**

![](/files/Qjo8BkmhGQtNK2TlNl0r)

{% hint style="info" %}
A simple pitch angle considered from your seating position makes you move in the up and front direction in addition to the pitch rotation.
{% endhint %}

## Getting Started

### Dimensions and speed input

In SimHub: make sure to enter the correct dimensions in the geometry settings.

**Every dimensions matters**, both for accurately calculating your platform’s real-world motion and for estimating your sitting position for compensation.

For all axes (Surge, TL, 2 DOF, 3 DOF), adjust your speed limiters to match your real actuators' capabilities as closely as possible. If the capabilities are overestimated, SimHub will assume the platform moves faster than it actually does, which can lead to inaccurate compensation.

### Open XR setup

* If you were using Open XR with another software, or custom settings
  * Make sure to back up your settings (Go into `%localappdata%\OpenXR-MotionCompensation`and copy all the files)
  * Uninstall Open XR and **check "delete user settings"** during the uninstallation process
  * Then go into `%localappdata%\OpenXR-MotionCompensation` and ensure the folder is empty or no longer exists (there should be no remaining files).
* Download and install the Open XR MC latest version : <https://github.com/BuzzteeBear/OpenXR-MotionCompensation/releases/latest>

### Enabling motion compensation in SimHub

* Go into Motion compensation settings

<figure><img src="/files/mWStkfpo9oQOdmpkpqu6" alt=""><figcaption></figcaption></figure>

* Enable motion compensation

<figure><img src="/files/ycvUaxBwZSilKP9Cqmaj" alt=""><figcaption></figcaption></figure>

* Click on configure OpenXR MC to set all the required settings

<figure><img src="/files/NqMOJyIum3LdVzIBPCWX" alt=""><figcaption></figcaption></figure>

### Initial in-game setup

As explained earlier, Open XR motion compensation will exclusively work with Open XR compliant games. If your game allows you to choose which VR mode to use (like Iracing), make sure to choose Open XR

> <mark style="color:red;">As with any unofficial feature, it might not work with all games or headsets, even if they support OpenXR.</mark>
>
> <mark style="color:red;">The keyboard shortcuts shown below are the default OpenXR MC bindings. To change them please refer to the documentation :</mark> [<mark style="color:red;">https://github.com/BuzzteeBear/OpenXR-MotionCompensation</mark>](https://github.com/BuzzteeBear/OpenXR-MotionCompensation)

* Start your game and enter a session

> <mark style="color:red;">If your game includes automatic camera movements (like lock to horizon), disable or reduce them as much as possible to avoid conflicts with motion compensation.</mark>

* Calibrate your VR view using the typical in-game control (usually `SPACE`or `DEL`... Please refer to your game controls for the actual view centering control)
* Press `CTRL + DEL` to calibrate the motion compensation
* Press `CTRL + D` to show the COR overlay : this will show a "triple" arrow (Front, up, right)
* Align the cor overlay position so it roughly matches your seat base position. It must point correctly to the front.

> To adjust the MC "COR" you have several shortcuts available to move it forward, sideways, or rotate it. The shortcuts from the MC configuration are listed in the SimHub MC dialog:
>
> <img src="/files/xRCzKiZYC7rIuIPIPrBx" alt="" data-size="original">

* Save the MC COR location : Press `CTRL + SHIFT + S`
* Enable motion compensation : Press `CTRL + INS`

### Fine COR tuning

At this stage, even if the COR was set with care, motion platform movements might not be completely cancelled. This is again an effect of the COR position.

To match the COR accurately between the VR view and SimHub’s expected location, we only need to adjust it using movements along two axes: pitch and roll.

> <mark style="color:red;">During the next steps, be aware of “gravity”: pitching forward/backward or rolling left/right may cause your head to tilt and distort the feeling of compensation. Try to stay as still as possible.</mark>

* Enter the game and enable motion compensation (see [#getting-started](#getting-started "mention"))
* Start an automatic roll animation

  * Go into "`VR MC Monitor`"

  <figure><img src="/files/zToQHqJnoDusT9Aigovm" alt=""><figcaption></figcaption></figure>

  * Click on `start roll test`

  <figure><img src="/files/cWPsROQJGhjNj9OyHmnQ" alt=""><figcaption></figcaption></figure>
* At this stage your platform will automatically roll from left to right.
* With this rolling movement running, adjust the **height** of the MC COR in game (move up or down) until you can't see any movements in game.
* Next, switch the automatic test to Pitch (`Start pitch test`) and disable Roll.
* With the pitch movement running, adjust the MC COR forward or backward in-game (move it front or rear) until there's no visible movement. Don’t move it left or right, or change its rotation, if you do, please restart this process.You’ve now adjusted your COR in two intersecting directions, allowing you to accurately position it in space. You’re done!
* Save the MC COR location : Press `CTRL + SHIFT + S`

## Actuator Speed Matching & Motion Smoothing

In motion compensation, timing and realism go hand-in-hand. If the compensation signal moves **faster or with more detail** than the rig can physically reproduce, it may lead to incorrect corrections—making you feel motion in the wrong direction or at the wrong intensity.

This is especially true for **actuators** with large deadbands or limited high-frequency response.

SimHub includes two key tools to address this:

* A **compensation speed limiter** to cap correction speed.
* A **motion detail smoother** to remove unrealistic high-frequency components from the compensation signal

You can access them in the VR MC monitor

#### Compensation Speed Limiter

<figure><img src="/files/p5DvaQ56XH6dSl13cEoO" alt=""><figcaption></figcaption></figure>

* Caps the maximum rate of change (°/s or mm/s) of the compensation position.
* Prevents the compensation signal from running ahead of the rig’s actual movement.
* Ensures the correction "waits" for slow actuators to catch up.

> 🔧 **Tip:** Start by matching your rig's real-world maximum speed. Lower slightly if you still feel mismatch or overshoot.

#### Motion Detail Smoothing

<figure><img src="/files/tRZezEkrDHOL0FfAqVXs" alt=""><figcaption></figcaption></figure>

* Applies a **low-pass filter** to remove small, sharp movements from the compensation signal.
* Especially useful for rigs that **cannot reproduce fine details** (due to deadband, mechanical damping, or PID tuning).
* Helps prevent the compensation from reacting to motion that was never physically "felt" in the first place.

> 🧠 Think of it as matching not just the **speed**, but also the **details and fidelity** of your compensation signal to what your hardware can actually reproduce.

#### Tuning Guide

* **Enable smoothing** and set it to a moderate value.
* Gradually increase it until the compensation feels calm and tracks the rig motion naturally.
* If smoothing is too high, compensation may feel delayed or sluggish.
* Combine with the speed limiter for best results.

#### Summary

| Feature                    | Purpose                                                       |
| -------------------------- | ------------------------------------------------------------- |
| Compensation Speed Limiter | Prevents correction from moving faster than the rig           |
| Target value smoothing     | Filters out unrealistic high-frequency motion                 |
| Goal                       | Match compensation behavior to what the rig can *actually* do |

Happy race/flight !


# OpenVR Motion compensation

## Introduction

Motion compensation is designed to cancel out the VR headset movements caused by your motion platform. For example, if the platform rolls to the left, motion compensation will apply a virtual roll to the right, keeping your viewpoint stable in VR.\
\
As of now, no official method for motion compensation is provided by VR frameworks. For Open VR Dschadu does provide us a motion compensation layer.

Motion compensation on OpenVR wouldn’t exist without his work. Don’t hesitate to support Dschadu efforts in any way you can!

> <mark style="color:red;">SimHub only provides motion data to external motion compensation software. We are not responsible for how these tools behave, nor can we guarantee their stability or compatibility. Results may vary depending on the game, the VR headset, and the motion compensation software itself. Use at your own risk.</mark>\
> \ <mark style="color:red;">For simplicity, in this guide we will use the following abbreviations:</mark>
>
> * *<mark style="color:red;">**"Open VR motion compensation"**</mark>* <mark style="color:red;">to "</mark>*<mark style="color:red;">**MC" or "MC layer"**</mark>*
> * *<mark style="color:red;">**"Open VR motion compensation center or rotation" to "COR"**</mark>*

## SimHub and Open VR MC roles

SimHub provides the "computations": based on your dimension inputs and the current motion target position, it estimates the required compensation (Heave, Sway, Surge, Yaw, Pitch, Roll). Those computations can be mixed with a physical sensor (see [WitMotion sensor for Motion compensation](/motion-addon/witmotion-sensor-for-motion-compensation))

This estimation is based on your seat base position and sent to the OpenVR Motion Compensation layer.

The OpenVR Motion Compensation layer performs the key compensation step: it applies the received values to the VR view, using the "COR" as the reference point.

## Open VR what is it ?

OpenVR is a standard for Virtual Reality that works across all major headsets.

## COR ? COR ? COR ?

Accurate motion compensation relies heavily on the COR .... COR stands for "center of rotation". It’s a reference point in space that must align between your VR view and your motion software’s computations.

Since complex platforms often don't have a single center of rotation, SimHub uses the seat base as the COR and computes all compensation around it.

**Don't assume the COR must be set at the same location as the other softwares in the game. In SimHub the in-game COR must be set to the seat base.**

![](/files/Qjo8BkmhGQtNK2TlNl0r)

{% hint style="info" %}
A simple pitch angle considered from your seating position makes you move in the up and front direction in addition to the pitch rotation.
{% endhint %}

## Getting Started

### Dimensions and speed input

In SimHub: make sure to enter the correct dimensions in the geometry settings.

**Every dimensions matters**, both for accurately calculating your platform’s real-world motion and for estimating your sitting position for compensation.

For all axes (Surge, TL, 2 DOF, 3 DOF), adjust your speed limiters to match your real actuators' capabilities as closely as possible. If the capabilities are overestimated, SimHub will assume the platform moves faster than it actually does, which can lead to inaccurate compensation.

### Enabling motion compensation in SimHub

* Go into Motion compensation settings

<figure><img src="/files/mWStkfpo9oQOdmpkpqu6" alt=""><figcaption></figcaption></figure>

* Enable motion compensation

<figure><img src="/files/ycvUaxBwZSilKP9Cqmaj" alt=""><figcaption></figcaption></figure>

* Click on configure OpenVR MC to set all the required settings

### Open VR motion compensation setup

Please follow the original software setup/configuration instructions available here :

* Installing the OpenVR Motion compensation layer : <https://ovrmc.dschadu.de/en/setup>
* Installing the FlyPt tracker (The flypt tracker allows to read data from memory instead of using a physical tracker like a controller, you don't need flypt to make it work) : <https://ovrmc.dschadu.de/en/vt_flyptmover>

Happy race/flight !


# WitMotion sensor for Motion compensation

<figure><img src="/files/ghRgfCoEimcyriohOmtX" alt=""><figcaption></figcaption></figure>

## Introduction

If your actuators are slow, imprecise, or unpredictable, motion compensation may become inaccurate. When tuning motion compensation smoothing or scaling is not enough to fill the gap, adding a physical sensor can significantly improve the result.

The physical sensor will help Simhub to know the real orientation and feed accordingly the motion compensation layer ( [OpenXR Motion compensation](/motion-addon/openxr-motion-compensation) or [OpenVR Motion compensation](/motion-addon/openvr-motion-compensation))\
\
Physical sensors can measure the following three components:

* Yaw (can sometime overshoot or drift) in case of high velocity
* Pitch angle
* Roll angle

However, physical sensors are not perfect. Because this type of sensor applies strong internal smoothing, the measured position can be delayed. It also cannot measure heave, sway, or surge movements.

Nevertheless, when a sensor is available, SimHub blends its data with internal calculations to build complete motion compensation. If the sensor is disconnected or missing, SimHub will continue working using only its internal computations. Naturally, the result will differ — otherwise, there would be no reason to add a sensor.

> <mark style="color:yellow;">Before investing in hardware, please note that both OpenVR and OpenXR motion compensation rely on third-party software</mark> <mark style="color:yellow;">**that is not guaranteed to work with every game or headset**</mark> <mark style="color:yellow;">and may become incompatible following VR framework or game updates</mark>.
>
> <mark style="color:yellow;">Physical sensor</mark> <mark style="color:yellow;">**is not supported on stacked setups**</mark> <mark style="color:yellow;">(IE : seat mover installed on top of a 3DOFs) : for such setup please does not install the sensor at a location</mark> <mark style="color:yellow;">**not moving**</mark> <mark style="color:yellow;">with the top seat mover.</mark>

## Required hardware

The WitMotion range has many variations, so please pay close attention to the model you purchase.<br>

* Sensor : WT901C-**232** , 9-Axis Vibration Inclinometer MPU9250, Asin B01N91GCJX

> <mark style="color:yellow;">This exists in two models, RS232 or TTL, you need the</mark> <mark style="color:yellow;">**RS232**</mark> <mark style="color:yellow;">version (WT901C-</mark><mark style="color:yellow;">**232)**</mark>

<figure><img src="/files/PNMHvEmqSUXdyF2dOaRe" alt="" width="375"><figcaption></figcaption></figure>

* Official RS232 to USB Adapter with CH340 chip, Asin : B07WF7BJJH

<figure><img src="/files/aRguki1tIXA7i0qhBBqQ" alt="" width="375"><figcaption></figcaption></figure>

The kit (sensor + adapter) can be found here

* ERacing lab : <https://eracing-lab.com/collections/diy-projects/products/witmotion>
* Amazon:
  * Sensor : <https://amzn.eu/d/7a48q7o>
  * Cable : <https://amzn.eu/d/39y4NYL>

## Physical installation

### Wiring<br>

* Plug the cable to the sensor
* Plug the sensor to an usb port

### Mounting

Install firmly the sensor on your simulator, you can install it vertically or horizontally .

> <mark style="color:yellow;">Ensure it is installed far from magnetic interference sources (motors, wheels, bass shakers).</mark>

#### Horizontal mounting

In horizontal mounting you must have **label on top**, connector pointing **to the right**.\
You can adjust later the rotation if you could not keep the connector pointing to the right, but try to keep it as flat as possible.

<figure><img src="/files/LotVTpiD1bR1IakcJk88" alt=""><figcaption></figcaption></figure>

#### Vertical mounting

In vertical mounting you must have label **on the right**, connector pointing **to the floor**.\
You can adjust later the rotation if you could not keep the label pointing to the right, but try to keep it as vertical as possible.

<figure><img src="/files/AG13iWer33eGQwxilriC" alt=""><figcaption></figcaption></figure>

#### **Reversed Horizontal** mounting

In reversed horizontal mounting you must have label pointing **to the floor,** connector pointing **to the right**.\
You can adjust later the rotation if you could not keep the connector pointing to the right, but try to keep it as flat as possible.

<figure><img src="/files/TDJ5uIBUjprYL9EjXrn9" alt=""><figcaption></figcaption></figure>

## Simhub Setup

In motion compensation settings, go into the physical sensor tab.

<figure><img src="/files/RudrLFXzKENLfBg9lGIc" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/N8ue7InKDf7uNk3HsG0q" alt=""><figcaption></figcaption></figure>

* Enable the sensor
* Select the serial port
* Select the mounting mode
* Adjust the yaw offset if you could not align the sensor as shown in the [#mounting](#mounting "mention") instructions; the preview will display a visual representation of the offset (for example, a 45° rotation).

  <figure><img src="/files/yA5Ef0Jp6cg9L5uI8t4s" alt=""><figcaption></figcaption></figure>

> <mark style="color:yellow;">Adjusting the yaw offset is critical, as it ensures SimHub correctly interprets the sensor’s mounting orientation, including:</mark>
>
> * <mark style="color:yellow;">Pitch and roll direction: if the sensor is rotated by 90°, pitch and roll will be swapped, and their directions may also be reversed.</mark>
> * <mark style="color:yellow;">Pitch and roll reference: an incorrect offset will result in mixed pitch and roll components.</mark>
>
> <mark style="color:yellow;">**SimHub takes care of it, as long as you give it the correct offset.**</mark>

* Perform an initial zero calibration.
* Optional: Enable yaw drift correction to progressively compensate for yaw drifts.

> <mark style="color:yellow;">About yaw drift : Yaw drift on the Witmotion sensor occurs easily, Simhub will only adjust the drift when expected yaw and sensor yaw are steady (and expected yaw close to 0). This means it will not attempt to compensate for unstable values during active yaw movements, even if drifting occurs.</mark>

## Calibration

* Start your platform. If it remains idle (outside of a game), use the "Force Unpark" button to unpark it, then open the VR MC Monitor dialog. If the settings are not visible, click on "Show MC Settings."

<figure><img src="/files/Ym7jyQbTAn22u25FJShw" alt=""><figcaption></figcaption></figure>

* When the platform is running and flat, click on calibrate zero :

<figure><img src="/files/eSS8AJIw45WFpfGxSZdV" alt=""><figcaption></figcaption></figure>

> <mark style="color:yellow;">Calibration is not required every time, but it is recommended to redo it periodically or after any significant rig movement or modifications.</mark>

## Motion compensation mixing

SimHub allows you to "mix" and "tune" sensor-based motion compensation with its own calculations, offering the best of both worlds.

Open the MC monitor (see [#fine-calibration](#fine-calibration "mention")) and open the Global tab

<figure><img src="/files/og54ojrvnwjuPzrj2Dgn" alt=""><figcaption></figcaption></figure>

You can now adjust for each motion compensation components how much of the compensation you want by enabling the `physical sensor mixing`.

* 100% means Simhub will only trust the sensor
* 50% means simhub will average evenly the simhub expected position with the sensor.

If the sensor reports slightly off values you can also scale it using the `sensor gain`

> <mark style="color:yellow;">Motion is complex and not limited to yaw, pitch, and roll alone. Some missing components will still be computed by SimHub (and the "mixing" option won't be available), you can smoth,scale, or disable those at your will.</mark>

Smoothing **should not be necessary** for the sensor, as its internal smoothing and latency are already significant and additional smoothing would increase latency further.

> <mark style="color:yellow;">Physical sensor values are injected into the compensation system using the same center of rotation as SimHub’s computations. Please pay attention to the following parameters:</mark>
>
> * <mark style="color:yellow;">In Simhub's geometry settings : Seat position and height for 2/3/6 DOFs and traction loss dimensions</mark>
> * <mark style="color:yellow;">In Game, make sure to get a matching COR (see OpenXr or OpenVR instructions).</mark> <mark style="color:yellow;">**Unmatched COR, makes any computations senseless.**</mark>


# Getting started - Device definition authoring

### Introduction

A **device definition** describes how a hardware device behaves and appears inside SimHub.

It defines:

* The **hardware interface** (HID, Serial, Named Protocol, etc.)
* The **available features** (LEDs, screens, encoders, buttons, etc.)
* Default parameters such as:
  * LED mappings and colors
  * Brightness profiles
  * Screen layout
  * Default telemetry bindings

A definition transforms a raw hardware device into a ready-to-use SimHub device with proper names, visuals, and defaults, once installed the end user can instantiate it as any other device.

***

### Creating a New Definition

1. Open **Descriptor Builder**\
   → *Devices → Utilities → Device definition authoring tools -> New*<br>

   <figure><img src="/files/xA1JFIPRt4Rkawr9kuk6" alt=""><figcaption></figcaption></figure>
2. Fill the **device description**:
   * Brand and product name
   * Thumbnail image
3. Choose the **hardware interface**:
   * Serial, HID, or custom named protocol (see [Device communication protocols](/device-definition-authoring/device-communication-protocols))
4. Add **features**:
   * LEDs, screens, encoders, buttons, etc.
5. Define **logical → physical mappings** for LEDs or buttons.

***

### Distribution Formats

| Format                 | Extension | Purpose                               |
| ---------------------- | --------- | ------------------------------------- |
| **Project**            | `.shdd`   | Editable, for collaboration or backup |
| **Installable device** | `.shdp`   | Read-only, for end-user distribution  |

***

### Exporting Your Definition

To share your work:

1. Open the authoring tool
2. Select the device and click on **Export installable definition**'

   It will create a `.shdp` file which can be installed by any user wuing "installed devices" menu.

### Managing Installed Definitions

Installed definitions can be viewed or removed from:

> **Devices → Installed Devices**

This view is intentionally simple — it only lists user-installed third-party definitions.


# Device communication protocols

Simhub can communicate in various ways to your devices, some protocols are pre implemented,\
No matter the protocol they all need you to be able to assign to your MCU a proper **PID/VID you own**.

## SimHub Standard Serial protocol

The most universal protocol, it can be implemented on any device with just a CDC either by using the [Standard Serial Firmware Builder](/standard-serial-firmware-builder/readme-1) (for atmega32u4) or copying the existing protocol

## Screen pass-through

Both USBD480NX and Vocore offer to drive leds through the screen. In such case you can use this protocol to instruct simhub to use the screen for the LEDs control.

## SimHub Standard HID protocol

When things will get more serious you might want to switch a proper HID implementation,

Simhub can identify the HID interface based on the HID Usage and usage page. The report ID and report length can be specified.

Make sure to properly include the report in your device HID descriptor, descriptors not specifying the report id won't work.

To be able to support multiple device instance, make sure your device exposes an unique HID serial number.

#### HID Report Format

The SimHub Standard HID protocol can expose separate reports for LEDs, motors and fans. Each report uses its own report ID and can use the same HID report length configured for the device.

Shorter or longer reports (for example 32, 64 or 128 bytes) can be used depending on the microcontroller capabilities. If the configured report length is too short to carry all channels, SimHub sends multiple packets using the start index, affected channel count and final packet flag.

### LED report

The LED report is used to update RGB LEDs efficiently. The default report ID used by the standard firmware builder is `0x68`.

| Byte  | Description                                                                                                                                                            | Example value    |
| ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- |
| 1     | **LED Report ID**                                                                                                                                                      | `0x68`           |
| 2     | **Start LED index**                                                                                                                                                    | `0x00`           |
| 3     | **Affected LED count**                                                                                                                                                 | `0x14` (20)      |
| 4     | **Draw flag**: `0` while more LED packets are expected, `1` for the last LED packet, `2` for the optional on connect report, `3` for the optional on disconnect report | `0x00`           |
| 5-7   | **LED #1**: R, G, B                                                                                                                                                    | `0xFF 0xFF 0xFF` |
| 8-10  | **LED #2**: R, G, B                                                                                                                                                    | `0xFF 0xFF 0xFF` |
| ...   | **Next LEDs**                                                                                                                                                          | `...`            |
| 62-64 | **Last LED in a 64-byte report**: R, G, B                                                                                                                              | `0xFF 0xFF 0xFF` |

For a 64-byte report, the 4-byte header leaves 60 bytes of payload. Since each LED uses 3 bytes, one packet can carry up to 20 LEDs.

The draw flag allows physical LEDs, such as WS2812B LEDs, to be refreshed only once per full frame. The optional `on connect` and `on disconnect` reports use the LED report ID and set the draw flag to `2` or `3`; all other data is set to zero.

{% hint style="info" %}
Warning the `on disconnect` report can't be guaranteed in case of process being killed or usb issue causing a disconnect for instance. Simhub sends a keep alive "draw" every 5 seconds even if nothing has changed. Using an internal firmware timeout of 6s would be relevant in cases of automations to be triggered after a software disconnect.
{% endhint %}

### Motor report

{% hint style="warning" %}
Motor HID reports are intended for the next SimHub device descriptor/standard HID implementation and are not available in current public SimHub releases yet.
{% endhint %}

The motor report carries one gain value and one frequency value per motor. The default report ID used by the standard firmware builder is `0x6A`.

| Byte  | Description                                                                  | Example value |
| ----- | ---------------------------------------------------------------------------- | ------------- |
| 1     | **Motor Report ID**                                                          | `0x6A`        |
| 2     | **Start motor index**                                                        | `0x00`        |
| 3     | **Affected motor count**                                                     | `0x02`        |
| 4     | **Final packet flag**: `1` when this is the last motor packet, otherwise `0` | `0x01`        |
| 5-6   | **Motor #1 gain**, unsigned 16-bit big-endian, from `0x0000` to `0xFFFF`     | `0xFF 0xFF`   |
| 7-8   | **Motor #1 frequency**, unsigned 16-bit big-endian                           | `0x00 0x3C`   |
| 9-10  | **Motor #2 gain**, unsigned 16-bit big-endian, from `0x0000` to `0xFFFF`     | `0x80 0x00`   |
| 11-12 | **Motor #2 frequency**, unsigned 16-bit big-endian                           | `0x00 0x78`   |
| ...   | **Next motors**                                                              | `...`         |

For a 64-byte report, the 4-byte header leaves 60 bytes of payload. Since each motor uses 4 bytes, one packet can carry up to 15 motors at the communication level. The current SimHub device descriptor implementation limits motor devices to 8 motors.

If the device descriptor does not expose frequency support for motors, firmware can ignore the frequency field.

### Fan report

{% hint style="warning" %}
Fan HID reports are intended for the next SimHub device descriptor/standard HID implementation and are not available in current public SimHub releases yet.
{% endhint %}

The fan report carries one unsigned 16-bit speed value per fan. The default report ID used by the standard firmware builder is `0x69`.

| Byte | Description                                                                | Example value |
| ---- | -------------------------------------------------------------------------- | ------------- |
| 1    | **Fan Report ID**                                                          | `0x69`        |
| 2    | **Start fan index**                                                        | `0x00`        |
| 3    | **Affected fan count**                                                     | `0x02`        |
| 4    | **Final packet flag**: `1` when this is the last fan packet, otherwise `0` | `0x01`        |
| 5-6  | **Fan #1 speed**, unsigned 16-bit big-endian, from `0x0000` to `0xFFFF`    | `0xFF 0xFF`   |
| 7-8  | **Fan #2 speed**, unsigned 16-bit big-endian, from `0x0000` to `0xFFFF`    | `0x80 0x00`   |
| ...  | **Next fans**                                                              | `...`         |

For a 64-byte report, the 4-byte header leaves 60 bytes of payload. Since each fan uses 2 bytes, one packet can carry up to 30 fans at the communication level. The current SimHub device descriptor implementation limits fan devices to 3 fans.

### Examples

Example 1 - Updating 2 LEDs

*Update the first 2 LEDs (LED #0 to #1):*

```
0x68  0x00  0x02  0x01  FF FF FF  FF FF FF  00 00 00 ... 00
```

Example 2 - Updating 22 LEDs (split across packets)

*Update the first 20 LEDs (LED #0 to #19):*

```
0x68  0x00  0x14  0x00  FF FF FF  FF FF FF  ...  FF FF FF
```

*Update the last 2 LEDs (LED #20 to #21):*

```
0x68  0x14  0x02  0x01  FF FF FF  FF FF FF  00 00 00 ...
```

Example 3 - Updating 42 LEDs (split across packets)

*Update the first 20 LEDs (LED #0 to #19):*

```
0x68  0x00  0x14  0x00  FF FF FF  FF FF FF  ...  FF FF FF
```

*Update the next 20 LEDs (LED #20 to #39):*

```
0x68  0x14  0x14  0x00  FF FF FF  FF FF FF  ...  FF FF FF
```

*Update the last 2 LEDs (LED #40 to #41):*

```
0x68  0x28  0x02  0x01  FF FF FF  FF FF FF  00 00 00 ...
```

Example 4 - Optional on connect report

*Sends a draw byte set to `2` on connection.*

```
0x68  0x00  0x00  0x02  00 00 00  00 00 00  ...  00 00 00
```

Example 5 - Optional on disconnect report

*Sends a draw byte set to `3` before disconnecting.*

```
0x68  0x00  0x00  0x03  00 00 00  00 00 00  ...  00 00 00
```

Example 6 - Updating 2 motors

*Update motor #0 at full gain / 60 Hz and motor #1 at half gain / 120 Hz:*

```
0x6A  0x00  0x02  0x01  FF FF  00 3C  80 00  00 78  00 00 ... 00
```

Example 7 - Updating 8 motors

*Update the currently supported maximum of 8 motors in one 64-byte report:*

```
0x6A  0x00  0x08  0x01  FF FF  00 3C  FF FF  00 3C  ...  FF FF  00 3C  00 00 ... 00
```

Example 8 - Updating 2 fans

*Update fan #0 to full speed and fan #1 to half speed:*

```
0x69  0x00  0x02  0x01  FF FF  80 00  00 00 ... 00
```

Example 9 - Updating 3 fans

*Update the currently supported maximum of 3 fans in one 64-byte report:*

```
0x69  0x00  0x03  0x01  FF FF  80 00  40 00  00 00 ... 00
```


# Supported screens

### Supported screens

* Vocore

  usb screen, supports "leds pass through"\*
* USBD480 :\
  Usb screen, does not supports "leds pass through"\*
* USBD480NX\
  Usb screen, supports "leds pass through"\*
* HDMI Monitor\
  Simple monitor display , does not supports "leds pass through"\*
* Remote web display\
  Provides a dedicated html "page" for each device, does not supports "leds pass through"\*
* MMF Rendering\
  In memory rendering which can be read by an external application, supports "leds pass through"\*

\* leds pass through : Leds data can be sent through the screen instead of using a separate hardware interface.

### **MMF Rendering**

MMF rendering is producing a dashboard rendering in memory. In this particular case a "consumer" application (typically making the interface with the real hardware) will expose all the available devices. Then Simhub can connect and render through shared memory the dashboards like any classic hardware displays.

This rendering can be used to bridge to unsupported screens/displays handled by an external application as well as virtual displays (IE : In sim dashboards textures ...)\
\
A demo "consumer" application can be found here: [MMFVisualizerV4](https://www.simhubdash.com/downloads/MMFVisualizerV4.zip)

> V4 update : Support for multitouch

To get it running make sure to make the device type id match the one shown in the device authoring tools :<br>

<figure><img src="/files/QaUZZ6ZwrXtkQck2HnAM" alt=""><figcaption></figcaption></figure>


# Firmware introduction

## Introduction

This firmware (arduino pro micro sketch) is intended for small productions of commercial leds/matrix based devices. It is compatible with ATmega32U4 with Arduino bootloader (Arduino pro micro, Arduino leonardo). It is intended to simplify end user device usage (at the price of a little more configuration while building the firmware.)

This requires a dedicated PID/VID and USB name so SimHub can recognize the device without requiring the user to choose the serial port. That's why this firmware can't run on any standard arduino uno, arduino nano or arduino mega which are not capable of USB definition customization).

The sketch is a skeleton giving all the minimal code to make the leds work, other features like controller etc, can be added on your side.

In order to port this protocol to another platform you can refer the the protocol as found in `protocol.h`.

Overall using this sketch is not the only way to do and is not intended to constrain manufacturers, if you are building your commercial device and have already done your firmware, want a deeper integration etc ... Please contact me at <https://www.simhubdash.com/simhub-contact/> so we can evaluate the possibilities.

## Sketch features overview

The sketch supports :

* **Up to 4 RGB LEDS strips**\
  WS2812B Neopixels and/or PL9823
  * Each strip can have its direction reversed. Ideally LEDS must be ordered in end user logic (telemetry LEDs, then buttons …)
  * Leds can be organized as buttons or telemetry leds and reordered.
  * Buttons default static color car be set.\ <br>
* **One WS2812B 8x8 Matrix**

  With various physical layouts pre-implemented.\ <br>
* **25KHZ Fans or custom implementation**\
  Up to 3 Fans (Supported from Simhub 9.8.3 and upward).\ <br>
* **Upload/Wipe protection**

  To reduce unwanted flashes, sketch offers a basic upload lock security. Upload will be locked after 15 seconds (can be customized) after the device is plugged. This can be unlocked by sending either the upload unlock command or unplugging/plugging the device.\ <br>
* **Automatic detection**

  Thanks to the USB signature (name and PID VID) the device can be recognized as compliant and scanned automatically, to detect the following device informations :

  * Default picture URL, the default picture URL can be set in firmware.
  * Hardware combination toward :
    * DEVICETYPE\_LEDS\_PLUS\_VOCORE\
      Led device + VOCORE
    * DEVICETYPE\_LEDS\_PLUS\_USBD480\
      Led device + USBD480
    * DEVICETYPE\_LEDS\_PLUS\_MONITOR\
      Led device + a windows monitor (HDMI etc ...)
    * DEVICETYPE\_MATRIX\
      Single 8x8 WS2812B matrix device
    * DEVICETYPE\_MATRIX\_PLUS\_LEDS\
      Single matrix device associated with one or more led strips
    * DEVICETYPE\_FANS\
      Fan device, up to 3 channels


# Getting started

## Preparation

* Make sure your target Arduino is not used already
  * Disable any devices in simhub which may already use it
  * Recommended : Disable the arduino feature (note : as long as the firmware builder is open arduino scan will be suspended)
* Open the firmware builder

  * To open the firmware builder, go in devices -> Utilities -> standard device firmware builder<br>

  <figure><img src="/files/5YiCK2StPGEp4Wnb8iu8" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/Moyg03UPoB3H28CdAHsy" alt=""><figcaption></figcaption></figure>

## Configure your firmware

### **Automatic detection**

![](https://github.com/SHWotever/SimHub/assets/2207331/c389cb91-628d-451c-bcb0-e627994da46d)

Points of attention :

* Device type
  * Must be set to the kind of device you want.
  * Unspecified will require it to be configured manually inside simhub, you should not need it anymore.
* Device name and brand name
  * **Don't abuse of upper case** ! This is visually heavy and takes lot of visual user space
  * The name is compiled inside the firmware and the USB signature, set it with care it's not possible to change it later without creating a new firmware
* Picture URL :
  * Make sure to host your picture on a reliable host. A Github repo should be a good reliable option if you don't have other solutions.
  * For the best result make sure it's a png **properly cropped** with **transparent background**.
  * Pay attention to get a **proper contrast**, Simhub main theme is dark : a dark picture over a dark background won't render properly.
* When automatic detection is enabled the USB name will get a prefix added (`SHd,`) which will be used to safely recognize and scan those devices without interfering with any other serial based hardware on your system). This requirement can't be bypassed to keep automatic detection.

### **USB Definition**

![](https://github.com/SHWotever/SimHub/assets/2207331/2442e502-e3a1-4f30-9824-aef97e2337ee)

**PID/VID : What is this thing ?** It's an unique identifier tied to a device model the OS (windows etc...) uses to recognize the brand and model of an usb device and eventually load the tied drivers. Simhub uses the same method to recognize a supported device.\
\
If you are building your own personal single device you can use a randomly generated PID/VID, otherwise make sure to have one per device model.

Buying a whole VID is outrageously expensive and primarily allow you to show legally the USB compliant logo on your device.

You can buy a an affordable and guaranteed to be unique PID/VID couple at MCS : <https://www.mcselec.com/index.php?page=shop.product\\_details\\&product\\_id=92\\&option=com\\_phpshop><br>

Points of attention :

* Don't forget that simple rule : **One PID/VID couple = one "product/model"**
* While simhub will successfully recognize a new device based on the USB name even if the same PID/VID couple is used. This will lead to conflicts (usb name conflicts) and impossibility to do a native integration later. In a few words : *Don't ignore the previous* **One PID/VID couple = one "product/model"***rule !*
* *How really Important is this PID/VID, if it can be set to a random value ?* Simhub will recognize compatible devices [based on their usb name](#automatic-detection), one PID/VID couple can only have one name saved in windows.

### **Upload protection**

![](https://github.com/SHWotever/SimHub/assets/2207331/3f9859d8-8594-46c8-bde1-177e89631e00)

**Protect your users from bad manipulations**, once your device is ready using the upload protection will help to protect against unwanted firmware wipes. While this "lock" is not meant to be bullet proof, it seriously reduces the chances of unwanted flashes.

### **Led strips setup**

![](https://github.com/SHWotever/SimHub/assets/2207331/4b2d5b52-7bfb-4920-85da-16c7f2bad846)

Points of attention :

* **Take care of the maximum power draw**, you can lock the maximum brightness either for eye comfort or power.
* **Warning** : a too low maximum brightness will also reduce the color depth and accuracy

### **LEDs Roles**

![](https://github.com/SHWotever/SimHub/assets/2207331/ac44cd7a-07b7-48a2-b3d7-d77071d0b0a2)

* All the leds can be grouped and or splitted either as telemetry leds or buttons (including static lighting feature default color)
* The individual leds section will be enabled automatically in case of grouped leds.
* The individual leds section always follows the hardware natural ordering, make sure to make it user friendly as much as possible.

### **8x8 WS2812B RGB Matrix**

![](https://github.com/SHWotever/SimHub/assets/2207331/3a112623-f9cb-4fb2-9b7d-e6a40398fe56)

Points of attention :

* Like leds, **take care of the maximum power draw**, you can lock the maximum brightness either for eye comfort or power. **Warning** : a too low brightness will also reduce the color depth and accuracy

## Standard fans setup

<figure><img src="/files/Vj7MaN7QJsFrpGZFilb5" alt=""><figcaption></figcaption></figure>

* On an ATMEGA32U4 you can only use the pins 9/10 and 11 to get a proper 25KHZ PWM signal
* You can configure an optional relay to stop the fans from running when they are not capable of stopping
* If you want to use custom logic or want custom code you can export the firmware and customize `FansCustom.h`. Implement `setMotorOutput()` for the actual fan output, and override `begin()` or `safetyStop()` when needed.

  <figure><img src="/files/uyRvbeIlbzaBuiYm7nZ1" alt=""><figcaption></figcaption></figure>

## Standard haptic motors setup

The standard firmware can also expose generic haptic motor channels for ShakeIt haptic effects.

Each motor channel receives:

* gain
* optional frequency

Motors are enabled as soon as the configured motor count is greater than zero. The frequency support and its range can be declared in the device definition when the hardware is able to use it.

Points of attention :

* The standard firmware exposes the communication channel, but the actual motor driver hardware remains specific to your design.
* When exporting the firmware, implement your hardware handling by overriding `onMotorsData()` in `motorscore.h`.
* `onMotorsData()` receives the current motor count and an array of motor states containing `gain` and `frequency`.
* `onMotorsSafetyStop()` can be overridden in `motorscore.h` to force your hardware to a safe stopped state when the communication timeout is reached.
* SimHub currently exposes up to 8 haptic motor channels through this standard firmware path.

## Vendor messages setup

The standard firmware can receive custom serial data through vendor messages. In a device definition, this feature is exposed as `Data communication`.

This is useful when your device needs a small custom data channel in addition to the standard features, for example:

* external segment displays
* custom indicators
* hydration systems
* any device-specific command which does not fit in the standard LED, fan or haptic motor channels

When a vendor message is received, the firmware calls `onCustomSerialData(int messageLength)` in `ProMicroSimhubStandardDriver.ino`. The `messageLength` parameter tells you exactly how many bytes are available for this message.

Points of attention :

* Read exactly `messageLength` bytes from `Serial`.
* The message content is device-specific. It can be plain ASCII text, binary data or any format your firmware understands.
* Vendor messages are intended for custom device data. Use the standard LED, fan and haptic motor channels whenever they match your hardware feature.
* When used from a device definition, enable `Data communication` to configure vendor messages.
* Vendor messages can be shipped with the definition so the end user does not need to configure the serial commands manually.

## Compiling or exporting

No matter the options you retain, **always triple check that the serial port used to flash is the one of your target device** (unplug everything else). If you wipe the firmware of the wrong device, this can't be reverted !

### Built in compilation and flash

If you don't plan any further customizations, you can click on `build and flash`. the configuration will be saved for later customizations if needed. Then you will be prompted to upload

### Built in compilation and export

If you want to customize the firmware, click on `build and export`.\
\
To guarantee the initial firmware "consistency" a compilation will occur, then the firmware source will be exported as zip including all the required dependencies. See [the next chapter](/standard-serial-firmware-builder/manual-compilation-and-customization) about how to compile the firmware yourself including the required USB signature configuration.

## Adding the device inside simhub

* In the device section click on add device, the device will be recognized automatically

## Personalizing further the device appearance

Check [Device definition authoring](/device-definition-authoring/getting-started-device-definition-authoring) to know how to create a complete exportable definition (pictures etc ...)


# Manual compilation and customization

Once exported and customized you need to upload manually the firmware, this requires some extra steps to get the right PID/VID signature and usb name

## Sketch customization

All the configuration constants are available in `externaldefines.h`

If you want to port the protocol to another platform MCU the serial protocol is visible in `protocol.h`

## Compiling

### Environment installation

* Install a legacy Arduino IDE 1.8.X (<https://www.arduino.cc/en/software>)

### Add a custom board to the Arduino IDE with your PID/VID

* Go into the Arduino IDE installation folder and inside the hardware\arduino\avr folder (ie : C:\Program Files (x86)\Arduino\hardware\arduino\avr on a standard installation)
* Make a backup of the boards.txt file
* Open the notepad as an administrator and edit the “boards.txt” file and add to the content of the boards.txt provided in the firmware export
* Save the file

### Uploading the sketch

* Choose your board in the boards menu (NB : See annexes if the custom board is not visible)

![](https://user-images.githubusercontent.com/2207331/213188072-3c3e77aa-0f93-42a6-918c-ebeeefdc565a.png)

* Select the serial port and upload

Notes :

* If upload protection was enabled to upload once again the sketch, unplug/plug back the board to allow upload (see Upload protection settings in sketch), or you can use the provided utility.
* After the first upload, device serial port name will change (as it is linked to the PID/VID)


# Testing and maintenance utility

## Testing and maintenance utility

A little testing utility is accessible from the firmware builder menu :

![](https://github.com/SHWotever/SimHub/assets/2207331/01876a4a-48f3-4742-b4d4-03cb7cc93a87)

![](https://github.com/SHWotever/SimHub/assets/2207331/3a6d6f80-2592-458f-876e-cc04324f81ea)


# References and troubleshooting

## Troubleshooting: Custom board is not visible in Arduino IDE

If the board does not show please verify that you got the board correctly added. You might also need to clear arduino cached files.

* Go into Arduino IDE preferences and get the settings directory (here : C:\Users\Nicolas\AppData\Local\Arduino15)

![](https://user-images.githubusercontent.com/2207331/213194737-5fef0680-fb88-4738-966e-cfd9349f7318.png)

* Make a backup of the folder
* Remove all subfolders.
* Restart the IDE

## Protocol reference

see protocol.h in the firmware.

## **Unlock upload**

* Send `(0xFF)(0xFF)(0xFF)(0xFF)(0xFF)(0xFF)unlock`
* Reply: `Upload unlocked\r`

Note: supporting this instruction is not mandatory to get SimHub working.

![](https://user-images.githubusercontent.com/2207331/213195090-bb314d8d-ad9c-4fad-b3b5-51fcc467d876.png)


# EXTERNAL SIM INTEGRATION

**This feature is currently in beta. Some breaking changes in the telemetry “contract” may still occur. Thank you for your understanding.**\
\
SimHub was originally built around avoiding third-party plugins for telemetry integration, while maintaining strong normalization across all supported simulations.\
However, this approach is not sufficient for private, specialized, or experimental simulations that are not publicly available.

To address this, SimHub now allows declaring external simulations.\
\
**This feature is available starting from Simhub 9.11.5**

## Core concepts

External simulation integration is designed to avoid:

* Sim-side SDKs
* Plugin SDKs
* Any hard dependency on a specific language

It relies on a simple **binary UDP feed** and a formalized **contract**, defined by a definition file.

### **The definition file (\*.simdef)**

The definition file describes:

* The game identity (name, picture, unique ID)
* Process identification for automatic sim detection.
* The telemetry format (default UDP port, available fields, etc.)

It acts as the **contract** between the simulation and SimHub.

The definition file is typically shipped with the simulation to ensure it is always up to date.\
A dedicated editor is available in SimHub.

### **The registration file (\*.simlink)**

The registration file is a simple pointer to a definition file, allowing SimHub to discover it automatically.

* It contains a single line: the path to the `.simdef` file.

Registration can be skipped by placing the definition directly in a SimHub-managed folder (see *Getting Started*).

### **The UDP telemetry feed**

Once the definition is created, a corresponding data structure can be sent from the simulation over UDP.

SimHub provides:

* A C# generator
* A C++ generator

These generate:

* The correct structure
* A minimal sending loop

The packet includes a header to ensure proper identification and reduce invalid format errors.

### **Optional extractor process**

If the target simulation cannot provide a native integration, an external extractor can be used.

The extractor is responsible for:

* Reading simulation data (memory, API, etc.)
* Producing the expected UDP telemetry feed

## Getting started

### Enable the definition editor

In SimHub, open the settings, and in Global enable the game definition authoring tools

![](/files/wNgadSbYF62lGFPj3320)

The editor will now appear in the left menu

![](/files/X83J8wAq1phuJLPZ2cJU)

### Creating the definition

Open the editor tool and create a new definition

#### Simulation Identity

Fill:

* Name
* Icon path : The icon path must be **relative to the definition file**

**Important**

* If you are copying a definition from another sim, make sure to regenerate the Unique Id to avoid conflicts later

<figure><img src="/files/kY1GudZdK9bIqTlOA1dC" alt=""><figcaption></figcaption></figure>

#### Telemetry definition

Add all the fields you will be able to provide out of the sim

<figure><img src="/files/z2NL75VHeTQrcB9NVvjz" alt=""><figcaption></figcaption></figure>

You can also add **custom fields**:

* They will be exposed in SimHub
* They won’t be used internally by SimHub features

**Important**

* The declared fields will be used to determine the available features. Do **not** declare fields you cannot provide.

### Create the telemetry feed

Once the definition is ready :\
\
Click on copy demo code (c# or c++) This gives you:

* The exact packet structure
* Required constants
* A minimal sending loop

### Data conversion

The generated structure includes comments for:

* Units
* Directions
* Expected formats

You must convert your simulation data to match these expectations.\
\
**Important**

* Everytime you change the definition (Add, remove or reorder fields), this structure and/or constants must be updated.
* SimHub requires a minimum of 60Hz data for a correct fidelity. Higher rates are allowed and Extra packets may be ignored if needed

### Test your UDP feed

Once your simulation sends telemetry:

Open **Telemetry Receiver Tester** in SimHub editor.\
If the feed is invalid the error will be visible. Otherwise the content will be shown\
![](/files/bbQOjeYtned5a2AYJgve)

**Important :**

* If you have configured an extractor process, this won't be automatically spawned using the tester.

### Store your definition

**During development**

You can register the definition right from the editor to make it available in SimHub.

**Production recommendation**

It is recommended to ship the definition file along the sim installed files, so it's always up to date and matching the simulator build.

```
YourGame/
    telemetry.simdef
    logo.jpg
    extractor.exe (Optionnal)
```

### Make the simulation visible in SimHub

There are two approaches

**Registered** (recommended)<br>

* Create a link file into `%localappdata%\SimHub\ExternalSims\Registrations\{UniqueId}.shlink`
* The file must simply contain the absolute path of the definition file.
* It is recommended to always write/rewrite it at sim startup so it's kept up to date in case the\
  installation got moved.
* The link file name must match the pointing definition UniqueId<br>

**Dropped in** (fallback)

* This procedure is a fall back in case the integration is not native to the game (IE extractor process).
* In such case simply drop the definition and all the dependencies (logo, extractor process) into `%localappdata%\SimHub\ExternalSims\Definitions\{SimName}\`

**Important :**

* If multiple definitions share the same UniqueId: **Registered definitions take priority**

### Using the definition

If everything is properly configured the simulation will now be visible in the list, simply activate it.

<figure><img src="/files/YxpUMxHg4myjVcDK5LJD" alt=""><figcaption></figcaption></figure>

### Summary

* Create a definition
* Generate the structure
* Send UDP telemetry
* Register or drop the definition
* Activate the simulation

### Troubleshooting

* If the sim does not appear, check simhub log files, any parsing or scanning errors will be visible (`C:\Program Files (x86)\SimHub\logs`)
* If data is not received by simhub, you might have a definition mismatch (IE changed fields, changed game identitity), you can use the telemetry test tool to check validity ( [#test-your-udp-feed](#test-your-udp-feed "mention"))
* The game signature and telemetry signature are visible in the SimDef Json, **never change it**, it's only shown for reference but is recomputed when the definition is loaded
* Process detection expects a process name, not a file name : Ie
  * `notepad` is valid,
  * `notepad.exe` **is not valid**


# Other simhub features

Other simhub documentations are available on <https://github.com/SHWotever/SimHub/wiki>


