Driving a linear actuator with pid

Hi

im still new at this, im trying to use a arduino pid controller to drive a linear actuator to a setpoint adjustet with a potentionmeter.

im using a H-bridge to drive the linear actuator.

i know my code is a mess, i have tryed to copy others code.

#include <PID_v1.h>

//Define Variables we'll be connecting to
double Setpoint, Input, Output;

//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);
//----------------------------------------------------------

int setting = 5;

// constants won't change. They're used here to set pin numbers:

const int relay1Pin =  4;      // the number of the Realy1 pin
const int relay2Pin =  5;      // the number of the Relay2 pin
//const int sensorPin = 1;    // select the input pin for the potentiometer
const int potPin = 0;       // slider potmeter 
const int pwm = 3;        // pwm signal

// variables will change:

int sensorValue = 0;  // variable to store the value coming from the sensor in the liniar actuar

int goalPosition; 
int CurrentPosition = 0; 
int sensorOutput = 0;
boolean Extending = false;
boolean Retracting = false;

// SMOOTING -------------------------------------------------------

const int numReadings = 5;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average

int inputPin = A1;


//---------------------------------------------------------------
void setup() { 

//initialize the variables we're linked to
  

  //turn the PID on
  myPID.SetMode(AUTOMATIC);
  //-------------------------------------------------------------


for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;

    
  //start serial connection
  Serial.begin(9600);

  
    
  // initialize the relay pin as an output:
  pinMode(relay1Pin, OUTPUT);    
  pinMode(relay2Pin, OUTPUT);
  pinMode(pwm, OUTPUT);    //pwm
  
  //preset the relays to LOW
  digitalWrite(relay1Pin, LOW); 
  digitalWrite(relay2Pin, LOW); 

  
}
}
void loop(){
  





    

//----------------------------------------------------------
  // subtract the last reading:
  total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = analogRead(inputPin);
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }

  // calculate the average:
  average = total / numReadings;
  // send it to the computer as ASCII digits

  //----------------------------------------------------------------------
 

CurrentPosition = average;


  int goalPosition = analogRead(potPin);
 
  goalPosition = map(goalPosition, 0, 1023, 280, 720);            // to get the same range as the potmeter from the liniar actuator

  
//-----------------------------------------------------

  Setpoint = goalPosition;
  //Serial.print("goalPosition = " );                       
  //Serial.println(Setpoint);
  
  Input = average;
  //Input = analogRead(1);
  Input = map(Input, 280, 720, 0, 255);

  myPID.Compute();
  analogWrite(pwm,Output);
  //analogWrite(pwm,55);

  //---------------------------------------------

  
   //print the results to the serial monitor:
  /*
  Serial.println ("Current = " );                       
  Serial.println(CurrentPosition);      
  Serial.println ("\t Goal = ");      
  Serial.println(goalPosition);  
  */
  
 
  
if (goalPosition > CurrentPosition + setting) {
        Retracting = false;
        Extending = true;
        digitalWrite(relay1Pin, HIGH);  
        digitalWrite(relay2Pin, LOW);  
        //Serial.println("Extending");     
    }      
    else if (goalPosition < CurrentPosition - setting) {
        Retracting = true;
        Extending = false;
        digitalWrite(relay1Pin, LOW);  
        digitalWrite(relay2Pin, HIGH); 
        //Serial.println("Retracting");         
    }



  if (Extending = true && CurrentPosition > goalPosition) {
    //we have reached our goal, shut the relay off
    digitalWrite(relay1Pin, LOW); 
    boolean Extending = false; 
    //Serial.println("IDLE");  
  }
  
  if (Retracting = true && CurrentPosition < goalPosition){
    //we have reached our goal, shut the relay off
    digitalWrite(relay2Pin, LOW); 
    boolean Retracting = false; 
    //Serial.println("IDLE");  
  }
  //delay(70);
    }

Do you have a question?

brunokc: i know my code is a mess, i have tryed to copy others code.

One way to make your sketch less messy: Tools->Auto Format Warning: '=' is the assignment operator. To compare two numbers for equality, use '=='.

Setting the serial speed just once is usually sufficiently. Ditto for pinModes.

gfvalvo: Do you have a question?

hehe yes, i cant get it to worke, the pwm is 255 all the time. i cant get the pid to worke.

AWOL: Setting the serial speed just once is usually sufficiently. Ditto for pinModes.

do i do that?

Start with the P set to 1, the I set to 0 and the D set to 0. I suspect the I or the D parameter is slamming Output against its limit.

You have a bunch of code that ignores the Output and tries to guess what direction the actuator should be driven and when it should stop. You should probably just set the limits on Output to +/-255 (default is 0-255) and use that sign for direction and the magnitude for PWM. When the PID loop wants the motor to stop, it will set Output to 0.

can i set the pwm signal to the H-bridge to -255 and it will run back?

brunokc: do i do that?

No, you do those things five times.

It's not necessary.

I believe it’s line #55

for (int thisReading = 0; thisReading < numReadings; thisReading++) {
readings[thisReading] = 0;

this should not be in setup. Setup is for 1 time setting of variables and conditions. This “for” statement therefore will only execute once and never increment “thisReading” beyond 1.

Ken_F:
I believe it’s line #55

for (int thisReading = 0; thisReading < numReadings; thisReading++) {
readings[thisReading] = 0;

this should not be in setup. Setup is for 1 time setting of variables and conditions. This “for” statement therefore will only execute once and never increment “thisReading” beyond 1.

that code isn’t at all necessary anywhere - the array is already zero.
(And I don’t see a problem with the for loop per se - it just includes too many other things)

brunokc:
can i set the pwm signal to the H-bridge to -255 and it will run back?

No, but you can:

if (int(Output + 0.5) == 0)
{
  digitalWrite(pwm, LOW);
}
else if (Output < 0)
{
   analogWrite(pwm, -(Output +0.5);
   SetDirectionBackward();
}
else
{
  analogWrite(pwm, Output+0.5);
  SetDirectionForward();
}

I add 0.5 so that when the ‘double’ value gets changed to an ‘int’ it gets rounded instead of truncated.