I've written here about the need to build a customized pad-like controller for my racing games:
http://jakkul.blogspot.com/2015/05/sim-racing-and-game-controllers-part-1.html Now I've managed to find 3 hours yesterday to put the thing together. But lets start from the beginning.
The Plan
The goal is to have the right hand operate the steering wheel
potentiometer, the left hand's index and middle finger to operate
accelerator and brakes, left thumb to operate gears up and down. After a
long debate I came up with this:
|
The Plan |
The ingredients
The thing that looked the most like the case for the device was a
tupperware-like food container. It's also easily available, easy to
drill and put things on and has a low low price of zero.
I also bought:
- Arduino Leonardo (clone I guess),
- two thumb joysticks,
- four buttons (two used),
- one linear 10k potentiometer,
- some cables.
|
The stuff |
Building
Building was a fun and easy part. I've screwed everything to the container, made a hole for cabling and connected together.
Connecting it all was easy:
- 5V and ground everywhere,
- digital pins 2 and 3 to the gear switches,
- X axis of the thumb joysticks (both) to analog lines 1 and 2,
- potentiometer to analog line 0.
I haven't connected the rest of the stuff available in the joysticks - that was not needed.
Starting up
I've used the following excellent howto on how to get Arduino Leonardo to behave like a Joystick:
http://www.instructables.com/id/Add-USB-Game-Controller-to-Arduino-LeonardoMicro/?ALLSTEPS. This is also very helpful:
http://www.imaginaryindustries.com/blog/?p=80&cpage=1.
There are two files that you need to get into your Arduino IDE
environment (HID.cpp and USBAPI.h) that define the Joystick, that is not
defined in Arduino IDE standard distribution.
I've used Arduino IDE 1.6.4 and Windows 7 64bit. I'm a linux addict, but
since this is to be used in racing games, I wanted to test it straight
away.
The step 2 of the howto mentioned above provides a test sketch (Arduino
program) that allows for the arduino board to send signals as a joystick
to your PC. The code that I've made basing on that and other examples
in the net is presented below. You can switch displaying all values on
COM port for double checking if it works. You can also tune your
potentiometers and joysticks using max-min ranges. Keep in mind, that
Arduino reads potentiometers and joysticks, returning and integer
ranging from 0 to 1023, and the Joystick class requires the values to be
between -127 and 127 for each axis.
Summary
It just works! I can now play my racing games with a full analogue
controller without the hassle of a steering wheel. It's a different kind
of fun, but still fun :)
The code
int useserial = 1;
float steeringmin = 0;
float steeringmax = 1023;
float brakemin = 501; //0;
float brakemax = 1023;
float accelmax = 1023;
float accelmin = 520; //0;
// 0 steer 1 brake 2 accel
float min = -127;
float max = 127;
float diff = max - min;
void setup() {
Joystick.begin();
if (useserial == 1 )
{
Serial.begin(9600);
}
}
void loop() {
float steer = (max - min) / (steeringmax - steeringmin) * ((float)analogRead(0) - steeringmin) + min;
float accel = (max - min) / (accelmax - accelmin) * ((float)analogRead(2) - accelmin) + min;
float brake = (max - min) / (brakemax - brakemin) * ((float)analogRead(1) - brakemin) + min;
int gearup = digitalRead(2);
int geardown = digitalRead(3);
if (steer > max) {
steer = max;
}
if (steer < min) {
steer = min;
}
if (accel > max) {
accel = max;
}
if (accel < min) {
accel = min;
}
if (brake < min) {
brake = min;
}
if (brake > max) {
brake = max;
}
if (useserial == 1 )
{
Serial.print ((int)steer);
Serial.print (' ');
Serial.print (analogRead(0));
Serial.print (' ');
Serial.print (accel);
Serial.print (' ');
Serial.print (analogRead(2));
Serial.print (' ');
Serial.print (brake); Serial.print (' ');
Serial.print (analogRead(1));
Serial.print (' ');
Serial.print (gearup);
Serial.print (' ');
Serial.println (geardown);
}
if (gearup == 0)
{
Joystick.pressButton(0);
} else {
Joystick.releaseButton(0);
}
if (geardown == 0)
{
Joystick.pressButton(1);
} else {
Joystick.releaseButton(1);
}
Joystick.setXAxis((int)steer);
Joystick.setYAxis((int)accel);
Joystick.setZAxis((int)brake);
Joystick.sendState();
}