2

I have a joystick that outputs the values 0 - 4095. I want to map these values in this fashion (Yes, the reversed mapping is intended):

outputValue = map(inputValue, 4095, 0, -2048, 2047);

However, the neutral central position of the joystick is offset, outputting 145 instead of 0.

Is there a way to map these values - taking the offset value in account - and still have the output values ranging from -2048 to 2047? I fail to do this with the map() function alone, and could need some help with the specific math involved.

1
  • your joystick may have a mechanical adjustment
    – jsotola
    Sep 7, 2023 at 15:36

1 Answer 1

6

You can only approximate it, you have to sacrifice something.

The basic problem is that your input range is asymmetric in respect to the mid point. Let's visualize it this way (with a bit of visual exaggeration):

min                     mid      max
0----------------------2193-----4095                   

Another problem is that the whole range 0..4095 may not be physically reachable by the joystick, so your usable range may actually look like this:

min                mid        max
433---------------2193-------3722                   

So, to calibrate your joystick, you need to measure the min, mid and max points that you can physically reach with exactly that joystick on the input scale (joysticks are analog devices, so their actual ranges can differ from joystick to joystick and even from axis to axis in the same physical joystick).

Now, if you have these numbers (I call those calibration values joy_min, joy_mid and joy_max), you need to map both parts of your range separately:

if( joy_input < joy_mid ) {
  output = map(joy_input, joy_min, joy_mid, -2048, 0);
} else {
  output = map(joy_input, joy_mid, joy_max, 0, 2047);
}

The downside is that any step in the output may represent a slightly different distance in the movement, depending on whether you are currently lower or higher than the measured midpoint. But I expect that to be negligible.

Also, keep in mind that this is only for one axis of the joystick. You may need completely different calibration values for the other axis. In addition, you may want to implement a "dead zone" around the midpoint, i.e. always returning output = 0 for joy_mid-10 < joy_input < joy_mid+10 or something like that.

And as the joystick range may drift (with temperature, age, etc...) and map does not constrain the output range, it might be a good idea to apply a output = constrain(output, -2048, 2047) afterwards.

(In my code, I assume that you want to map 0..4095 to -2048..2047 as you say in the text; but in your code, you map 4095..0 to -2048..2047, basically flipping the direction. If that part of your code is correct and the text is not, just swap -2048 with 2047 in my code.)

1
  • Thanks for your reply. With regards to the reversed mapping, it's intended. I've updated my question.
    – Erik
    Sep 7, 2023 at 7:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.