pid controlled system with linear actuator small issue newbie needs help

so this is my first arduino set up and control system

i was able to find and upload a sample code that does pretty much exactly what i need to do

the problem i run into is when i turn the control potentiometer one way the actuator moves smoothly but turn the knob the opposite way it jumps in small intervals

i looked over the code and i am kind of at a loss if someone can lend a hand with it i would appreciate it thank you

attached below is the original sample code i uploaded

/* Sample code to control the position of an actuator with potentiometer feedback using a MegaMoto.

The main loop of this program checks the potentiometer, and moves the actuator accordingly.

Written by Progressive Automations

This example code is in the public domain.
*/

const int feedback = A0; //potentiometer from actuator
const int pot = A1; //pot from throttle

const int enable = 8;
const int PWMA = 11;
const int PWMB = 3;

int actMax = 760;
int actMin = 250;//positions of actuator

int potMin = 0;
int potMax = 1023;

int precision = 2;//how close to final value to get
int checkingInterval = 50;//how often position is checked (milliseconds)

int rawcurrentPosition = 0;
int currentPosition = 0;
int rawdestination = 0;
int destination = 0;
int difference = 0;//values for knowing location

void setup()
{
pinMode(feedback, INPUT);//feedback from actuator
pinMode(pot, INPUT);//feedback from potentiometer
pinMode(enable, OUTPUT);
pinMode(PWMA, OUTPUT);
pinMode(PWMB, OUTPUT);//three pins for MegaMoto
digitalWrite(enable,HIGH);
Serial.begin(9600);
}

void loop()
{
destination = getDestination();
currentPosition = analogRead(feedback);//check where you are
Serial.print("Position ");
Serial.println(analogRead(feedback));
difference = destination - currentPosition;//find out how far you are from the destination
if (currentPosition > destination) pullActuatorUntilStop(destination);// choose what action to take
else if (currentPosition < destination) pushActuatorUntilStop(destination);
else if (difference < precision && difference > -precision) stopActuator();
}//end void loop

int getDestination()
{
rawdestination = analogRead(pot);//read the potentiometer to get the destination
destination = map(rawdestination, potMin,potMax,actMin,actMax);//convert the potentiometer feedback to match the actuator
return(destination);
}//end getDestination

void pushActuatorUntilStop(int destination)
{
destination = getDestination();
int temp = analogRead(feedback);
difference = destination - temp;//check difference to see if continue moving, or stop

while (difference > precision || difference < -precision)
{
destination = getDestination();
temp = analogRead(feedback); //continue checking difference
difference = destination - temp;
pushActuator();
}//end while

delay(25);
stopActuator();
}//end pushActuatorUntilStop

void pullActuatorUntilStop(int destination)
{
destination = getDestination();
int temp = analogRead(feedback); //check difference to see if continue moving, or stop
difference = destination - temp;

while (difference > precision || difference < -precision)
{
destination = getDestination();
temp = analogRead(feedback); //continue checking difference
difference = destination - temp;
pullActuator();
}//end while

delay(25);
stopActuator();
}//end pullActuatorUntilStop

void stopActuator()
{
analogWrite(PWMA,0);
analogWrite(PWMB,0);
}//end stopActuator

void pushActuator()
{
analogWrite(PWMB,255);
analogWrite(PWMA,0);
}//end pushActuator

void pullActuator()
{
analogWrite(PWMB,0);
analogWrite(PWMA,255);
}//end pullActuator

Please use code tags when posting code ( "</>" button).

That code does not use a PID algorithm, in fact it is pure crap. You are really wasting your time even trying to figure out what it does.

Start by studying one of the many tutorials describing how PID works, and write your own. It is pretty simple and you can certainly produce something better than the junk you downloaded, given a bit of understanding (which "Progressive Automations" obviously lacks). Google "arduino pid tutorial".

Or, use the Arduino PID library.

Hello, there.

The implementation of a PID is really simple, the difficult part if you do not know control theory is tuning the gain parameters of your control law.

Here is an example I made for you:

// These parameters have to be tuned to fit your needs!
// Use an experimental method like Ziegler-Nichols tuning,
// it is the easiest if you lack experience.
double Kp = 1;
double Ki = 0;
double Kd = 0;

double prevError = 0;
double sumError = 0;

uint32_t prevTime;

double destination = 0;
double currentPosition = 0;

double computePID (double reference, double current, double dt) {
  // Compute position error
  double error = reference - current;

  // Compute sum of errors (used by integrator part)
  sumError = sumError + error*dt;

  // Compute difference of error (used by derivative part)
  double difference = (error - prevError)/dt;
  prevError = error;

  return Kp*error + Ki*sumError + Kd*difference;
}

void applySpeed (double controlSignal) {
  int direction = controlSignal/fabs(controlSignal);
  controlSignal = min(255,max(0,fabs(controlSignal)));
  
  // Apply the speed to your motors here, use direction variable to determine
  // the direction to set (-1 or 1).
}

void setup () {
  prevTime = micros();
}

void loop () {
  double dt = (double)(micros()-prevTime)/1000000;
  prevTime = micros();

  // Get current position here from feedback

  double controlSignal = computePID(destination, currentPosition, dt);
  applySpeed(controlSignal);

  // Use timer interrupts instead, this is just to show that
  // you need to specify a constant sampling interval.
  delay(1);
}

I wrote this from my head so I cannot guarantee it is fault-free, but you can give it a try. I use double variables because it is better for convergence.

I am a Master student in Robotics and Control, if you have any questions, I am happy to answer via PM.

I use double variables because it is better for convergence.

Helpful post, but did you know that "double" is the same as "float" (32 bits) on the standard Arduino?

jremington:
Helpful post, but did you know that "double" is the same as "float" (32 bits) on the standard Arduino?

Yes, though I usually use 32-bit MPUs (with FPUs) when working with control systems, so double is usually more precise than float in that sense. But for the standard Arduino, it doesn't matter.