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;
}
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.
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