# How to Implement ABS Anti-Lock Braking Simulation Effects in a DIY Sim-Racing FFB Pedal

> Learn to implement ABS anti-lock braking simulation effects for your DIY sim-racing FFB pedal. Configure SimHub and ESP32 firmware for realistic force feedback.

- Repository: [chrgri/diy-sim-racing-ffb-pedal](https://github.com/chrgri/diy-sim-racing-ffb-pedal)
- Tags: how-to-guide
- Published: 2026-02-27

---

**To implement ABS anti-lock braking simulation effects, configure the SimHub plugin to set frequency, amplitude, and waveform pattern, which serializes the settings into `payloadPedalConfig` and transmits them to the ESP32 firmware where `ABSOscillation.forceOffset()` generates real-time force or travel offsets.**

The **DIY Sim-Racing FFB Pedal** project by chrgri delivers open-source force feedback hardware for racing simulators. Implementing ABS anti-lock braking simulation effects requires coordinating a SimHub plugin interface, a configuration transport layer, and real-time ESP32 firmware to generate pulsating feedback that mimics wheel lock-up.

## Architecture Overview

The ABS implementation spans three layers. The **SimHub plugin** ([`EffectsTab_ABS.xaml.cs`](https://github.com/chrgri/diy-sim-racing-ffb-pedal/blob/main/EffectsTab_ABS.xaml.cs)) provides the user interface for tuning parameters. The **configuration structure** ([`payloadPedalConfig.cs`](https://github.com/chrgri/diy-sim-racing-ffb-pedal/blob/main/payloadPedalConfig.cs)) packs these parameters into a binary struct sent over serial. The **ESP32 firmware** ([`ABSOscillation.h`](https://github.com/chrgri/diy-sim-racing-ffb-pedal/blob/main/ABSOscillation.h)) receives the struct, calculates the waveform, and mixes the offset into the motor control loop in [`Main.cpp`](https://github.com/chrgri/diy-sim-racing-ffb-pedal/blob/main/Main.cpp).

## Configuring ABS in the SimHub Plugin

### UI Controls in EffectsTab_ABS.xaml.cs

The primary interface resides in [`SimHubPlugin/UIFunction/EffectsTab_ABS.xaml.cs`](https://github.com/chrgri/diy-sim-racing-ffb-pedal/blob/main/SimHubPlugin/UIFunction/EffectsTab_ABS.xaml.cs). Key controls include:

- **`checkbox_enable_ABS`** – Toggles `Settings.ABS_enable_flag` to activate the effect.
- **`Slider_ABS_freq`** – Sets `payloadPedalConfig_.absFrequency` in Hz (typical range 5–20 Hz).
- **`Slider_ABS_AMP`** – Controls `payloadPedalConfig_.absAmplitude` (stored as kg/20, displayed as percentage).
- **`AbsPattern`** – Selects `payloadPedalConfig_.absPattern` (`0` for sine wave, `1` for saw-tooth).
- **`EffectAppliedOnForceOrTravel_combobox`** – Sets `payloadPedalConfig_.absForceOrTarvelBit` (`0` for force offset, `1` for travel offset).
- **`Simulate_ABS_check`** and **`btn_testABS`** – Trigger `payloadPedalConfig_.Simulate_ABS_trigger` or `calculation.SendAbsSignal` for one-shot testing.

All changes raise `ConfigChangedEvent(dap_config_st)`, streaming the updated struct to the ESP32.

### Configuration Structure in payloadPedalConfig.cs

The [`SimHubPlugin/VariablesStruct/payloadPedalConfig.cs`](https://github.com/chrgri/diy-sim-racing-ffb-pedal/blob/main/SimHubPlugin/VariablesStruct/payloadPedalConfig.cs) struct defines the binary protocol:

```csharp
public byte absFrequency;          // Hz
public byte absAmplitude;          // kg/20 (converted to % in UI)
public byte absPattern;            // 0 = sine, 1 = saw-tooth
public byte absForceOrTarvelBit;   // 0 = apply to force, 1 = apply to travel
public byte Simulate_ABS_trigger;  // 1 = simulate, 0 = normal operation
public byte Simulate_ABS_value;    // % trigger level for simulation

```

These fields travel over serial as part of the larger `DAP_config_st` payload.

## Firmware Implementation on ESP32

### Waveform Generation in ABSOscillation.h

The [`ESP32/include/ABSOscillation.h`](https://github.com/chrgri/diy-sim-racing-ffb-pedal/blob/main/ESP32/include/ABSOscillation.h) header declares the core function:

```c
void forceOffset(DAP_calculationVariables_st* calcVars_st,
                 uint8_t absPattern,
                 uint8_t absForceOrTarvelBit,
                 float * absForceOffset,
                 float * absPosOffset);

```

The implementation calculates a periodic waveform based on elapsed time stored in `calcVars_st->elapsedTime`. For **sine wave** (`absPattern == 0`):

```c
float period = 1.0f / cfg->absFrequency;
float t = calcVars_st->elapsedTime;
float wave = sinf(2.0f * M_PI * t / period);

```

For **saw-tooth** (`absPattern == 1`):

```c
wave = fmodf(t, period) / period;  // 0..1 ramp

```

The amplitude scales by `cfg->absAmplitude * 0.05f` (converting kg/20 units to approximate Newtons). The **mode selector** (`absForceOrTarvelBit`) determines the output:

```c
if (absForceOrTarvelBit == 0) {
    *absForceOffset = amp * wave;   // apply as force
} else {
    *absPosOffset = amp * wave;     // apply as travel displacement
}

```

### Integration in Main.cpp

The main control loop in [`ESP32/src/Main.cpp`](https://github.com/chrgri/diy-sim-racing-ffb-pedal/blob/main/ESP32/src/Main.cpp) invokes the ABS module each cycle:

```c
float absForceOffset = 0.0f;
float absPosOffset = 0.0f;

absOscillation.forceOffset(&dap_calculationVariables_st,
                           dap_config_pedalUpdateTask_st.payLoadPedalConfig_.absPattern,
                           dap_config_pedalUpdateTask_st.payLoadPedalConfig_.absForceOrTarvelBit,
                           &absForceOffset,
                           &absPosOffset);

// Mix into final motor command
totalForce += absForceOffset;
targetPosition += absPosOffset;

```

The offsets blend with the normal pedal physics, creating the pulsating sensation without disrupting the base force calculation.

## Testing and Debugging ABS Effects

The **Simulate_ABS_trigger** field enables hardware-in-the-loop testing. When `Simulate_ABS_trigger` is set to `1`, the firmware uses `Simulate_ABS_value` as a virtual wheel-slip threshold, generating the ABS pulse regardless of actual game data.

For one-shot debugging, the **Test ABS** button toggles `calculation.SendAbsSignal`. This flag forces a single period of the configured waveform, allowing you to verify motor response and mechanical damping without entering a race.

## Summary

- **Enable ABS** via the `checkbox_enable_ABS` in [`EffectsTab_ABS.xaml.cs`](https://github.com/chrgri/diy-sim-racing-ffb-pedal/blob/main/EffectsTab_ABS.xaml.cs) to activate the effect pipeline.
- **Tune parameters** through `payloadPedalConfig` fields: `absFrequency` (Hz), `absAmplitude` (kg/20), `absPattern` (0=sine, 1=saw-tooth), and `absForceOrTarvelBit` (force vs travel).
- **Generate waveforms** in the ESP32 firmware via `ABSOscillation.forceOffset()`, which calculates real-time offsets based on elapsed time and configuration.
- **Integrate** by calling `forceOffset()` in [`Main.cpp`](https://github.com/chrgri/diy-sim-racing-ffb-pedal/blob/main/Main.cpp) and mixing the returned offsets into the final motor command.
- **Test** using `Simulate_ABS_trigger` for continuous simulation or `SendAbsSignal` for one-shot debugging.

## Frequently Asked Questions

### What frequency should I set for realistic ABS simulation?

Most modern vehicles exhibit ABS pulsations between **12 Hz and 16 Hz**. Setting `absFrequency` to **15** in the SimHub plugin produces a realistic rapid stutter, while lower values around **8 Hz** simulate older ABS systems or gravel surfaces where the modulation is slower.

### Can I apply ABS effects to pedal travel instead of force?

Yes. Set `absForceOrTarvelBit` to `1` (travel mode) in `payloadPedalConfig`. In this mode, `ABSOscillation.forceOffset()` writes the waveform to `absPosOffset` rather than `absForceOffset`, causing the pedal position to oscillate physically while maintaining constant force. This is useful for hydraulic-style pedals where travel modulation feels more realistic than force spikes.

### How do I test ABS effects without driving in a simulator?

Use the **Simulate_ABS_trigger** flag. Set `Simulate_ABS_trigger` to `1` and specify a threshold percentage in `Simulate_ABS_value`. The firmware will generate the ABS waveform continuously regardless of game telemetry. Alternatively, click the **Test ABS** button in the UI, which toggles `SendAbsSignal` to fire a single, immediate pulse for hardware validation.

### What is the difference between sine and saw-tooth ABS patterns?

The **sine wave** (`absPattern = 0`) produces smooth, sinusoidal oscillations that feel like a gentle pulsing under the foot, similar to road-car ABS. The **saw-tooth** (`absPattern = 1`) generates a sharp ramp-up and sudden drop, creating a more aggressive, mechanical clicking sensation typical of racing ABS systems or older pumps. Choose the pattern that matches your vehicle class and personal preference.