编辑: NaluLee 2019-08-02
我的题目是:基于PID算法的温度控制系统 89C51单片机,通过键盘输入预设值,与DS18B20测得的实际值做比较,然后驱动制冷或加热电路.

用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

下载(注:源文件不在本站服务器,都将跳转到源网站下载)
备用下载
发帖评论
相关话题
发布一个新话题