本文将分析《手把手教你看懂并理解Arduino PID控制库》中:初始化的问题函数
先看问题的图示:ui
上一节,讨论的是PID控制由开转关的过程当中存在的问题,那么紧接着上一节,若是在关闭后,忽然再次开启,那么会产生什么问题呢?直观来看,对于被控量会出现图中,绿色线的一个bump,这个bump是因为由关转开的一瞬间,输出忽然放大,那么对于灵敏度高的系统,则会出现,滞后大的系统可能不会如此明显,但无论怎么说,为了杜绝一切不利因素,咱们都应该想办法消除这个bump。因为这个bump的根因是因为输出的突变而形成的,因此须要想办法控制这个输出的突变。spa
想想,全部此类问题都是发生在时间轴上的,那么PID控制中时间轴会影响的项只有积分项和微分项(能够想象,比例向为Kp * (设定值 - 被控量),这是一个连续量,不存在突变的可能(除非是采样时间特别长,在改变输出前,被控量飞上天了),因此只须要从这两项上想办法,控制住这两项的突变,便可控制住输出的突变。首先问题发生在PID关闭转开启的过程当中,因为PID开启关闭控制的函数是SetMode,因此在此函数中,增长一个initial函数用于控制积分项和微分项便可。具体作法是:.net
一、更新微分项上一次采样值为PID开启一瞬间的采样值,这样能够保持微分项维持在上一次开启结束的状态不变。code
二、将积分项设置为当前的输出,为何要这么作呢?积分项因为PID关闭长时间维持关闭前的状态,一旦开启,若是不改变积分项,输出会瞬间被拉回到上一次开启结束的状态,突变就这样产生了blog
/*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; }
图片说明一切。。。。。图片
NOTE:若有不足之处请告知。^.^get
下一章将介绍若是在系统运行过程当中,控制方向对系统的影响it
NEXTio
PS:转载请注明出处:欧阳天华