So I'm still using the Arduino racing pad since 2 years. I'm still racing in LFS, now in Assetto Corsa with it. I've complained about what's bad about it. And now I've solved another issue that I've had - the crappy joysticks. I've used FSR402 tensiometers for both accelerator and braking. This seems much more natural than using the lever sticks. And precise. Now I can drive powerful cars with no ABS and TC in Assetto Corsa :)
Why tensiometers?
When I've started thinking about that crappy joysticks, I've looked at what the game consoles are doing for the trigger buttons on the pads:
- X360 pad uses a potentiometer with clever levers,
- Playstation uses tensiometers,
- X One uses Hall Effect sensors.
I wanted to buy the replacement parts for the X360 to check the levers, but the tensiometers are just cheaper. The Hall Effect sensors seem to be a very cool idea, but you really need to have an idea how to sort out the mechanics.
How does it look:
Bad. Ugly. But works.I've placed the tensiometers along another edge of this beautiful lunch box. And now I can use both methods of controlling the speed of the car by just remapping controls. Frankly speaking - I haven't used the levers since I've got the tensiometers running.
Wiring FSR402 to Arduino:
Check this for examples of wiring and code: https://learn.adafruit.com/force-sensitive-resistor-fsr/using-an-fsr. After wiring the tensiometer properly you use it within the code like any other potentiometer.
Video:
Summary:
This just works. I'm using this for gaming weekly or biweekly (you know, 3 kids) for the last 3-4 months.Using tensiometers for game controlers has another potential application. People making pedals for racing always look for methods to measure travel for acceleration and pressure for braking - to simulate real car hydraulics. All not ridiculously expensive steering wheels on the market use potentiometers for all pedals. And with a very simple mechanism (1 swing, some foam) you can get a pressure measuring tensiometer based pedal - you'll need a bigger tensiometer thou.
Code:
The requirements for having this running are described in the part3 of this "journey".
#include "HID-Project.h"
const int pinLed = LED_BUILTIN;
const int pinButton = 2;
// this is for printing to COM - set to 1 to get printouts
const int printuj = 0 ;
void setup() {
pinMode(pinLed, OUTPUT);
pinMode(pinButton, INPUT_PULLUP);
Gamepad.begin();
if ( printuj == 1 ) {
Serial.begin(9600);
}
}
void loop() {
// limits for steering
float steeringmin=0;
float steeringmax=1023;
// limits for joystick braking
float brakemin=0;
float brakemax=1023;
// limits for joystick accelerating
float accelmax=1023;
// limits for tensometer acceleration and braking
float brakemaxb=910;
float accelmaxb=910;
float accelmin=0;
float min=-32767;
float max=32767;
float diff=max-min;
float minB=-123;
float maxB=+123;
float diffB=maxB-minB;
// steering
float steer = (float)analogRead(0)/(steeringmax-steeringmin)*diff + min;
// acceleration, braking for joysticks and for tensometers
float accel = ((float)analogRead(2)/(accelmax-accelmin))*diff + min;
float brake = ((float)analogRead(1)/(brakemax-brakemin))*diff + min;
float accelb = ((float)analogRead(4)/(accelmaxb-accelmin))*diffB + minB;
float brakeb = ((float)analogRead(3)/(brakemaxb-brakemin))*diffB + minB;
// all 4 buttons readouts
int gearup = digitalRead(2);
int geardown = digitalRead(3);
int gearupb = digitalRead(4);
int geardownb = digitalRead(5);
// idiotic deadzones for joystick
if ((accel <= 3) and (accel >= -3)) {
accel=0;
}
if ((brake <= 3) and (brake >= -3)) {
brake=0;
}
// limits for tensometers
if (accelb > maxB) {
accelb=maxB;
}
if (brakeb > maxB) {
brakeb=maxB;
}
// this is the COM printing
if ( printuj == 1 ) {
Serial.print ((int)steer);
Serial.print (' ');
Serial.print (analogRead(0));
Serial.print (' ');
Serial.print ((int)accel);
Serial.print (' ');
Serial.print (analogRead(2));
Serial.print (' ');
Serial.print ((int)brake);
Serial.print (' ');
Serial.print (analogRead(1));
Serial.print (' ');
Serial.print (gearup);
Serial.print (' ');
Serial.print (geardown);
Serial.print (' ');
Serial.print (gearupb);
Serial.print (' ');
Serial.print (geardownb);
Serial.print (' ');
Serial.print (analogRead(3));
Serial.print (' ');
Serial.print ((int)brakeb);
Serial.print (' ');
Serial.print (analogRead(4));
Serial.print (' ');
Serial.print ((int)accelb);
Serial.println (' ');
}
\\ button switching
if (gearup == 0)
{
Gamepad.press(1);
} else {
Gamepad.release(1);
}
if (geardown == 0)
{
Gamepad.press(2);
} else {
Gamepad.release(2);
}
if (gearupb == 0)
{
Gamepad.press(3);
} else {
Gamepad.release(3);
}
if (geardownb == 0)
{
Gamepad.press(4);
} else {
Gamepad.release(4);
}
\\ output to axises. xA is 16bit, the rest I don't remember and it does not matter.
Gamepad.xAxis((int)steer);
Gamepad.yAxis((int)accel);
Gamepad.rxAxis((int)brake);
Gamepad.zAxis((int)accelb);
Gamepad.rzAxis((int)brakeb);
Gamepad.write();
}