PID入门提高翻译教程【一】-Arduino中文社区 – Powered by Discuz!

Igor Arduino评论42,132字数 2876阅读9分35秒阅读模式
        几十年来,PID控制器已被证明是一个非常有用的工具,在工业自动化领域。其应用范围涵盖机械,化工,食品等行业,采矿业,汽车和航空航天业和许多其他地方等。由于它的简单,它允许手动调协,成功地处理甚至很多非线性部分未知的过程,它成为一个标准的工具,它通常被看作是通用实现反馈控制的实际目标。

PID控制包含有比例(P),积分(I),微分(D)三种控制规律。它们都是线性控制器,其作用是按偏差的比例,或比例加积分,或比例加积分和微分形成控制量,去控制被控对象,使被控对象输出趋于稳定。这里的偏差就是系统的给定值:Setpoint,与被控对象的实际输出就是控制器的输入值:Input之差;error = Setpoint - Input。

原文地址传送:http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/希望通过对本文的翻译,帮助大家更加好的理解和认识PID控制。

对于学习PID,我们第一次会接触到以下公式:

上面公式为离散化的位置式PID,因为实际中很多都是模拟量,而计算机只能处理数字量,只能将连续的离散化。位置式的PID是指控制器输出直接去控制执行机构(如阀门)和执行机构(阀门开度一一对应)。

上面公式为离散化的位置式PID,因为实际中很多都是模拟量,而计算机只能处理数字量,只能将连续的离散化。位置式的PID是指控制器输出直接去控制执行机构(如阀门)和执行机构(阀门开度一一对应)。

根据以上公式写出下面的PID程序:

kittenblock中小学创客名师推荐的图形化编程软件

/*定义变量*/

unsigned long lastTime;

double Input, Output, Setpoint;

double errSum, lastErr; doublekp, ki, kd;

void Compute() {

/*上次计算时间*/

unsigned long now = millis();

double timeChange = (double)(now - lastTime);

/*按公式写出如下的式子*/

double error = Setpoint - Input;

errSum += (error * timeChange);

double dErr = (error - lastErr) / timeChange;

/*计算 PID的输出*/

Output = kp * error + ki * errSum + kd * dErr;

/*记录下一个采样时间PID参数的值*/

lastErr = error;

lastTime = now;

}

void SetTunings(doubleKp,doubleKi,doubleKd) {

kp = Kp;    ki = Ki;    kd = Kd;

}

Compute()函数会被定时或不定时的调用,他能工作的很好。虽然这个系列并没有做到很好,如果我们想通过上的代码设计出工业级别PID驱动器,我们最好解决一下问题:

Sample Time(采样时间):如果PID能有规律的被调用,那么PID将实现很好的控制,同时我们也能简化一些内部的数学计算。

Derivative Kick(微分失控):问题不大,也很好解决,我们会在后面解决这个问题。

On-The-Fly Tuning Changes(快速调整参数变化):好的PID算法在改变参数的时候,并不会影响内部的工作。

Reset Windup Mitigation(缓解积分饱和):了解什么是积分饱和,并且在有利的方面进行方案实施。

On/Off (Auto/Manual)(开关-自动或手动):在很多应用里,我们有时候需要关闭PID控制器,然后通过手动调节输出,避免控制器的干扰。

Initialization(初始化):

Controller Direction(控制器的方向):最后一个章节会有详细介绍。

注:所有的程序中都是采用double双精度,在arduino中,双精度是采用float精度处理的。所以,我建议改变所有double变成float。

采样时间:

PID如果不规则的调用,会产生以下2个问题:

1.有时候定时调用,有时候又停止调用,将得不到PID的持续稳定特性。

2.需要额外对积分和微分进行数学计算,因为他们都是和时间息息相关的。

解决方法:保证PID在一个固定的的时间间隔内被调用,我通过每个周期内事先设置好的采样时间调用compute函数,PID再决定是计算还是立即返回数值。一旦我们知道PID在固定时间间隔内被调用,积分和微分的计算就能被简化。

程序:

 

kittenblock中小学创客名师推荐的图形化编程软件

unsigned long lastTime; doubleInput, Output, Setpoint; doubleerrSum, lastErr; doublekp, ki, kd; int SampleTime =1000; //1sec void Compute() {    unsigned long now = millis();    int timeChange = (now - lastTime);//第10行    if(timeChange>=SampleTime)    {           doubleerror = Setpoint - Input;       errSum += error;       doubledErr = (error - lastErr);       Output = kp * error + ki * errSum + kd * dErr;       lastErr = error;       lastTime = now;    } } void SetTunings(doubleKp,doubleKi,doubleKd) {   doubleSampleTimeInSec = ((double)SampleTime)/1000;// millis()函数的时间是ms所以/1000可以转化成秒    kp = Kp;    ki = Ki * SampleTimeInSec;//31行    kd = Kd / SampleTimeInSec; } void SetSampleTime(int NewSampleTime) {    if (NewSampleTime >0)    {       doubleratio  = (double)NewSampleTime //39行                       / (double)SampleTime;       ki *= ratio;       kd /= ratio;       SampleTime = (unsigned long)NewSampleTime;    } }

注:9和10行就是PID决定是否进行计算,同时我们也简化了积分和微分的计算。在30和31行,我们知道采样时间是一定的,我们可以通过这个等式等效,就不需要KI,KD不断的与时间变化做乘积。39到42行函数可以改变采样时间,时间是以秒为单位。

附录:             常用被控参数的经验采样周期

被控参数采样周期/s备注被控参数采样周期/s
流量1~5优先选1~2s温度15~20s
压力3~10优先选6~8s直流电机100ms
液位6~8

PID入门提高翻译教程【一】-Arduino中文社区 – Powered by Discuz!

 

文章末尾固定信息

weinxin
我的微信
我的微信
一个码农、工程狮、集能量和智慧于一身的、DIY高手、小伙伴er很多的、80后奶爸。
 
Igor
  • 本文由 Igor 发表于 2019-01-3015:34:15
匿名

发表评论

匿名网友
:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:
确定

拖动滑块以完成验证