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

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) provides the user interface for tuning parameters. The configuration structure (payloadPedalConfig.cs) packs these parameters into a binary struct sent over serial. The ESP32 firmware (ABSOscillation.h) receives the struct, calculates the waveform, and mixes the offset into the motor control loop in 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. 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 struct defines the binary protocol:

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 header declares the core function:

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):

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):

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:

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 invokes the ABS module each cycle:

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 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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →