本帖最后由 FSL_TICS_ZJJ 于 2014-5-7 11:08 编辑
PID实指“比例proportional”、“积分integral”、“微分derivative” , 这三项构成PID基本要素。每一项完成不同任务对系统功能产生不同的影响。 搞软件的往往对硬件不屑 ,却忘了软件再牛B也是为硬件服务的 , PID的数字化算法就完全是为硬件而生的 , 这是控制电机算法的一个难点 , 没有一定的对软硬件的理解 , 就连调试装定PID参数都会很为难 ! 飞思卡尔智能车项目里面就会用到PID算法 , 比如车爬坡和平地连续拐弯时 , 代码里面没有PID算法 , 控制和驱动起来就会很拙急 , 对不对 ? 不过 ,搞清楚问题还是有个前提的 , 那就是懂点微积分 , 不会微积分嘛 , 下面的内容无需关注
实际上 , PID算法的应用基础始于对PCB板上的运放的PID参数进行调校 , P对应于运放增益 ; I 就是运放输入和输出端之间接一个电容引入反馈 , 就是控制器的输出与输入误差会积累起来影响输出 ; D 就是运放输入端串接一个电容 ,起的微分作用是阻止输出与输入误差的变化 . 结合示波器来观察控制电机的PID参数设定的话 , 网上有一首诗 , 它就代表我的心声了 :
参数整定找最佳,从小到大顺序查
先是比例后积分,最后再把微分加
曲线振荡很频繁,比例度盘要放大
曲线漂浮绕大湾,比例度盘往小扳
曲线偏离回复慢,积分时间往下降
曲线波动周期长,积分时间再加长
曲线振荡频率快,先把微分降下来
动差大来波动慢,微分时间应加长
理想曲线两个波,前高后低四比一
一看二调多分析,调节质量不会低 !
下面贴段代码 (真的是仅供参考):
#include <mc9s12dg128.h> /* derivative information */
/*
***********************************************************************************
* 宏定义
**********************************************************************************/
#define STABMAX 50
#define SENSORNUM 8
#define SAMPLETIMES 5
/*
***********************************************************************************
* FUNCTION PROTOTYPES
**********************************************************************************/
int CalculateP(void);
float CalculatePID(void);
/********************************** PID控制程序 ********************************/
struct CARSTATE
{
int E0;
int E1;
int E2;
int E3;
float Integral;
}CarState;
/*
***********************************************************************************
* 初始化PID参数
**********************************************************************************/
void Init_PID()
{
CarState.E0 = 0;
CarState.E1 = 0;
CarState.E2 = 0;
CarState.E3 = 0;
CarState.Integral = 0;
}
/*
**********************************************************************************
* 信号处理函数
*
* 程序描述: 对传感器采集过来的数据进行处理,得到一些基本的计算参数
*
**********************************************************************************/
int SignalProcess( unsigned int signal )
{
const int BitValue[8] = {43,26,12,6,-6,-12,-26,-43}; //MAX:28
int i,CurrPoint=0,LastPoint=0,BitNum=0;
unsigned char SignalBit[8];
for(i=0;i<8;i++)
{
SignalBit
= signal & 0x0001;
BitNum += SignalBit;
signal >>= 1;
}
switch(BitNum)
{
case 1:
for(i=0;i<8;i++)
if(SignalBit != 0)
CurrPoint += BitValue;
CarState.E0 = CurrPoint;
break;
case 2:
for(i=0;i<8;i++)
if(SignalBit != 0)
CurrPoint += BitValue;
CurrPoint >>= 1;
CarState.E0 = CurrPoint;
break;
default:
CarState.E0 = CarState.E1;
break;
}
return CalculateP()*100;
}
/*
**********************************************************************************
*
* PID计算函数
*
* 程序描述: 计算P参数
*
**********************************************************************************/
int CalculateP(void)
{
CarState.E1 = CarState.E0;
return((int)CarState.E0);
}
/*
***********************************************************************************
* PID计算函数
*
* 程序描述: 对传感器采集过来的数据进行处理,得到一些基本的计算参数
*
******************************************************************* ***************/
float CalculatePID(void)
{
float P, I = 0, D;
/* parameter const */
float Kp = 1.0, Ki = -0.0002, Kd = -0.0002;
/* P parameter */
P = CarState.E0 * Kp;
/* I parameter */
if(P+I<2)
{
CarState.Integral += Ki * CarState.E0;
I = CarState.Integral;
}
/* D parameter */
D = Kd * ( CarState.E0 + 3*CarState.E1 - 3*CarState.E2 - CarState.E3 )/6.0;
CarState.E3 = CarState.E2;
CarState.E2 = CarState.E1;
CarState.E1 = CarState.E0;
return (P+I+D);
}
坐等整数的算法,实数的确实有点太占资源了!
一周热门 更多>