183 lines
5.0 KiB
Markdown
Executable File
183 lines
5.0 KiB
Markdown
Executable File
---
|
|
author: Akbar Rahman
|
|
pub_date: Tue, 04 Aug 2020 15:20:13 +0100
|
|
title: Repurposing Racing Wheel Pedals
|
|
tags: [ g27, sim_racing ]
|
|
uuid: 0f09200e-fd50-451b-aae1-1117a8a704db
|
|
---
|
|
|
|
<h1>Repurposing Racing Wheel Pedals</h1>
|
|
<p>I have a Logitech G27 I don't use much. I wondered if I could use it for anything else. I could. </p>
|
|
|
|
<h2> The Pinout of the Connector </h2>
|
|
|
|
<p>The first thing I had to do was figure out what each pin did on the DE-9 connector, and which
|
|
ones I should care about.
|
|
This was done easily after I took off the top plastic casing thing by poking the three 100k Ohm
|
|
potentiometers and the connector in the right places at the right times:
|
|
</p>
|
|
|
|
<style> #pinout_table tr td:first-child { text-align: right } </style>
|
|
<img src="/res/repurposing-racing-wheel-pedals-g27-pinout.svg" class="centered" style="width: 10em;">
|
|
<table id="pinout_table">
|
|
<tr> <th>pin</th> <th>function</th></tr>
|
|
<tr> <td>1,4</td> <td>ground</td></tr>
|
|
<tr> <td>6</td> <td>clutch pedal</td></tr>
|
|
<tr> <td>7</td> <td>brake pedal</td></tr>
|
|
<tr> <td>8</td> <td>accelerator pedal</td></tr>
|
|
<tr> <td>9</td> <td>voltage in</td></tr>
|
|
</table>
|
|
|
|
<h2> Reading the Values of the Pots </h2>
|
|
|
|
I'm using an Arduino to read the pots and then do something with the values.
|
|
I very dirtily wired pin 4 on the pedals to GND on a Arduino Uno, pin 9 to 5V, and
|
|
pins 6,7,8 to A0, A1, and A2.
|
|
I used a basic sketch to check that everything is good:
|
|
|
|
<details>
|
|
<summary> Show/hide test_sketch.ino </summary>
|
|
<pre><code> void setup() {
|
|
Serial.begin(9600);
|
|
}
|
|
|
|
void loop() {
|
|
Serial.println(analogRead(A2));
|
|
delay(20);
|
|
}
|
|
</code></pre>
|
|
</details>
|
|
|
|
I noticed that the minimum and maximum values read by the Uno were quite far off 0 and 1024, like
|
|
they should be, and voltage was being lost on the way to and from the potentiometers.
|
|
Since the pedals have to be calibrated every time you plug them in, I assume this is normal and
|
|
spat out this code:
|
|
|
|
<details>
|
|
<summary> Show/hide sketch_aug02a.ino </summary>
|
|
<pre><code>// sensor pins
|
|
int sa = A0;
|
|
int sb = A1;
|
|
int sc = A2;
|
|
|
|
// minimum values detected by the sensors
|
|
int mina = 1025;
|
|
int minb = 1025;
|
|
int minc = 1025;
|
|
|
|
// maximum values detected by the sensors
|
|
int maxa = 512;
|
|
int maxb = 512;
|
|
int maxc = 512;
|
|
|
|
// raw values of the sensors
|
|
int rva, rvb, rvc;
|
|
|
|
// calculated values of the sensors (between 0 and 1, this is the value sent to computer)
|
|
float cva, cvb, cvc;
|
|
|
|
void setup() {
|
|
Serial.begin(9600);
|
|
}
|
|
|
|
void loop() {
|
|
rva = analogRead(sa);
|
|
rvb = analogRead(sb);
|
|
rvc = analogRead(sc);
|
|
|
|
if (rva < mina) mina = rva;
|
|
if (rvb < minb) minb = rvb;
|
|
if (rvc < minc) minc = rvc;
|
|
|
|
if (rva > maxa) maxa = rva;
|
|
if (rvb > maxb) maxb = rvb;
|
|
if (rvc > maxc) maxc = rvc;
|
|
|
|
cva = (float)(rva-mina)/(float)(maxa-mina);
|
|
cvb = (float)(rvb-minb)/(float)(maxb-minb);
|
|
cvc = (float)(rvc-minc)/(float)(maxc-minc);
|
|
|
|
Serial.print('[');
|
|
Serial.print(cva); Serial.print(',');
|
|
Serial.print(cvb); Serial.print(',');
|
|
Serial.print(cvc);
|
|
Serial.print(']');
|
|
Serial.println();
|
|
delay(20);
|
|
}
|
|
</code></pre>
|
|
</details>
|
|
|
|
<h2> Actually Making the Numbers Do Something </h2>
|
|
|
|
This is where you can make the pedals do fun things.
|
|
I reworked another piece of code I wrote to do a similar thing to quickly create a script that
|
|
reads the values sent by the Arduino, and then simulate pressing a key combination.
|
|
The only thing I've done with this is set push-to-talk to ctrl-shift-alt-1.
|
|
I don't know what else I could use this for, maybe temporarily muting particular things, like music.
|
|
|
|
<details>
|
|
<summary> Show/hide pedalboard.py </summary>
|
|
<pre><code> #!/usr/bin/env python3
|
|
|
|
import sys
|
|
import json
|
|
import time
|
|
from enum import Enum
|
|
|
|
import keyboard
|
|
import serial
|
|
|
|
class KeyState(Enum):
|
|
UP = 0
|
|
DOWN = 1
|
|
|
|
STATES = [KeyState.UP] * 3
|
|
THRESHOLD = 0.8
|
|
MACROS = ['ctrl+shift+alt+1', 'ctrl+shift+alt+2', 'ctrl+shift+alt+3']
|
|
|
|
def get_args():
|
|
""" Get command line arguments """
|
|
|
|
import argparse
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('device')
|
|
return parser.parse_args()
|
|
|
|
|
|
def main(args):
|
|
""" Entry point for script """
|
|
while True:
|
|
try:
|
|
kb = serial.Serial(port=args.device, baudrate=9600)
|
|
while True:
|
|
handle(json.loads(kb.readline()))
|
|
except serial.serialutil.SerialException as e:
|
|
print(e)
|
|
print("Failed to connect to device... trying again")
|
|
time.sleep(1)
|
|
except Exception as e:
|
|
print(e)
|
|
return 0
|
|
|
|
def handle(data):
|
|
global STATES
|
|
|
|
states = [KeyState.DOWN if value > THRESHOLD else KeyState.UP for value in data]
|
|
r = [handle_state_change(i, states[i]) if states[i] != STATES[i] else None for i in range(len(STATES))]
|
|
STATES = states
|
|
return r
|
|
|
|
def handle_state_change(key, newstate):
|
|
print(f"{key} {newstate}")
|
|
return keyboard.press(MACROS[key]) if newstate == KeyState.DOWN else keyboard.release(MACROS[key])
|
|
|
|
|
|
if __name__ == '__main__':
|
|
try:
|
|
sys.exit(main(get_args()))
|
|
except KeyboardInterrupt:
|
|
sys.exit(0)
|
|
</code></pre>
|
|
</details>
|