On one fated late August day, my Subaru BRZ came to a surprising halt in the keyhole at Road Atlanta. It was going to take a while to source and buy a new engine and I still wanted to get some seat time in.
Enter a crazy idea: Why not use the car's electronics to control a virtual BRZ on Forza?! 🤔
Seat time is the best way to develop your skills as a driver. It's hard to keep your skills sharp when you're not at the racetrack. Most people turn to buying sim rigs to alleviate that.
These usually include a gaming PC (or console), steering wheel, pedals, gear shifter, monitor rig, racing seat, handbrake, VR headset, and a rig or frame to tie everything together.
These setups spiral up in cost as you start to invest in it. This is exacerbated once you want to replicate the feel of an actual car with direct drive steering wheels, load cell pedals, and all sorts of other fancy but really expensive components.
To work with an Xbox, we feed our data into an Xbox Adaptive Controller (more on that below). You can remove some of the complexity and cost of this solution if you're only targeting a PC. The Xbox solution, however, works for both PC and Xbox.
Even with the purchase of the Adaptive Controller, the total cost of parts comes to less than the cost of an entry level steering wheel, the Logitech G29. The parts breakdown is as follows:
|Xbox Adaptive Controller||$99.00||1||$99.00|
|Xbox Trigger Breakout||$9.99||1||$9.99|
As mentioned before, your car has a bunch of different ECUs and sensors that communicate over a CAN bus. The easiest way to tap into this data is by using the standardized OBD2 port.
While there are tons of CAN reverse engineering tools available, I chose the Macchina M2 because of its developer friendliness out of the box.
You can use a tool like SavvyCAN (using the M2RET firmware) or Comma AI's Cabana to reverse engineer the signals for your car. I had previously done so and utilized the following signals for the Subaru BRZ (it works for almost all modern Subarus)
On manual BRZs, you cannot get the exact gear the car is in (this is derived from engine RPM and vehicle speed when you're on the road). We'll workaround this in the future. UPDATE: Gear detection now works thanks to a motion sensor!
You can find the firmware for the Macchina M2 on GitHub.
We can utilize the Atmel SAM3X's native USB functions on the M2. By emulating an Human Interface Device (e.g. mouse, keyboard, joystick) gamepad, we can pretend that the car is the joystick. Using a modified version of the ArduinoJoystickLibrary, we setup HID descriptors that will differ depending on if you're using a PC or Xbox:
|Signal||Xbox Mapping||PC Mapping|
|Accelerator||Right trigger (MCP4261)||X axis|
|Brakes||Left trigger (MCP4261)||Y axis|
|Steering||Left thumbstick||Z axis|
|Downshift||X (remapped from X1)||N/A|
|Gears 1 - 6||N/A||Buttons 0 - 5|
|Clutch||Left bumper||Button 9|
|Rewind||Y (remmpped from X2)||N/A|
For Xbox, we need to pipe the USB joystick data into an Xbox Adaptive Controller to workaround the limitation of only Xbox licensed hardware It would've been nice to use the USB port on the Adaptive Controller for all inputs. Unfortunately, we've got two issues:
Instead of wasting the granularity of our throttle / brake pedals on a digital on/off, we'll utilize the Adaptive Controller's 3.5mm inputs for the triggers to get the full range of control.
We use an 3.5mm audio jack that includes microphone input. This is so that the controller can provide us a reference voltage of 1.8V to run our 10k potentiometer against. We feed this into the digital potentiometer and control the resistance over SPI.
To make for a cleaner setup, I made this Xbee breakout for the M2 for both triggers. You can purchase it here: https://www.tindie.com/products/18061/
Now that we've got all the separate bits, we can put the system together! Here's a video of the first startup:
Now, just add friends and you get a pretty snazzy setup for time attack and drift competitions! Cheers 🙌