As an epically nerdy birthday present to myself I bought a Velleman K8055 USB Experiment Interface Board from Maplin (25GBP as a kitset) and then set about finding an application for it. Ultimately I would like to build a force feedback chair for my racing sims, but that will have to wait until I'm better settled and have the equipment and space to work on it. So instead I decided to build a modification to the brake pedal of my Fanatec Porsche 911 Turbo Wheel that would give it vibration feedback to indicate whether the wheels were locked under braking. As I have very little experience in either electronics or programming, and none at all in programming for devices, this was more about the fun of the journey than the destination.
I broke the project up into 5 phases that would let me take baby steps, and so that I could enjoy sending emails back home to my family telling them "phase 3 is complete". Yep, now approaching dork factor 9. I hoped that each phase would take me about an evening to complete, and quite amazingly that is more or less how it turned out.
Phase I - in which Doris gets her oats
This was supposed to be the easiest phase, and it was: I assembled the kit in about 2.5 hours (the instructions and components were very clear and well laid out) and on connecting it to my computer got a real thrill seeing the "now connecting" LED flash. The included test program lit up the indicator LEDs on the digital and analog ports, and pressing the buttons and turning the pots on the board was displayed in sympathy on the computer screen. Success!
Phase 2 - Write my own test program in Visual Basic
Having never written code to control a device, I decided to make a very simple program in Visual Basic (.net), which I am somewhat familiar with. There is a supplied dll that handles the communication to the board and all my program had to do was provide an interface to that dll. My program simply connected to the board and let the user turn a single LED on and off. It sounds trivial in hindsight, but it was quite a break through as this is the basis of the functionality required for hardware side of the mod. Unfortunately the software side required knowledge of a different language...
Phase 3 - Write my own test program in C++
C++ was totally unfamiliar territory to me, so this phase was simply about replicating the functionality of the VB code in C++. Luckily Microsoft have made free VB and C++ editors/compilers ("Express Editions", whatever that means) and with Google at my side I managed to make an exe that could toggle an LED on and off. It was failing to compile until I found that I needed a different version of the dll for it to work in C++ (called K8055D_C.dll).
Phase 4 - Write a plug-in for rFactor
rFactor will load up any correctly formatted C++ dll that is placed in its plugin directory, and feed it with vehicle and environment telemetry. I used the internals plugin supplied by ISI as a template to make my own code, and predictably spent most of the time fixing compile time bugs. My plugin used the following logic to determine when to turn on vibration (NB: this doesn't list all of the routines needed):
for( long i = 0; i < 4; ++i ) // Check all wheels for lock up
{
const TelemWheel &wheel = info.mWheel[i];
if(3.0*abs(wheel.mRotation)/metersPerSec<=.5) // if wheel is rotating slower than 50% vehicle spd { // speed@hub = dist/time = dist/angle * angle/time = 1.9m/2*pi * .mRotation = 3 * .mRotation
++sumLocked; // count how many wheels are locked
}
} // End rotation check
if (info.mUnfilteredBrake >= 0.1 && metersPerSec >= 1.0) // Are we moving AND braking?
{
if(sumLocked >= 1) // If we are moving AND braking AND have lockup in at least n wheels then...
{ SetDigital(6); // Send digital feedback (turn on digital output 6 - vibration)
SetAnalog(2,0); } // Send analog feeback (set analog channel 2 to zero - LED brightness)
else SetAnalog(2, min(abs((long) info.mWheel[3].mRotation*1.5),255)); // otherwise analog 2 represents brake disc rotation speed as the brightness of an LED on the board
}
else // If not braking OR moving
{
ClearDigital(6); // If we aren't braking OR we aren't moving then there should be no FFB
SetAnalog(2,0);
}
Having it actually work in rFactor first time (albeit some tuning necessary) was such a rush! When I brake analog LED 2 decreases in brightness as brake rotor speed reduces, and if 1 or more wheels is locked then digital LED 6 turns on.
Phase 5 - Add vibration functionality to brake pedal
I dismembered a PlayStation 2 Dualshock controller and took the beefier of the two vibration motors (DC motor driving an off-center mass). Using a rubber-band I was able to secure this surprisingly firmly to the back of the brake pedal. To drive the motor I use 4 NiMH AA cells. The power circuit is switched by a small relay, which is in turn switched by digital channel 6 of the board. Velleman says that an external supply is necessary for switching the relay, but that seemed ridiculous given that the board itself runs off the 5V supplied by the computer. I couldn't find anything on the net that indicated that this was possible, but after a lot of thinking, spec-sheet reading, and nervous experimentation I got it working with the internal supply (a woo-hooo moment). [For any skulking Googlers, I'll try and produce a schematic of what I did -- it was fairly simple... if I don't get around to this you can email me]
The Result
I had originally wanted to get the vibration motor powered by PWM, which the board supports in the analog channels, but this would mean running the motor by the board itself and it would pull way too much current. As it is I've settled with having the vibration motor switched digitally - at the moment its turned on when the brakes are locked, but the original plan was to have it switched on when braking, and turned off if a wheel locked. I will try this at some point.
In game it is surprisingly fun to have the brake pedal suddenly start shaking as I over-estimate grip in the braking zone. The amount of vibration was just right straight out of the box, I have no plans to boost it or subdue it. I'm not sure that it will help lap times as I'm usually aware that lockup is imminent before I consciously feel the FFB, but it certainly adds to the fun. Having said that, the brake vibration made me aware that I was consistently locking a wheel on entry to a particular corner at Silverstone in a Formula Ford - something I hadn't picked up on from sound or visual cues. Fanatec has recently released its own plugin that does a similar thing with the vibration motors inside the wheel, and feeling vibration in both hands and a foot while sliding towards the outside of a bend in a cloud of tyre smoke is really immersive!
This project was all about the fun of making something of my own for my favourite hobby, and to learn a new set of skills, and in both those respects it was a complete success. Within a week I needed to program a routine to make measurements from external voltmeters, barometers, etc at work, so this experience was invaluable. In terms of making something I can use in the future it was also quite a success. I'm usually one to design it, build it, use it once to prove it works, and then put it in a drawer, but this mod is still set up and I turn it on on the rare occaisons I play rFactor. Overall it was a big challenge for me but surprisingly frustration free, so I'm desperately trying to think of another fun project I can use the board for.
Addenda:
3 months later: Added .INI file support to the plugin, so that the basic parameters of operation can be edited without having to recompile the plugin, even while playing.
4 months later: Added a similar vibration effect to the clutch pedal using the remaining PS2 motor to define the friction point of the clutch. I shortened the active portion of the clutch pedal travel using dxtweak2 to make it more realistic. It is an interesting addition, but not a must-have.
5 months later: I wrote a VB programme using a GTR2 telemetry control by Nye and now have the brake vibration running in GTR2 -- albeit by a bit of an approximation, given that there is no car speed or position output from the control. Very cool!