Potentiometer mapping with PID controller

image

I'm working on this ball and beam project and I'm trying to match the dial potentiometer with the softpot in the beam in terms of inches. I would like it so that the ball stays on the right side from the center, but the strip is 20 inches long. That's what was supplied. My code works with the PID controller in it, just need help to map both potentiometers to the correct numbers. Here is my code:

#include <Servo.h>  // Arduino Servo Library
#include <PID_v2.h>

// Servo, potentiometers setup
const int SetpointPotPin = A3; // User Input
const int FeedbackPotPin = A4; // Pin connected to softpot wiper
const int ServoPin = 9;

double Input, Output, Setpoint;
float Kp = 0.75;     // Initial Proportional Gain
float Ki = 0;     // Initial Integral Gain
float Kd = 0.25;     // Initial Derivative gain



PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
// Note: Use REVERSE instead of DIRECT when higher Output 
// tilts the ball toward lower SoftPot values

Servo myServo;

void setup()
{
  Serial.begin(115200);
  myServo.attach(ServoPin);

  myPID.SetMode(AUTOMATIC);      // Start the control loop
  myPID.SetOutputLimits(1000, 2000); // Output drives 'servo.writeMicroseconds)'
}


void loop()
{  
  // Where do we want the ball to settle
  Setpoint = analogRead(SetpointPotPin);

  // Where is the ball right now
  Input = analogRead(FeedbackPotPin);

  myPID.Compute();

  myServo.writeMicroseconds(Output);
}

Well documented and posted question!
What does it do and what do You want to happen? I don't pick up what the "failure" looks like.

So what's it's supposed to do is whatever number the dial potentiometer is set to, that's the inch mark that the beam is supposed to self balance the ball using the softpot. My code has that working, I just need to scale the values so that the softpot knows where 0 inch to 12 inch is, samething with the dial potentiometer.

Serial print here and there.

image

I'm working on this ball and beam project and I'm trying to match the dial potentiometer with the softpot in the beam in terms of inches. I would like it so that the ball stays on the right side from the center, but the strip is 20 inches long. That's what was supplied. My code works with the PID controller in it, just need help to map both potentiometers to the correct numbers. It works without the map functions in the loop, but once they're added the servo doesn't move the beam with the position but the mapping in the serial monitor is correct. Need help with fixing this. Here is my code:

#include <Servo.h>  // Arduino Servo Library
#include <PID_v2.h>

// Servo, potentiometers setup
const int SetpointPotPin = A3; // User Input
const int FeedbackPotPin = A4; // Pin connected to softpot wiper
const int ServoPin = 9;

double DialPot, SoftPot;
double Input, Output, Setpoint;
float Kp = 0.75;     // Initial Proportional Gain
float Ki = 0;     // Initial Integral Gain
float Kd = 0.25;     // Initial Derivative gain



PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
// Note: Use REVERSE instead of DIRECT when higher Output 
// tilts the ball toward lower SoftPot values

Servo myServo;

void setup()
{
  Serial.begin(9600);
  myServo.attach(ServoPin);

  myPID.SetMode(AUTOMATIC);      // Start the control loop
  myPID.SetOutputLimits(1000, 2000); // Output drives 'servo.writeMicroseconds)'
}


void loop()
{  
  // Where do we want the ball to settle
  DialPot = analogRead(SetpointPotPin);
  DialPot = map(DialPot, 0, 1023, 8, 20);
  Setpoint = DialPot;

  // Where is the ball right now
  SoftPot = analogRead(FeedbackPotPin);
  SoftPot = map(SoftPot, 0, 1023, 0, 20);
  Input = SoftPot;
  
  myPID.Compute();

  myServo.writeMicroseconds(Output);

  Serial.print("Knob Val: ");
  Serial.println(DialPot);
  Serial.print("Strip Pot Val: ");
  Serial.println(SoftPot);
}

You need to supply more information. What detects the position of the ball, and how? What would be the "correct numbers"? What have you done to verify the scaling in the map() function?

Put in print statements to see the PID input and output values and verify that they make sense. It should be easy to understand why the servo doesn't move.

Threads merged. Please do not cross-post.

Note: The map() function works in integers so there are only 21 positions between 0 and 20 while there are 1024 positions of the pot. I recommend you use positions in hundredths of an inch:
SoftPot = map(SoftPot, 0, 1023, 0, 2000);

Is your mapping correct? If you put the ball at inch marker 0 do you get 0 for Input? If you put the ball at inch marker 20 to you get 2000?

You must use the same units for Setpoint as for Input. Whenyou change the Input to hundredths you must also change the Setpoint to the same scale.

Note: If you want to display in inches, just use Setpoint/100.0 and Input/100.0.

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