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– TogglesSettings.ABS_enable_flagto activate the effect.Slider_ABS_freq– SetspayloadPedalConfig_.absFrequencyin Hz (typical range 5–20 Hz).Slider_ABS_AMP– ControlspayloadPedalConfig_.absAmplitude(stored as kg/20, displayed as percentage).AbsPattern– SelectspayloadPedalConfig_.absPattern(0for sine wave,1for saw-tooth).EffectAppliedOnForceOrTravel_combobox– SetspayloadPedalConfig_.absForceOrTarvelBit(0for force offset,1for travel offset).Simulate_ABS_checkandbtn_testABS– TriggerpayloadPedalConfig_.Simulate_ABS_triggerorcalculation.SendAbsSignalfor 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_ABSinEffectsTab_ABS.xaml.csto activate the effect pipeline. - Tune parameters through
payloadPedalConfigfields:absFrequency(Hz),absAmplitude(kg/20),absPattern(0=sine, 1=saw-tooth), andabsForceOrTarvelBit(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()inMain.cppand mixing the returned offsets into the final motor command. - Test using
Simulate_ABS_triggerfor continuous simulation orSendAbsSignalfor 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →