Calibrating a potentiometer

I am using the joystick library to make a throttle quadrant for a flight simulator.
I'm using a linear potentiometer as an input for the throttle position. The lever I've attached to the potentiometer doesn't allow the potentiometer to move through its full range of motion so I have to use the map function to map the potentiometer reading to a range of -127 to +127.

I have used the method given in the calibration tutorial to determine the maximum and minimum possible reading if the potentiometer.
https://www.arduino.cc/en/Tutorial/BuiltInExamples/Calibration

However when I run the sketch, I get values for the minimum and maximum values which are outside the actual sweep of the potentiometer. Because of this, the map function never returns the maximum or minimum values even when the potentiometer levels is moved to it's extreme positions .

Why am I getting these incorrect values for maximum and minimum range?

Your circuit or calibration is incorrect. If you connect the pot between Vcc and Gnd and the wiper to the analog input then you only need a loop that measures and outputs the values to Serial Monitor. Then turn the pot to the min and max position, record the values, and you're done with the calibration.

What's the resistance of your pot? Recommended is <50k.
How long are the wires to the controller? Can they catch ambient noise?

It's a 10k potentiometer.
The connections are exactly as you've mentioned.
The wires are only about 20cm long.

So what are the raw min/max values you are reading while calibrating and later?

During calibration.. the max value will be about 560
And the min value will be about 200

During normal operation the pot will only go to a max of about 500 and a min of maybe 190 .

These are just examples. I'll upload the sketch at soon as possible. I don't have access to my PC at the moment.

Then use just these values.

I've tried that obviously!
The values change each time I restart the Arduino. Otherwise there would be no need for calibration.

That's another thing.. I don't understand why these values change every time I reset the Arduino.

Hello
Did you post your current sketch and schematic to see how we can help?

[quote="mahela007, post:7, topic:985210"]

You'd still have to calibrate (map) but you could have "permanent" fixed-calibration built-into your code. That's what I'd expect you to be doing.

If the pot and the Arduino are using the same 5V power supply it shouldn't change very much. Your variations are more than I'd expect.

  • There's a chance that your mechanical construction isn't "solid".

  • There will always be some noise, but that noise can be less than one-count. A capacitor (maybe 0.1uF or larger) between the analog input and ground can help to reduce the nose and/or "slow down" the variations. Any noise on the power supply (the ADC reference) can also affect the ADC readings.

  • With any analog-to digital conversion there is always a chance of being on the "hairy edge" between two counts.

Well my mechanism is as simple as can be. Just a stick glued to a potentiometer.
As for the power supply, the Arduino is being powered over the USB port from the PC.

Here is my sketch

#include <Encoder.h>
#include <Joystick.h>

const int scaleFactor = 2.3;

//the pins used by the rotary encoder
int pinA = 2;
int pinB = 3;
int clickPin = 9;

int highPin = 5; //pin to supply 5V out because the Vout pin is already in use.

int potSensorPin = A2;

//parameters and values for EMA filtering algorith used for filtering potentiometer value
int EMA_S = 0; // EMA S
int oldEMA_S = 0;
float EMA_a = 0.3; //filtering value


int sensorValue = 0;


long oldPos = -999;
long newPos = 0;

long output_ = 0;

//The range of values that the arduino will output to the PC
//to emulate the joystick axis
long maxValue = 127;
long minValue = -127;

//the minimum and maximum value of the potentiometer viper 
//will be used to map the potentiometer value to a range between maxValue and minValue above
int potMinimum = 0; 
int potMaximum = 0;

Encoder trimWheel(pinA, pinB);
Joystick_ Joystick(
  0x15, JOYSTICK_TYPE_JOYSTICK,
  3, //Number of buttons
  0, //No hat switches
  true, // this stick does have an X axis
  true, // this tick does have a Y axis
  false, //no z axis
  false, //no X rotation axis
  false, //no Y rotation axis
  false, //no Z rotation axis
  false, //no rudder
  false,  //throttle AXIS IS DISABLED
  false, //no accelerator
  false, //no brake
  false //no steering
  );

const bool initAutoSendState = true;//not really necessary. used by the joystick library

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Joystick.setXAxisRange(minValue,maxValue);
  Joystick.setYAxisRange(minValue,maxValue);

  //supply a HIGH voltage to Vin of the rotary encoder
  pinMode(highPin,OUTPUT);
  digitalWrite(highPin,HIGH);
  
  pinMode(pinA,INPUT);
  pinMode(pinB,INPUT);
  pinMode(clickPin,INPUT);
  
  potMinimum = 500;
  potMaximum= 500;
  Joystick.begin();

  // turn on LED to signal the start of the calibration period:
  //pinMode(17, OUTPUT);
  //digitalWrite(17, HIGH);
  
  // calibrate during the first five seconds
  while (millis() < 5000) {
    sensorValue = analogRead(potSensorPin);
    // record the maximum sensor value
    if (sensorValue > potMaximum) {
      potMaximum = sensorValue;
    }

    // record the minimum sensor value
    if (sensorValue < potMinimum) {
      potMinimum = sensorValue;
    }
  }

  // signal the end of the calibration period
  //digitalWrite(13, LOW);
  Serial.println("Calibration Done");
  Serial.println(potMaximum);
  Serial.println(potMinimum);
}

