专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

PID 算法 C18 程序的实现

作者:佚名   来源:本站原创   点击数:  更新时间:2010年08月28日   【字体:

当然 为了省事 我们当然去搞增量PID 了 何况 前辈们都说这个比较好

PID 计算资源需求

DS=Pdu(k)+I t/ti( uk)+ D TD/T duk+du(k-1)

puk-i *T/TI*uk+d*(uk-2* uk-1 + uk-2)

 三个系统状态是需要的 UK UK-1  UK-2 

还有P I D 的参数也是需要的

当然还有个 采样时间 T (似乎也有人 把积分时间 T 和微分时间T 分开了? 我不是很明白不管他)

应为不同的硬件体系 我们需要计算数据的位数 有差异(可能需要int型 去算 也可能用 long  ,floAt 等)

应为是C18下的 我先试用INT 去做

#define  PID_TYPE int

这样以后换类型也省事

于是我们定义1个结构体


struct pid_unit { 
        PID_TYPE pid_sens[3];   // 用来保存 UK UK-1 UK-2 三个时刻的输出偏差

        PID_TYPE pid_cpid[3];   // 当然是 P  I  D 三个参数咯
        PID_TYPE pid_dpid[3];   // P 部分计算值 I部分计算值 D 部分计算值 这三个值相加就是PID 的输出

      };

 

 

初始化PID

void pid_init(struct pid_unit *unit, 

              PID_TYPE p,             

              PID_TYPE i,            

              PID_TYPE d)              
{ 
        unit->pid_cpid[0] = p; //PID 比例系数 初始化 没得说 哈
        unit->pid_cpid[1] = i; 
        unit->pid_cpid[2] = d; 
 
        unit->pid_dpid[0] = 0;//P  i  d 个个部分都假定为0  不过实际也是0#24
        unit->pid_dpid[1] = 0; //
        unit->pid_dpid[2] = 0; //
 
        unit->pid_sens[0] = 0; // 当前差值

  unit->pid_sens[1] = 0; //

        unit->pid_sens[2] = 0; //


}

接下来 就是计算部分了

第一部分 P部分 计算

unit->pid_dpid[0]  =  unit->pid_sens[0] * unit->pid_cpid[0]; //就是P*UK

然后是I部分 。。不过大家会发现I还需要前一次的计算结果。。咋办。。

第一次 用的是0。n那么第二次 用的就是现在的咯

所以要保存现在的值 给下一次用

同时保存上一次的值 到上上一次

说的这么拗口,。那是我语文没学好

其实就是保存三个时间状态值

丢弃最老的 保存最新的

        unit->pid_sens[1] = unit->pid_sens[0];
        unit->pid_sens[0] = input;

  unit->pid_dpid[1] =  unit->pid_sens[0] * unit->pid_cpid[1] * time;

等我吃个饭再来 有点问题
 GOOGLE 源码是  :

 unit->pid_dpid[1] +=  unit->pid_sens[0] * unit->pid_cpid[1] * time;

ΔU = U(k)-U(k-1) = Kp*[e(k)-e(k-1)]+Ki*e(k)+Kd*[e(k)-2*e(k-1)+e(k-2)]

是肯定没问题的。。所以 似乎GOOGLE 上源码不对哦,,大家要注意了
 

D部分  Kd*[e(k)-2*e(k-1)+e(k-2)

  
 unit->pid_dpid[2]  = ((unit->pid_sens[0] - 2*unit->pid_sens[1]+unit->pid_sens[2])/time) *unit->pid_cpid[2];
然后对P  I  D 求和

unit->pid_dpid[0] +                 unit->pid_dpid[1] +                unit->pid_dpid[2];

 

故有PID 计算子函数如下

 

PID_TYPE pid_control(struct pid_unit *unit,   
                     PID_TYPE input,          

                     PID_TYPE time)            
{ 
        // adjust the FIFO preserving the sensor data 
        unit->pid_sens[1] = unit->pid_sens[0]; 
        unit->pid_sens[0] = input; 
 
        // calculate each pid variable 
        unit->pid_dpid[0]  =  unit->pid_sens[0] * unit->pid_cpid[0]; 
        unit->pid_dpid[1] =  unit->pid_sens[0] * unit->pid_cpid[1] * time; 
        unit->pid_dpid[2]  = (unit->pid_sens[0] - unit->pid_sens[1])/time *unit->pid_cpid[2]; 
 
        return unit->pid_dpid[0] +  
               unit->pid_dpid[1] + 
               unit->pid_dpid[2]; 
} 
 
关闭窗口

相关文章