该代码是基于msp430f149的pid算法
PID.h
#include "PID.h"
PID pid;//存放PID算法所需要的数据,即结构体
//**********************************************************************************
// PID算法
// PID公式out=(Kp*Ek)+(Kp*(T/Ti)∑(0--n)Ek)+(Kp*(Td/T)(Ek-Ek_1))+out0
//**********************************************************************************
void PID_Calc(void)//PID的计算
{
float DelEk;//相邻两次偏差值
float TI,KI;//(T/Ti),(Kp*(T/Ti))
float Iout;
float Pout;
float Dout;
float TD; //(Td/T)
float KD; //(Kp*(Td/T))
float out; //用来暂时存储pid的脉宽
if(pid.C10ms<pid.T/10) //计算周期未到
{
return ;
}
pid.Ek = pid.Sv - pid.Pv;//当前的偏差值=设定值-实际值
pid.SEk += pid.Ek; //历史偏差总和 ,偏差值有正负不会无穷大
DelEk = pid.Ek - pid.Ek_1;//最近两次的偏差
TI = pid.T/pid.Ti;
KI = TI*pid.Kp; //即是(Kp*(T/Ti))
TD = pid.Td/pid.T;
KD = TD * pid.Kp; //即是(Kp*(Td/T))
Pout = pid.Kp * pid.Ek; //比例输出
Iout = pid.SEk * KI; //积分输出
Dout = KD * DelEk; //微分输出
out = Pout + Iout + Dout + pid.OUT0;//本次输出的脉宽
//pid.out有可能是正值也有可能是负值
//pid.out的占空比不会超过100也不会小于0
//用TACCR0设置周期,即PID的周期
if(out>TACCR0)//如果out的值比周期还大
{
pid.out = TACCR0;//就让输出的pwm等于周期
}
if(out<0)//如果输出值为负数
{
pid.out = 0;//就让输出的pwm等于最小值0
}
pid.out = out;//否则直接输出
pid.Ek_1 = pid.Ek;//更新偏差
pid.C10ms = 0;//每执行一次中断后就++
}
PID.c
#ifndef __pid__
#define __pid__
#include "msp430x14x.h"
//**********************************************************************************
// 用结构体对pid进行保存
//PID公式out=(Kp*Ek)+(Kp*(T/Ti)∑(0--n)Ek)+(Kp*(Td/T)(Ek-Ek_1))+out0
//**********************************************************************************
typedef struct //创建一个结构体
{
float Sv; //用户设定值
float Pv; //当前传感器反馈值,把传感器所得的值给他
float Kp; //比例系数
float T; //PID的计算周期->采样周期,即多长时间执行一次pid算法
float Ti; //积分时间常数
float Td; //微分时间常数
float Ek; //本次偏差
float Ek_1; //上次偏差
float SEk; //前n项和,即历史偏差之和
float OUT0; //常数,防止输出为零,给出的稳定输出
float out; //本次应该输出的pwm
int C10ms; //计算的10ms值让他加
}PID;
extern PID pid;//外部声明,防止报错
void PID_Calc();//PID的计算
#endif
|