void loop(){
  //this section reads the position of the rotary encoder
  //and translates it to a joystick axis for the PC
  newPos = trimWheel.read();
  int diff = (newPos - oldPos);
  if (abs(diff) > 0){
    output_ += (diff*scaleFactor);
    output_=constrain(output_,minValue,maxValue);
    oldPos = newPos;
    //Serial.println(output_);
    Joystick.setXAxis(output_); 
  }
  if (!digitalRead(clickPin)){
    //placeholder. Do something if the click button on the 
    //rotary encoder is pressed.
  }
  
  //read the potentiometer to set the axis position on the joystick
  sensorValue = analogRead(potSensorPin);
  Serial.println(sensorValue);

  //user an EMA algorithm to smooth the potentiometer values
  EMA_S = (EMA_a * sensorValue) + ((1-EMA_a)*EMA_S);
  if (abs(oldEMA_S - EMA_S)> 0){
    oldEMA_S = EMA_S;

  }

  //Serial.println("Sensor Value:");
  //Serial.println(sensorValue);
  //Serial.println("min");
  //Serial.println(potMinimum);
  //Serial.println("Max");
  //Serial.println(potMaximum);
  //Serial.println("EMA_S");
  //Serial.println(EMA_S);
  Joystick.setYAxis(map(EMA_S,potMinimum,potMaximum,minValue,maxValue));
  //Serial.println(map(EMA_S,potMinimum,potMaximum,minValue,maxValue));
  //Serial.println("===========================");
}

Hi,
Can you please post and try a simplified code that JUST reads and maps your value, output the rawanalog and the mapped values to IDE serial monitor.
So we can see where the problem may be.

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

I'll do that. Give me a minute. :slight_smile:

Here's some simplified code with the output


int potSensorPin = A2;
int oldSensorValue = 0;
int newSensorValue = 0;

int potMaximum = 500;
int potMinimum = 500;



void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  int sensorValue;
  while (millis() < 8000) {
    sensorValue = analogRead(potSensorPin);
    if (millis()%100 == 0){
      Serial.println (millis());
      Serial.println(sensorValue);
    }
    // record the maximum sensor value
    if (sensorValue > potMaximum) {
      potMaximum = sensorValue;
    }

    // record the minimum sensor value
    if (sensorValue < potMinimum) {
      potMinimum = sensorValue;
    }
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  newSensorValue = analogRead(potSensorPin);
  if (abs(newSensorValue - oldSensorValue)>5 ){
    Serial.print("pot Max: " );
    Serial.println(potMaximum);

    Serial.print("pot Min: ");
    Serial.println(potMinimum);

    Serial.print("Current sensor Value: " );
    Serial.println(newSensorValue);
    Serial.println("================");
    oldSensorValue = newSensorValue;
  }
}

Output:

pot Max: 607
pot Min: 238
Current sensor Value: 615
================
pot Max: 607
pot Min: 238
Current sensor Value: 670
================
pot Max: 607
pot Min: 238
Current sensor Value: 617
================
pot Max: 607
pot Min: 238
Current sensor Value: 671
================
pot Max: 607
pot Min: 238
Current sensor Value: 654
================
pot Max: 607
pot Min: 238
Current sensor Value: 671
================
pot Max: 607
pot Min: 238
Current sensor Value: 609
================
pot Max: 607
pot Min: 238
Current sensor Value: 675
================
pot Max: 607
pot Min: 238
Current sensor Value: 668
================
pot Max: 607
pot Min: 238
Current sensor Value: 616
================
pot Max: 607
pot Min: 238
Current sensor Value: 668
================
pot Max: 607
pot Min: 238
Current sensor Value: 608
================
pot Max: 607
pot Min: 238
Current sensor Value: 669
================
pot Max: 607
pot Min: 238
Current sensor Value: 610
================
pot Max: 607
pot Min: 238
Current sensor Value: 669
================
pot Max: 607
pot Min: 238
Current sensor Value: 615
================
pot Max: 607
pot Min: 238
Current sensor Value: 609
================
pot Max: 607
pot Min: 238
Current sensor Value: 603

There are many sensor values that are greater than the pot Max value somehow!
Do I have a bad potentiometer?

Get a pot that is made by a reputable manufacturer, such as Allan-Braldley could be marked "AB". Don't use a cheap hobby pot. Another choice would be a wire-wound pot. It will be much more stable.

I guess that you catch ambient noise. A scope could reveal the nature of your distorted values. Or your mechanical construction does not fix the end points.

Remember, with a joystick, YOU are part of a feedback system, so you will not be aware of resistance errors.

This is for the propeller pitch lever of a throttle quadrant. When the lever is adjusted to max position, it should output the maximum signal. However, with the error i mentioned above, even when the lever is at max, the output is not. It stops at around 85%.

Have you actually opened the joystick to be sure there is ONLY a pot?

Hi,
Can you please post an image(s) of your project so we can see your component layout?

A circuit diagram would also help.
How are you powering your project?

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

Here are the pics. :slight_smile:
Just a potentiometer and a rotary encoder connected directly to am arduino pro micro