notes/blog/g27_pedals.md

183 lines
5.0 KiB
Markdown
Raw Normal View History

2024-04-13 19:44:27 +00:00
---
author: Akbar Rahman
2024-04-13 19:52:42 +00:00
pub_date: Tue, 04 Aug 2020 15:20:13 +0100
2024-04-13 19:44:27 +00:00
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>
2024-04-13 19:54:16 +00:00
<img src="./images/repurposing-racing-wheel-pedals-g27-pinout.svg" class="centered" style="width: 10em;">
2024-04-13 19:44:27 +00:00
<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 &lt; mina) mina = rva;
if (rvb &lt; minb) minb = rvb;
if (rvc &lt; minc) minc = rvc;
if (rva &gt; maxa) maxa = rva;
if (rvb &gt; maxb) maxb = rvb;
if (rvc &gt; 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 &gt; 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>