编辑: NaluLee | 2019-08-02 |
用keil C语言来实现PID的控制. 最佳答案 //PID算法温控C语言2008-08-17 18:58 #include #include #include #include struct PID { unsigned int SetPoint;
// 设定目标 Desired Value unsigned int Proportion;
// 比例常数 Proportional Const unsigned int Integral;
// 积分常数 Integral Const unsigned int Derivative;
// 微分常数 Derivative Const unsigned int LastError;
// Error[-1] unsigned int PrevError;
// Error[-2] unsigned int SumError;
// Sums of Errors };
struct PID spid;
// PID Control Structure unsigned int rout;
// PID Response (Output) unsigned int rin;
// PID Feedback (Input) sbit data1=P1^0;
sbit clk=P1^1;
sbit plus=P2^0;
sbit subs=P2^1;
sbit stop=P2^2;
sbit output=P3^4;
sbit DQ=P3^3;
unsigned char flag,flag_1=0;
unsigned char high_time,low_time,count=0;
//占空比调节参数 unsigned char set_temper=35;
unsigned char temper;
unsigned char i;
unsigned char j=0;
unsigned int s;
延时子程序,延时时间以12M晶振为准,延时时间为30us*time void delay(unsigned char time) { unsigned char m,n;
for(n=0;
nPrevError = pp->LastError;
pp->LastError = Error;
return (pp->Proportion * Error//比例 + pp->Integral * pp->SumError //积分项 + pp->Derivative * dError);
// 微分项 } 温度比较处理子程序 compare_temper() { unsigned char i;
if(set_temper>temper) { if(set_temper-temper>1) { high_time=100;
low_time=0;
} else { for(i=0;
iIntegral * pp->SumError // 积分项 - pp->Derivative * dError // 微分项 );
} ??? 在实际运算时,由于水具有很大的热惯性,而且PID 运算中的I(积分项)具有非常明显的延迟效应所以不能保留,我们必须把积分项去掉,相反D(微分项)则有很强的预见性,能够加快反应速度,抑制超调量,所以积分作用应该适当加强才能达到较佳的控制效果,系统最终选择PD 控制方案,下面C 代码所示为PD 控制的实现过程: float PIDCalc( PID *pp, int NextPoint ) { int dError,Error;
Error = pp->SetPoint*10 - NextPoint;
// 偏差,设定值减去当前采样值 dError = Error-pp->LastError;
// 当前微分,偏差相减 pp->PrevError = pp->LastError;
// 保存 pp->LastError = Error;
return (pp->Proportion * Error // 比例项 - pp->Derivative * dError // 微分项 );
} 温度控制实现 ??? 通过温度的PID 运算,产生结果fOut,该参数决定是否加热,加热时间是多长.该程序如下: stPID.Proportion = 2;
//设置PID 比例值 stPID.Integral = 0;
//设置PID 积分值 stPID.Derivative = 5;
//设置PID 微分值 fOut = PIDCalc ( &stPID,(int)(fT*10) );
//PID 计算 if(fOutsp = set_point;
} pid_tune DESCRIPTION Sets the proportional gain (p_gain), integral gain (i_gain), derivitive gain (d_gain), and the dead band (dead_band) of a pid control structure _pid. void pid_tune(struct _pid *pid, float p_gain, float i_gain, float d_gain, int dead_band) { pid->pgain = p_gain;
pid->igain = i_gain;
pid->dgain = d_gain;
pid->deadband = dead_band;
pid->integral= integral_val;
pid->last_error=0;
} pid_setinteg DESCRIPTION Set a new value for the integral term of the pid equation. This is useful for setting the initial output of the pid controller at start up. void pid_setinteg(struct _pid *pid,float new_integ) { pid->integral = new_integ;
pid->last_error = 0;
} pid_bumpless DESCRIPTION Bumpless transfer algorithim. When suddenly changing setpoints, or when restarting the PID equation after an extended pause, the derivative of the equation can cause a bump in the controller output. This function will help smooth out that bump. The process value in *pv should be the updated just before this function is used. void pid_bumpless(struct _pid *pid) { pid->last_error = (pid->sp)-(pid->pv);
} pid_calc DESCRIPTION Performs PID calculations for the _pid structure *a. This function uses the positional form of the pid equation, and incorporates an integral windup prevention algorithim. Rectangular integration is used, so this function must be repeated on a consistent time basis for accurate control. RETURN VALUE The new output value for the pid loop. USAGE #i nclude "control.h"*/ float pid_calc(struct _pid *pid) { int err;
float pterm, dterm, result, ferror;
err = (pid->sp) - (pid->pv);
if (abs(err) > pid->deadband) { ferror = (float) err;
/*do integer to float conversion only once*/ pterm = pid->pgain * ferror;
if (pterm >
100 || pterm < -100) { pid->integral = 0.0;
} else { pid->integral += pid->igain * ferror;
if (pid->integral > 100.0) { pid->integral = 100.0;
} else if (pid->integral < 0.0) pid->integral = 0.0;
} dterm = ((float)(err - pid->last_error)) * pid->dgain;
result = pterm + pid->integral + dterm;
} else result = pid->integral;
pid->last_error = err;
return (result);
} void main(void) { float display_value;
int count=0;
pid = &warm;
// printf("Enter the values of Process point, Set point, P gain, I gain, D gain n");
// scanf("%d%d%f%f%f", &process_point, &set_point, &p_gain, &i_gain, &d_gain);
process_point = 30;
set_point = 40;
p_gain = (float)(5.2);
i_gain = (float)(0.77);
d_gain = (float)(0.18);
dead_band = 2;
integral_val =(float)(0.01);
printf("The values of Process point, Set point, P gain, I gain, D gain n");
printf(" %6d %6d %4f %4f %4fn", process_point, set_point, p_gain, i_gain, d_gain);
printf("Enter the values of Process pointn");
while(count