ImprovingtheBeginner’sPID–Introduction翻译:rei1984InconjunctionwiththereleaseofthenewArduinoPIDLibraryI’vedecidedtoreleasethisseriesofposts.Thelastlibrary,whilesolid,didn’treallycomewithanycodeexplanation.Thistimearoundtheplanistoexplainingreatdetailwhythecodeisthewayitis.I’mhopingthiswillbeofusetotwogroupsofpeople:•Peopledirectlyinterestedinwhat’sgoingoninsidetheArduinoPIDlibrarywillgetadetailedexplanation.•AnyonewritingtheirownPIDalgorithmcantakealookathowIdidthingsandborrowwhatevertheylike.It’sgoingtobeatoughslog,butIthinkIfoundanot-too-painfulwaytoexplainmycode.I’mgoingtostartwithwhatIcall“TheBeginner’sPID.”I’llthenimproveitstep-by-stepuntilwe’releftwithanefficient,robustpidalgorithm.为了结合新版arduinoPID库的发布,我决定发表一个系列的文章。在最新的库里,并没有程序的注解和解释。这次我计划围绕程序做一个详细的解释,为什么程序是这样写的。我希望对以下2类人有用:对arduinopid库感兴趣的人,能得到源码的解释。任何正在写自己pid程序的人,能看看我的作品,并且随性浏览。TheBeginner’sPIDHere’sthePIDequationaseveryonefirstlearnsit:ThisleadsprettymucheveryonetowritethefollowingPIDcontroller:下面有pid公式,每个人初次学习都会遇到:这就引导了每个人写出如下的pid算法:1/*workingvariables*/23456789101112131415161718192021222324252627282930unsignedlonglastTime;doubleInput,Output,Setpoint;doubleerrSum,lastErr;doublekp,ki,kd;voidCompute(){/*Howlongsincewelastcalculated*/unsignedlongnow=millis();doubletimeChange=(double)(now-lastTime);/*Computealltheworkingerrorvariables*/doubleerror=Setpoint-Input;errSum+=(error*timeChange);doubledErr=(error-lastErr)/timeChange;/*ComputePIDOutput*/Output=kp*error+ki*errSum+kd*dErr;/*Remembersomevariablesfornexttime*/lastErr=error;lastTime=now;}voidSetTunings(doubleKp,doubleKi,doubleKd){kp=Kp;ki=Ki;kd=Kd;}Compute()iscalledeitherregularlyorirregularly,anditworksprettywell.Thisseriesisn’tabout“worksprettywell”though.Ifwe’regoingtoturnthiscodeintosomethingonparwithindustrialPIDcontrollers,we’llhavetoaddressafewthings:Compute()会被经常或者不经常的调用,他也能运行的很好。这个系列不是讨论工作的怎么好的思路。如果我们用这份代码对比工业上的pid控制器,我们不得不涉及到如下几件事:1.SampleTime-ThePIDalgorithmfunctionsbestifitisevaluatedataregularinterval.Ifthealgorithmisawareofthisinterval,wecanalsosimplifysomeoftheinternalmath.采样时间。如果pid能有规律的被调用。Pid算法函数能有很好的表现。如果算法在采样间隔内,我们也能简化一些内部计算。2.DerivativeKick-Notthebiggestdeal,buteasytogetridof,sowe’regoingtodojustthat.微分界跃-不是最大的难点,很简单的可以去除,所以我们打算那样做。3.On-The-FlyTuningChanges-AgoodPIDalgorithmisonewheretuningparameterscanbechangedwithoutjoltingtheinternalworkings.运行的时候更改PID参数,不会引起界跃输出。4.ResetWindupMitigation-We’llgointowhatResetWindupis,andimplementasolutionwithsidebenefits对windupmitigation的复位-我们介绍什么是复位windup。采用一种方式解决误差。5.On/Off(Auto/Manual)-Inmostapplications,thereisadesiretosometimesturnoffthePIDcontrollerandadjusttheoutputbyhand,withoutthecontrollerinterferingpid的开关。在很多应用里面,pid内有意的关闭,并且用人工的方式调整输出,没有和控制器连接。6.Initialization-Whenthecontrollerfirstturnson,wewanta“bumplesstransfer.”Thatis,wedon’twanttheoutputtosuddenlyjerktosomenewvalue初始化,但我们打开控制器。我们会进行一些参数的传递。这样我们就不会突然输出一个新值。7.ControllerDirection-Thislastoneisn’tachangeinthenameofrobustnessperse.it’sdesignedtoensurethattheuserenterstuningparameterswiththecorrectsign.pid输出的方向-这是最后一篇,主要是引进符号的概念。增加output可能input变小,所以需要符号来表别方向。Oncewe’veaddressedalltheseissues,we’llhaveasolidPIDalgorithm.We’llalso,notcoincidentally,havethecodethat’sbeingusedinthelastestversionoftheArduinoPIDLibrary.Sowhetheryou’retryingtowriteyourownalgorithm,ortryingtounderstandwhat’sgoingoninsidethePIDlibrary,Ihopethishelpsyouout.Let’sgetstarted.Next一旦我们解决了所有问题,我们就有一个坚实的pid算法。并非巧合,我们会采用最新的arduinopid的算法。所以,不管是你打算写自己的算法还是把pid库内容弄明白。我都希望帮助你,让我们开始吧。UPDATE:InallthecodeexamplesI’musingdoubles.OntheArduino,adoubleisthesameasafloat(singleprecision.)TruedoubleprecisionisWAYoverkillforPID.Ifthelanguageyou’reusingdoestruedoubleprecision,I’drecommendchangingalldoublestofloats.更新:所有的程序实例都采用double双精度。在arduino中,双精度double是采用float单精度处理的。Double对于pid来杀鸡用牛刀了。如果你使用的语言有双精度的支持,我建议改变所有的双精度double变为单精度float。SampleTime采样时间(ThisisModification#1inalargerseriesonwritingasolidPIDalgorithm)TheProblemTheBeginner’sPIDisdesignedtobecalledirregularly.Thiscauses2issues:不规则的调用pid算法,会产生2个问题:•Youdon’tgetconsistentbehaviorfromthePID,sincesometimesit’scalledfrequentlyandsometimesit’snot.当你有时候规则的调用pid算法,有时候又停止调用时,你不会得要pid的一个长期的调整。(算法不能正确的执行)•Youneedtodoextramathcomputingthederivativeandintegral,sincethey’rebothdependentonthechangeintime.你必须要做微分和积分,因为他们都是和时间息息相关的。TheSolutionEnsurethatthePIDiscalledataregularinterval.ThewayI’vedecidedtodothisistospecifythatthecomputefunctiongetcalledeverycycle.basedonapre-determinedSampleTime,thePIDdecidesifitshouldcomputeorreturnimmediately.OnceweknowthatthePIDisbeingevaluatedataconstantinterval,thederivativeandintegralcalculationscanalsobesimplified.Bonus!TheCode123456789/*workingvariables*/unsignedlonglastTime;doubleInput,Output,Setpoint;doubleerrSum,lastErr;doublekp,ki,kd;intSampleTime=1000;//1secvoidCompute(){unsignedlongnow=millis();101112131415161718192021222324252627282930313233343536373839404142434445inttimeChange=(now-lastTime);if(timeChange=SampleTime)//等间隔采样{/*Computealltheworkingerrorvariables*/doubleerror=Setpoint-Input;errSum+=error;doubledErr=(error-lastErr);/*ComputePIDOutput