首先要明确一个概念,控制大疆电机我们只能控制其给定的电流,即我们只能将要设置的电流以CAN报文的形式发送给大疆电机的电调(DJ_CurrentTransmit)
电流对电机的作用是给他一个恒定的速度,电流越大速度越大。
大疆电机采用三环嵌套:电流环->速度环->位置环

大疆DJMotor结构体里定义了两个PID结构体分别控制位置环PID和速度环PID:
typedef struct
{
vs32 SetVal; //要PID调节参数的目标值
vs32 CurVal; //要PID调节参数的当前值
float Kp; //PID参数
float Ki;
float Kd;
vs32 delta; //PID增量
vs32 midVal[3]; //本次偏差,上次偏差,上上次偏差
}Inc_PIDTypedef;
Inc_PIDTypedef PID_POS,PID_RPM;

在PID初始化中赋值要调整参数的目标值Set和PID参数Kp/Ki/Kd:
void Inc_PID_Init(Inc_PIDTypedef* PID,float KP,float KI,float KD,int Set)
{
PID->CurVal=0;
PID->SetVal=Set;
PID->midVal[0]=0;
PID->midVal[1]=0;
PID->midVal[2]=0;
PID->Kp=KP;
PID->Ki=KI;
PID->Kd=KD;
}
Inc_PID_Init(&DJmotor[PitchID].PID_POS, 1.3, 0.2, 0.0,DJmotor[ID].valueSet.pulse);
Inc_PID_Init(&DJmotor[PitchID].PID_RPM, 8.0, 0.5, 0.0,DJmotor[ID].valueSet.speed);

增量式PID调节函数:
void Inc_PID_Operation(Inc_PIDTypedef PID)
{
PID->midVal[0]=PID->SetVal-PID->CurVal; //得到当前偏差
PID->delta = PID->Kp
(PID->midVal[0]-PID->midVal[1]) + PID->Ki PID->midVal[0] + PID->Kd (PID->midVal[0]+PID->midVal[2]-2PID->midVal[1]); //得到当前增量
PID->midVal[2]=PID->midVal[1]; //更新上次偏差与上上次偏差
PID->midVal[1]=PID->midVal[0];
}
Inc_PID_Operation(&DJmotor[id].PID_POS);
Inc_PID_Operation(&DJmotor[id].PID_RPM);
增量式PID原理:可参考pid文档,这里简单概括一下。比例相Kp调节当前偏差和上次偏差的差值,积分项Ki调节当前偏差,微分相Kd调节当前偏差和上次偏差的差值和上次偏差和上上次偏差的差值的差值(PID->midVal[0]-
PID->midVal[1])-(PID->midVal[1]-*PID->midVal[2])
由于增量式PID控制增量,所以其公式可以由两次相邻时刻位置型PID的差值推得:

可以看到,结果就是这么来的。

了解以上知识后,我们就可以看大疆PID的调节了:
用电流控制速度:
DJmotor[id].PID_RPM.SetVal = DJmotor[id].valueSet.speed;
DJmotor[id].PID_RPM.CurVal = DJmotor[id].valueReal.speed;
Inc_PID_Operation(&DJmotor[id].PID_RPM);
DJmotor[id].valueSet.current += DJmotor[id].PID_RPM.delta;
根据设定速度和当前速度进行增量式PID调节,将增量加到电流相当于加到速度。
用电流控制位置:
DJmotor[id].PID_POS.SetVal = DJmotor[id].valueSet.pulse;
DJmotor[id].PID_POS.CurVal = DJmotor[id].valueReal.pulse;
Inc_PID_Operation(&DJmotor[id].PID_POS);
DJmotor[id].PID_RPM.SetVal = DJmotor[id].PID_POS.delta;
DJmotor[id].PID_RPM.CurVal = DJmotor[id].valueReal.speed;
Inc_PID_Operation(&DJmotor[id].PID_RPM);
DJmotor[id].valueSet.current += DJmotor[id].PID_RPM.delta;
控制位置分为两步,由于速度是位置的导数,故先根据设定位置和当前位置进行增量式 PID调节,而其增量就是速度,故直接将增量结果赋值给要设定的速度(而非自加)
接着再根据速度和当前速度进行增量式PID调节,将增量加到电流。