Rotary encoder with Windows Game Device Calibration Tool

Hi,

I'm having a bit of a problem with encoders and the built in Windows Game Device Calibration Tool.

I have an encoder and I want it to cover the slider from 0% to 100% in 7 clicks. This means "chunks" of 14% until it practically reaches 100% (98% because I rounded the value 100/7 to be 14). I'm using the map() function to do that (as shown in the code below) and I am able to see the values increasing and decreasing 14% at a time but when I get to 0% and keep on turning the encoder (or 98%, which is 14x7, and continue turning) the value doesn't stop there and keeps on detecting values if I turn it.

This causes that if I want to decrease having reached more than 100% I have to turn the encoder in the opposite direction that many clicks I turned past 100% to see the values decreasing.

I'm not sure anymore if the map() function is suitable for a rotary encoder and discrete values.

Please forgive my explanation if it's not clear.

This is the code I've written but it doesn't solve this issue.

// Reading of encoder2
    long encoderValue2 = myEncoder2.read();
    long axisValue2 = map(encoderValue2, 0, 1023, 0, 7500);
    
    // This is me trying to limit the readings and values to cover just the slider range in 7 steps. No more, no less
   
 if (axisValue2 > 100) {
      
      joystick.setBrake(100); //setting the slider to 100%

    } else if (axisValue2 < 0) {
     
          joystick.setBrake(0);
    }

    joystick.setBrake(axisValue2);


// The following code os for other things regarding encoder 2
    if (encoderValue2 != previousEncoderValue2) {
      handleEncoder2(encoderValue2);
      previousEncoderValue2 = encoderValue2;
    }

Thank you very much for your help.

Regards

From your description I suspect encoderValue2 is going below zero and feeding this (negative) value into the the map() function.

A very brief example in WOKWI:

It wouldn't hurt either to post ALL the code, not just a snippet. Then at least people would know which encoder library you're using.

1 Like

(that link is a new, blank project)

Corrected. Thanks!

1 Like

I supect you are right.

Here's another mapping test, but with dynamic input limits so that the randomly zeroed-out start position can map to the observed range:

It simulates the inputs one might get from powering on an encoder at some arbitrary point in a limited range.

// Physically limited range encoder mapping simulation
// This maps the most current observation to 0-100 in the observed range
// https://wokwi.com/projects/393017345335968769
// for https://forum.arduino.cc/t/rotary-encoder-with-windows-game-device-calibration-tool/1238392/5
const byte PotPin = A0; // Attach to pot wiper
int biasValue; // powerup setting

void setup() {
  // put your setup code here, to run once:
  pinMode(PotPin, INPUT); // Attach to pot wiper;
  Serial.begin(115200);
  biasValue = analogRead(PotPin);
  Serial.println("move the pot to a random position and restart the arduino.");
}

int maxObserved = -10000;
int minObserved = 10000;
int lastObserved = -10000;

void loop() {
  // put your main code here, to run repeatedly:
  int inputVal = analogRead(PotPin) - biasValue;
  if (inputVal != lastObserved) {
    if (inputVal > maxObserved) maxObserved = inputVal;
    if (inputVal < minObserved) minObserved = inputVal;

    int mapVal0 = map(inputVal, 0, 1024, 0, 100);

    int mapVal = map(inputVal, minObserved, maxObserved, 0, 100);

    Serial.print("min:");
    Serial.print(minObserved);
    Serial.print(" obs:");
    Serial.print(inputVal);
    Serial.print(" max:");
    Serial.print(maxObserved);
    Serial.print(" map0:");
    Serial.print(mapVal0);
    Serial.print(" map:");
    Serial.print(mapVal);
    Serial.println();
    lastObserved = inputVal;
  }
}

Thanks Dave, I hadn't thought about that yet. I'll deal with the initialization as soon as I finish with the issue of values below 0% or above 100%.

About those values I have another encoder whose map function is as follows:

long axisValue1 = map(encoderValue1, 0, 1023, 0, 1023);

And it works. If I turn it way past 100% it will decrease as soon as i turn one click to the left. The same at 0% when it turn it to the right. That's why I think my issue comes with the "chunks" of percentages that the read() function gets. In this case they are small so values don't go that far beyond limits (I think, please correct me if I'm wrong). But with the encoder2 mapping I'm struggling.

The encoder library I'm using is:

<Encoder.h>

They are linked. With an encoder, initialization issues cause values below 0% or above 100%.

Why then doesn't the assignment of axisValue to 100 (or 0) work when I ask about the value? It seems as though the code bypasses that and keeps reading values when I turn beyond the limits instead of saying: ok, you are above 100% I'll just keep giving you 100% until you want to go below that

???

What code? The snippet in #1 doesn't compile or look well formed, so I really can't say why it does what you say it does.

I can say that because map is defined as:

that this map function really isn't going to do much of anything different than axisValue=encoderValue:

map() doesn't constrain().

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.