Reading Gameport Joystick into Arduino

I'm working on converting an old Thrustmaster WCS Mk2 and Flight stick combination to USB (For fun and education) via the Arduino Micro and the NicoHood\HID library, so far things have gone pretty smoothly, I have all the axes reporting and all the buttons are read via a pair of shift registers but I've run into an issue with the joystick pots that I'm unsure how to solve.

In the Gameport joystick the pots are ~100k pots that are connected to power and signal via their first and second pins, since the Arduino cannot read resistance directly I've setup a voltage divider for each of the axes so I can read the voltage difference as the pot is turned.

When using a 100k ohm resister as R2 in the divider I got a range of 2.5V - 5V as would be expected, however, I wanted to take full advantage of the 10 bit ADC and moved from a 100k to a 22k, this allowed a range of about 4.8V to .8V.

At this point I noticed that the voltage divider was having the interesting effect of biasing the values coming into the Arduino. What I mean by this is as the pot was turned there were smaller steps at the lower end of the scale than the larger end.

I ran a simulation through falstad, comparing the response from a voltage divider with a 100k pot as r1 and a 22k resister as r2 and confirmed that the response is non-linear, whereas with a linear pot, the response is nearly linear, as expected.

My question is, after all that preamble, is there a way to read the analog values from the joystick in a linear way, utilizing as much of the resolution of the 10 bit ADC as possible, without modifying the joystick? Obviously I could gut the stick and rewire the pots, but I'd like to avoid this with either a hardware or software compensation of some kind so that other gameport joysticks might also work, but I'm afraid I'm a little out of my depth.

I've researched the issue and from what I've seen so far, most people seem ok with just utilizing the 2.5 to 5v range with less non-linearity, but I'd like to have higher resolution and I'm sure there must be a solution!

Any suggestions are greatly appreciated!

Any suggestions are greatly appreciated!

As your Google seems to be defective, I’ll post you a link which was found by the Google I have.

While I appreciate the input and sarcasm, my Google doesn't seem to be as defective as your reading comprehension :o

...most people seem ok with just utilizing the 2.5 to 5v range with less non-linearity, but I'd like to have higher resolution and I'm sure there must be a solution!

Built to Specs article shows them using a 100k R2 for their voltage divider and sampling from the resultant 2.5v-5v range, which is fine for their application as they only wanted 180 data points anyways, in my case I'm looking to utilize as much of the 10 bit range as possible while maintaining linearity.

Currently I've increased the voltage range by using a 22k R2, providing a range of ~4.8v-~.8v but at the cost of drastically worse linearity, that's the problem I'm trying to solve.

For anyone still pondering this, a quick suggestion that it might be possible to make linear measurements by using 558 (very common and inexpensive IC) and measuring its pwm output (this is actually the way gameport was originally designed to be measured with). If I remember correctly, Teensy or some other MCU has hardware PWM inputs, which would make the measuring as easy as an analog pin. Without a hardware pwm input you need to measure the pulse width by polling with DigitalRead();

Another, perhaps not so elegant way could be to feed your voltage divider from a higher voltage - say 12V, with an upper resistor of say 150K. That way the voltage would move between 0 and 4.8V, on much more linear range, although not completely linear. If you do this, you NEED to protect the analog input pin by grounding it with a zener diode - or it very likely will die the first time there’s any contact problem with the joystict and thus the pin voltage gets to rise to 12V through the 150K upper resistor.

Hope this helps.