程序是自己编的,根据多方资料改写了一部分,为增量式PID算法。程序采用浮点形式,如果MCU速度不够快,可根据需求转换定点运算。关键变量:ref——设置的参数;feb——采样反馈;根据实际情况修改这两个变量即可。相关参数:Kp、Ti、Td、T:根据各项目的控制对象不同而修改其定义值。//定义变量doubleref=0;//设置参数doublefeb=0;//采样反馈intpwm_var=0;//PID调整量Uint16PWM_out=0;//PWM输出量doubleUo=0;doubleEk=0;doubleEi=0;doubleEd=0;#defineKp8//PID调节的比例常数#defineTi0.05//PID调节的积分常数#defineTd0.02//PID调节的微分时间常数#defineT0.02//采样周期#defineKppKp*(1+(T/Ti)+(Td/T))#defineKi(-Kp)*(1+(2*Td/T))#defineKdKp*Td/T//#defineKpp4//#defineKi0.8//#defineKd20//误差的阀值,小于这个数值的时候,不做PID调整,避免误差较小时频繁调节引起震荡#defineEmin3//调整值限幅,防止积分饱和#defineUmax100#defineUmin-100//输出值限幅#definePmax15500#definePmin200/////////////////////////////////////////////////////////////////////////PID运算///////voidpid_ctrl(void){Ek=ref-feb;//差值运算if(fabs(Ek)Emin)//误差的阀值(死区控制??){pwm_var=0;}else{Uo=Kpp*Ek+Ki*Ei+Kd*Ed;//PID计算Ed=Ei;Ei=Ek;pwm_var=(int)Uo;//强制转化调整量,PWM为整数if(pwm_var=Umax)pwm_var=Umax;//调整值限幅,防止积分饱和if(pwm_var=Umin)pwm_var=Umin;//调整值限幅,防止积分饱和}PWM_out+=pwm_var;//调整PWM输出if(PWM_outPmax)PWM_out=Pmax;//输出值限幅if(PWM_outPmin)PWM_out=Pmin;//输出值限幅TBCCR1=PWM_out;//输出给寄存器,改变PWM占空比}///////////////////////////////////////////////////////////////////调用示例:voidmain(void){ref=120.6;while(1){feb=adc_sample();pid_ctrl();}}另外附上:PID调节经验总结(搜索资源)PID控制器参数选择的方法很多,例如试凑法、临界比例度法、扩充临界比例度法等。但是,对于PID控制而言,参数的选择始终是一件非常烦杂的工作,需要经过不断的调整才能得到较为满意的控制效果。依据经验,一般PID参数确定的步骤如下:(1)确定比例系数Kp确定比例系数Kp时,首先去掉PID的积分项和微分项,可以令Ti=0、Td=0,使之成为纯比例调节。输入设定为系统允许输出最大值的60%~70%,比例系数Kp由0开始逐渐增大,直至系统出现振荡;再反过来,从此时的比例系数Kp逐渐减小,直至系统振荡消失。记录此时的比例系数Kp,设定PID的比例系数Kp为当前值的60%~70%。(2)确定积分时间常数Ti比例系数Kp确定之后,设定一个较大的积分时间常数Ti,然后逐渐减小Ti,直至系统出现振荡,然后再反过来,逐渐增大Ti,直至系统振荡消失。记录此时的Ti,设定PID的积分时间常数Ti为当前值的150%~180%。(3)确定微分时间常数Td微分时间常数Td一般不用设定,为0即可,此时PID调节转换为PI调节。如果需要设定,则与确定Kp的方法相同,取不振荡时其值的30%。(4)系统空载、带载联调对PID参数进行微调,直到满足性能要求。增量式PID控制算法当执行机构需要的不是控制量的绝对值,而是控制量的增量(例如去驱动步进电动机)时,需要用PID的“增量算法”。增量式PID控制算法C51程序?12345678910111213141516171819202/*====================================================================================================PIDFunctionThePID(比例、积分、微分)functionisusedinmainlycontrolapplications.PIDCalcperformsoneiterationofthePIDalgorithm.WhilethePIDfunctionworks,mainisjustadummyprogramshowingatypicalusage.=====================================================================================================*/typedefstructPID{intSetPoint;//设定目标DesiredValuelongSumError;//误差累计doubleProportion;//比例常数ProportionalConstdoubleIntegral;//积分常数IntegralConstdoubleDerivative;//微分常数DerivativeConstintLastError;//Error[-1]intPrevError;//Error[-2]}PID;12223242526272829303132333435363738394041424staticPIDsPID;staticPID*sptr=&sPID;/*====================================================================================================InitializePIDStructurePID参数初始化=====================================================================================================*/voidIncPIDInit(void){sptr-SumError=0;sptr-LastError=0;//Error[-1]sptr-PrevError=0;//Error[-2]sptr-Proportion=0;//比例常数ProportionalConstsptr-Integral=0;//积分常数IntegralConstsptr-Derivative=0;//微分常数DerivativeConstsptr-SetPoint=0;}/*====================================================================================================增量式PID计算部分=====================================================================================================*/intIncPIDCalc(intNextPoint){34445464748495051525354registerintiError,iIncpid;//当前误差iError=sptr-SetPoint-NextPoint;//增量计算iIncpid=sptr-Proportion*iError//E[k]项-sptr-Integral*sptr-LastError//E[k-1]项+sptr-Derivative*sptr-PrevError;//E[k-2]项//存储误差,用于下次计算sptr-PrevError=sptr-LastError;sptr-LastError=iError;//返回增量值return(iIncpid);}