Beginner PID Advanced

 

existing problems

The purpose of this adjustment is to eliminate a phenomenon known as "Derivative Kick".



 

The picture above reflects this problem. Since error=Setpoint-Input, any change in Setpoint will cause error to change instantaneously. The derivative of this change is infinite (actually, since dt is not 0, it just computes to a very large number). This number is fed into the pid equation, which outputs an undesired peak. Fortunately there is an easy way to get rid of this.

solution



 
The derivative error is equal to the negative derivative of the input, except when the Setpoint  is changed. This is not a perfect solution, instead of adding (Kd *derivative of error), we subtract (Kd *derivative of input). This is called using a "derivative measure".
 

The Code

/*working variables*/
unsigned long lastTime;
double Input, Output, Setpoint;
double errSum, lastInput;
double kp, ki, kd;
int SampleTime = 1000; //1 sec
void Compute()
{
   unsigned long now = millis();
   int timeChange = (now - lastTime);
   if(timeChange>=SampleTime)
   {
      /*Compute all the working error variables*/
      double error = Setpoint - Input;
      errSum += error;
      double dInput = (Input - lastInput);
 
      /*Technical PID output, Compute PID Output*/
      Output = kp * error + ki * errSum - kd * dInput;
 
      /*Remember some variables for next time*/
      lastInput = Input;
      lastTime = now;
   }
}
 
void SetTunings(double Kp, double Ki, double Kd)
{
  double SampleTimeInSec = ((double)SampleTime)/1000;
   kp = Kp;
   ki = Ki * SampleTimeInSec;
   kd = Kd / SampleTimeInSec;
}
 
void SetSampleTime(int NewSampleTime)
{
   if (NewSampleTime > 0)
   {
      double ratio  = (double)NewSampleTime
                      / (double)SampleTime;
      to *= ratio;
      kd /= ratio;
      SampleTime = (unsigned long)NewSampleTime;
   }
}
 

Modifications here are very easy. We replace the error derivative and the input derivative. Remember the last input not the last error.

The Result



 

Here is the modified result, notice that the input still looks the same. So we get the same performance, but without outputting huge spikes every time the Setpoint  changes.

This may or may not be a big problem. It depends on how sensitive your program is to output peaks.

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327040218&siteId=291194637