Teach you to understand and understand the Arduino PID control library - initialization

Introduction

This article will analyze the problem of initialization in " Teach you to understand and understand the Arduino PID control library "

problem definition

First look at the diagram of the problem:

In the previous section, we discussed the problems in the process of PID control switching from on to off. Then, immediately after the previous section, if it is suddenly turned on again after being turned off, what problems will occur? Intuitively, for the controlled quantity, there will be a bump in the green line in the figure. This bump is due to the sudden amplification of the output at the moment when it is turned from off to on. Then, for a system with high sensitivity, it will appear in a system with a large lag. It may not be so obvious, but in any case, in order to eliminate all negative factors, we should find a way to eliminate this bump. Since the root cause of the bump is caused by the mutation of the output, it is necessary to find a way to control the mutation of the output.

solution

Think about it, all such problems occur on the time axis, then the only items that the time axis will affect in PID control are the integral term and the derivative term (it is conceivable that the proportional direction is Kp * (set value - controlled quantity) ), this is a continuous quantity, and there is no possibility of mutation (unless the sampling time is very long, before changing the output, the controlled quantity will fly into the sky), so we only need to think of ways to control these two items. The sudden change of PID can control the sudden change of the output. First of all, the problem occurs in the process of turning PID off and on. Since the function of PID on and off control is SetMode, in this function, an initial function is added to control the integral term and differential The specific method is as follows:

1. Update the last sampling value of the differential term to the sampling value at the moment when the PID is turned on, so that the differential term can be kept unchanged at the end of the last turning on.

2. Set the integral term as the current output. Why do you want to do this? Because the integral term is closed for a long time, the PID remains in the state before it is closed. Once it is turned on, if the integral term is not changed, the output will be instantly pulled back to the state where the last turn-on ended, and a sudden change occurs.

code

/*working variables*/
unsigned long lastTime;
double Input, Output, Setpoint;
double ITerm, lastInput;
double kp, ki, kd;
int SampleTime = 1000; //1 sec
double outMin, outMax;
bool inAuto = false;
 
#define MANUAL 0
#define AUTOMATIC 1
 
void Compute()
{
   if(!inAuto) return;
   unsigned long now = millis();
   int timeChange = (now - lastTime);
   if(timeChange>=SampleTime)
   {
      /*Compute all the working error variables*/
      double error = Setpoint - Input;
      ITerm+= (ki * error);
      if(ITerm> outMax) ITerm= outMax;
      else if(ITerm< outMin) ITerm= outMin;
      double dInput = (Input - lastInput);
 
      /*Compute PID Output*/
      Output = kp * error + ITerm- kd * dInput;
      if(Output> outMax) Output = outMax;
      else if(Output < outMin) Output = outMin;
 
      /*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;
      ki *= ratio;
      kd /= ratio;
      SampleTime = (unsigned long)NewSampleTime;
   }
}
 
void SetOutputLimits(double Min, double Max)
{
   if(Min > Max) return;
   outMin = Min;
   outMax = Max;
    
   if(Output > outMax) Output = outMax;
   else if(Output < outMin) Output = outMin;
 
   if(ITerm> outMax) ITerm= outMax;
   else if(ITerm< outMin) ITerm= outMin;
}
 
void SetMode(int Mode)
{
    bool newAuto = (Mode == AUTOMATIC);
    if(newAuto && !inAuto)
    {  /*we just went from manual to auto*/
        Initialize();
    }
    inAuto = newAuto;
}
 
void Initialize()
{
   lastInput = Input;
   ITerm = Output;
   if(ITerm> outMax) ITerm= outMax;
   else if(ITerm< outMin) ITerm= outMin;
}

in conclusion

Pictures say it all. . . . .

NOTE: Please let us know if there are any inadequacies. ^.^

The next chapter will introduce the influence of the control direction on the system if the system is running.

NEXT

PS: Please indicate the source for reprinting: Ouyang Tianhua

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325548753&siteId=291194637