Servo Motor PID Parameters Problem

Status
Not open for further replies.

FMradio

Member level 3
Joined
Nov 24, 2009
Messages
58
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Location
Heaven
Activity points
1,672
Hey guys!
I am working on a servo motor drive so far its working great but now I am facing a problem related to PID parameter values
Servo loop time = 5ms
Encoder PPR = 1000
Motor RPM (max) = 4200
Kp = 5, Ki = 1, Kd = 3 (signed int16)
Motor (signed int16)

Here is my Servo Controlling Algorithm
Servo loop:
Error = reference position – encoder position
If(Error > 1023) Error = 1023
Else if(Error <-1023) Error = 1023
Motor = PID (Error);
If(Motor > 1023) Motor = 1023
Else if(Motor <-1023) Motor = 1023
Goto Servo loop;

Now my Problem is that I can’t increase the range of my PID parameters values, I have seen in a Ready Made Servo drive it takes in the PID values up to 16bits more flexible better for precise tuning & It can take a small servo loop time up to 125u seconds , here in my case lets assume
Error = 1023; (maxium)
in PID
P = Error x Kp; // 1023 x 5 = 5115
I = summation f(Error) x Ki; // it will grow with time “Servo loop time”
D = difference of Errors x Kd
Motor = P + I + D // it will saturated

Here if I reduce my servo loop time then the integrator will sum up the error more quickly right and I can’t go below Ki=1 (minimum), & if I make Ki > 1 Motor starts oscillating. “Stuck”
& if I increase Kp then P=32 will exceed 32000 again it will saturated (signed int16)
Similarly with Kd,
I am not using any floating variables in order to minimize the computation cost,

now whats the solution??
 

If(Error > 1023) Error = 1023
Else if(Error <-1023) Error = 1023
I am not sure what do you want to do with this. Error is all the time equal to 1023 (the same position or what)?

Regards
 

I am not sure what do you want to do with this. Error is all the time equal to 1023 (the same position or what)?

Regards

its a Saturation bound on Error so that the error remains in between -1023 to 1023
 

Yes, but shouldn't it be

If(Error > 1023) Error = 1023
Else if(Error <-1023) Error = -1023

????
 

I think, you should use float variables to avoid saturation, so Kp, Ki and Kd could be less then 1 and more precisselly at the same time.

Regards
 

Yes, but shouldn't it be

If(Error > 1023) Error = 1023
Else if(Error <-1023) Error = -1023

????

its not the actual code just a text

If(Error > 1023) then set Error = 1023
Else if(Error <-1023) then set Error = -1023

but its not my Problem sir

---------- Post added at 12:17 ---------- Previous post was at 12:14 ----------

I think, you should use float variables to avoid saturation, so Kp, Ki and Kd could be less then 1 and more precisselly at the same time.

Regards

yes u r right but if i use Floating values the computation cost will increase & some times it disable the interrupts as floating variable is 32 bits
 

Can you describe what type of microcontroller is used in your aplication?

Regards
 

Make your error value a long (32-bit) variable.
Then scale the result to suit the control response.
 

Can you describe what type of microcontroller is used in your aplication?

Regards

am using PIC18F

---------- Post added at 14:27 ---------- Previous post was at 14:21 ----------

Make your error value a long (32-bit) variable.
Then scale the result to suit the control response.

sir can u plzz show me how to scale the error ??

for eg
Error type is 32-bit integer
Error = 47
if i divide my error by 2
i get Error = 24 instead of 23.5

now again its a problem ?? 0.5 lost
 

It will not be lost. It will be summed in the Ki value.

Code:
/*--- Pi structure ---*/

typedef struct 
  {
  int16_t Gain[2];    /* Pi gain values - Kp and Ki */
  int16_t History[2]; /* Delay-line samples */
  int16_t Output;     /* Pi Controller Output  */
  int16_t Target;     /* Target speed */
  int16_t Measured;   /* Measured speed */
  }PI;
 
PI Pi_sync; 


/*--- Error limits ---*/

#define MAX_ERROR   +250
#define MIN_ERROR   -250
#define OUTPUTSCALE 50

/*--- Pi Gains ---*/

#define Kp  3
#define Ki  1
        
/*--- Initialise Pi ---*/

void PiInit(PI *Pi)
  {
  Pi->Gain[0] = Kp;  /* Proportional gain Kp */                 
  Pi->Gain[1] = Ki;  /* Integral gain Ki */           

  Pi->History[0] = 0;
  Pi->History[1] = 0;        
  Pi->Output = 0;
  }
  
/*--- Calculate Pi ---*/

int16_t PiCalc(PI *Pi)  
  {
  int32_t error, scaled_error;
  
  Pi->History[0] = Pi->Measured - Pi->Target;  
    
  error = (int32_t)(Pi->History[0] * Pi->Gain[0]);    
  error += (int32_t)(Pi->History[1] * Pi->Gain[1]);
  
  Pi->History[1] += Pi->History[0];
        
  if(Pi->History[1] > MAX_ERROR){
    Pi->History[1] = MAX_ERROR;
    }
  else if(Pi->History[1] < MIN_ERROR){
    Pi->History[1] = MIN_ERROR;
    }
    
  scaled_error = error / OUTPUTSCALE;       
  Pi->Output = (int16_t)scaled_error; 

  return Pi->Output;
  }     
    
/*--- End of file ---*/
 
Last edited:
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…