[solved]Problem with unojoy and potentiometer range

Hello to the Arduino community 8)

My project is to use a real arcade flightstick to play a specific game on PS3 console.

The arcade controls are composed with this, for the analog part ->

  • 5K potentiometer for the flightstick X movement
  • 5K pot. for the flightstick Y movement
  • 5K pot for the throttle control

..and a couple of pushbuttons (digital).

Someone pointed me the Arduino and the ‘UnoJoy' code to program it, which is exactly what I need for my project.

So I’ve got the Arduino Rev3, cabled the potentiometers & digital buttons, injected the Uno Joycode… and … YES! It works as expected… :slight_smile: I can move my arcade joytick in all the directions, and move the throttle stick up and down, they are all working in my PS3 game…

...but...

When I move my arcade flightstick to the extreme left, the plane inside my PS3 game doesn’t go to the extreme left. It goes to the left, yes, but not to the extreme left. Same for the right movement of course

Here’s the reason : when my arcade flightstick is positioned to the extreme left, the potentiometer itself for that axe is not to its extreme left position. Same problem for the extreme right position. Let me figure this.

  • here is the full 'physical' range of my joytick for the X axe (in green) ->

  • here’s the full range of the X potentiometer (in green)

-> my arcade flight stick ‘physically’ cannot reach the red range on left and right :

consequence in my game -> my plane cannot turn to the extreme left/right. =(

If I used a PC computer, it wouldn’t be a problem, because a simple calibration should fix that, but because I’m using a PS3, any ‘software’ calibration is impossible. :blush:

The idea would be to tell the arduino to move the ‘0’ potentiometer value to the of the ‘0’ position from my arcade stick, and of course bring back the last value ‘255’ from the potentiometer into the extreme right position of my arcade stick. So the full range of my arcade flight stick will be adapted to the full range of values my PS3 is expecting.
In order to have this ->

In the Unojoy.h, I spotted something that may help me? ->

        uint8_t padding : 7;     // We end with 7 bytes of padding to make sure we get our data aligned in bytes
                                 
		uint8_t leftStickX : 8;  // Each of the analog stick values can range from 0 to 255
		uint8_t leftStickY : 8;  //  0 is fully left or up
		uint8_t rightStickX : 8; //  255 is fully right or down 
		uint8_t rightStickY : 8; //  128 is centered.
                                 // Important - analogRead(pin) returns a 10 bit value, so if you're getting strange
                                 //  results from analogRead, you may need to do (analogRead(pin) >> 2) to get good data

As far as I understand, If I change these values, I should move my logical '0' point a little bit further on one 'physical' potentiometer?
So I tried to change this as a test :

		uint8_t leftStickX : 8;  // Each of the analog stick values can range from 0 to 255

...into this ->

		uint8_t leftStickX : 16;  // Each of the analog stick values can range from 0 to 255

So 8 -> 16 for the X axe ...but as a result, all my other axes go wrong, wich is very strange because the modification has only be done on the X axe ?!

I also tried other values, lower, bigger ...only for that axe X ... but always different problems like nore more axes movables or going crazy?!

Note that each time I put back that original value '8' on that line, everything is going back to normal (exept my range problem I'm trying to sovle here). In addition, it seems that only that '8' value works... for all the test I've done with other values, everything go wrong! :blush:

Oh, I also checked into the UnoJoyArduinoSample.ino file, and spotted this :

  // Set the analog sticks
  //  Since analogRead(pin) returns a 10 bit value,
  //  we need to perform a bit shift operation to
  //  lose the 2 least significant bits and get an
  //  8 bit number that we can use  
  controllerData.leftStickX = analogRead(A0) >> 2;
  controllerData.leftStickY = analogRead(A1) >> 2;
  controllerData.rightStickX = analogRead(A2) >> 2;
  controllerData.rightStickY = analogRead(A3) >> 2;
  // And return the data!
  return controllerData;

Maybe something to do here too?

Do you have an idea about how I can fix my potentiometer 'range' problem? =(
I'm familiar wih programation in general, but first time I see arduino code programmation. Maybe a simple 'X value' = 'X value' + 'something' somewhere in that code should help me the skip the red zones that my arcade joystick cannot handle?

Thanks for your help.

Woah woah woah woah woah; you don't want to mess around in the UnoJoy.h file; you'll break everything forever. Well, not really, but you won't fix anything, and it won't work until you change that back to what it was.

What that :8 and :16 are are lengths of bitfields that the UnoJoy library is sending over to the code on the ATmega8u2, and ultimately turning that into controller data. When you changed it from 8 to 16, you were telling the UnoJoy library 'I'm sending 16 bits of data in my X axis now', but the ATmega8u2 chip doesn't know that, so it's using the first 8 bits of data you're sending for the X axis, then the next 8 bits for the Y axis.

So, all the changes you want to make are going to be in the UnoJoyArduinoSample.ino file (which you should Save As... something else, so you'll still have the original sample reference implementation intact when you want to make something else).
You're on the right track when you're looking at the

// Set the analog sticks
  //  Since analogRead(pin) returns a 10 bit value,
  //  we need to perform a bit shift operation to
  //  lose the 2 least significant bits and get an
  //  8 bit number that we can use  
  controllerData.leftStickX = analogRead(A0) >> 2;
  controllerData.leftStickY = analogRead(A1) >> 2;
  controllerData.rightStickX = analogRead(A2) >> 2;
  controllerData.rightStickY = analogRead(A3) >> 2;

block - In this block, you're setting the values you want the controller axes to be at. All of the stick axes UnoJoy uses are 8 bits long, so we need to make sure that we're giving it 8 bit data. That's why this code takes the raw analogRead data and shifts it over by 2 bits, turning a 10 bit value into an 8 bit value.

What you want to do is to take the range of values that your potentiometer actually gives you and map that to the range that UnoJoy can use (0 to 255). For that, I'd use the map() function built into Arduino.

So, figure out what range of values your pot sends out (look in the Examples->Basics->AnalogReadSerial), then put in some code like:

 uint8_t lStickX = map(analogRead(A0), whatever your minimum was, whatever your maximum was, 0, 255);
LStickX = constrain(LStickX, 0, 255); // Make sure you don't have too high or low a number
controllerData.leftStickX = lStickX;

Anyhow, that should map the values your Arduino actually sees to the values you want the controller to give. Hope it helps!
-Chatham
UnoJoy.com

A HUUUGE thank you to you, Chatham!

After following your clear instructions :

Use the AnalogReadSerial command to read and display the min/max values from the three potentiometers, and adapt the UNOJOY code with the use ofthe magial map function...it works great now, thank you so much! 8) Your UNOJOY code is just awesome! I'm sure I'll use it for others projets.

Now that the proof of concept on the 'control part' of my project is totally working, I'll move to the next part which will be piece of cake now :slight_smile: I'll publish a video of all that stuff working when the project will be done 8)

...and the project is now completed! :slight_smile:

Here's the beast powered by Arduino/UnoJoy :

All the details right here.