PID实际编程的过程的,要注意的东西还是有几点的。PID这东西可以做得很深。 1 PID的诊定。凑试法,临界比例法,经验法。 2 T的确定,采样周期应远小于过程的扰动信号的周期,在小车程序中一般是ms级别。 3 目标速度何时赋值问题,如何更新新的目标速度?这个问题一般的人都乎略了。目标速度肯定不是个恒定的,那么何时改变目标速度呢? 4 改变了目标速度,那么e(k) e(k-1) e(k-2)怎么改变呢?是赋0还是要怎么变? 5 是不是PID要一直开着? 6 error为多少时就可以当速度已达到目标? 7 PID的优先级怎么处理,如果和图像采集有冲突怎么办? 8 PID的输入是速度,输出是PWM,按理说PWM产生速度,但二者不是同一个东西,有没有问题? 9 PID计算如何优化其速度?指针,汇编,移位?都可以试! //***************************************************** //定义PID结构体 //***************************************************** typedef struct PID { int SetPoint; //设定目标 Desired Value double Proportion; //比例常数 Proportional Const double Integral; //积分常数 Integral Const double Derivative; //微分常数 Derivative Const int LastError; //Error[-1] int PrevError; //Error[-2] } PID; //***************************************************** //定义相关宏 //***************************************************** #define P_DATA 100 #define I_DATA
0.6 #define D_DATA
1 #define HAVE_NEW_VELOCITY 0X01 //***************************************************** //声明PID实体 //***************************************************** static PID sPID; static PID *sptr = &sPID; //***************************************************** //PID参数初始化 //***************************************************** void IncPIDInit(void) { sptr->LastError = 0; //Error[-1] sptr->PrevError = 0; //Error[-2] sptr->Proportion = P_DATA; //比例常数 Proportional Const sptr->Integral = I_DATA; //积分常数Integral Const sptr->Derivative = D_DATA; //微分常数 Derivative Const sptr->SetPoint =100;
目标是100 } //***************************************************** //增量式PID控制设计 //***************************************************** int IncPIDCalc(int NextPoint) { int iError, iIncpid; //当前误差 iError = sptr->SetPoint - NextPoint; //增量计算 iIncpid = sptr->Proportion * iError //E[k]项 - sptr->Integral * sptr->LastError //E[k-1]项 + sptr->Derivative * sptr->PrevError; //E[k-2]项 sptr->PrevError = sptr->LastError;
//存储误差,用于下次计算 sptr->LastError = iError; return(iIncpid);
//返回增量值 } Int g_CurrentVelocity; Int g_Flag; void main(void) {
DisableInterrupt
InitMCu();
IncPIDInit();
g_CurrentVelocity=0;
//全局变量也初始化 g_Flag=0;
//全局变量也初始化 EnableInterrupt;
While(1)
{
if (g_Flag& HAVE_NEW_VELOCITY)
{
PWMOUT+= IncPIDCalc(CurrentVelocity);
g_Flag&=~ HAVE_NEW_VELOCITY;
} } } //**************************************** //采样周期T //**************************************** Interrrupt TIME void {
CurrentVelocity =GetCurrentVelocity;
g_Flag|= HAVE_NEW_VELOCITY;
} |