徐富军的工作笔记 https://bbs.21ic.com/?51766 [收藏] [复制] [RSS]

日志

PID相关的程序

已有 2811 次阅读2009-6-25 03:54 |个人分类:我的项目|系统分类:单片机| pid

很长时间没有更新blog了


另外有个事情比较抱歉,由于有阵子sina的邮箱不好用,所以我改用了gmail的邮箱,结果今天突然看看sina的邮箱,发现有不少朋友管我要9200的protel文件以及pid的程序,我想我干脆直接贴在这里吧,希望这点信息对那些朋友还有用。


// 数据全部采用long型,最后的两位表示小数


struct _pid
{
 long set_point;   //设定值           
 long ek0;   //当前误差               
 long ek1;  //上一次误差                
 long ek2;  //上上次误差                
 long uk0;  //当前输出                
 long uk1;  //上一次输出                
 long kp;                    
 long ki;                    
 long kd;                    
};


void pid_init(void)
{
 pid.set_point = parameters.cur_set_point_temp;


 pid.kp = (long) (parameters.p);
 pid.ki = (long) (parameters.i);
 pid.kd = (long) (parameters.d);


 pid.ek0 = 0;
 pid.ek1 = 0;
 pid.ek2 = 0;
 pid.uk0 = 0;
 pid.uk1 = 0;
 
 ad_scall = parameters.ad_zero_value - parameters.ad_full_value;  //软件校后的采样数据范围
}


// 改进型的pid算法,积分的范围有限制,可以有效改善稳定过程中的过冲


void pid_output_caculate(void)
{
 // 计算本次误差
 pid.ek0 = (long) pid.set_point * 10 - (long) current_temp;
 deltauk = pid.kp * (pid.ek0 - pid.ek1) / 100;
 
 // 在3度范围才进行积分
 if(abs(pid.ek0) < 300)
 {
  deltauk += pid.ki * pid.ek0 / 1000;
 }
 
 // 加上微分量
 deltauk += pid.kd * (pid.ek2 + pid.ek0 - 2 * pid.ek1) / 100;


 // 得到当前输出
 pid.uk0 = pid.uk1 + deltauk; 


 // 保存当前的数据
 pid.ek2 = pid.ek1;
 pid.ek1 = pid.ek0;
 pid.uk1 = pid.uk0;
}


路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)