I'm trying to implement a PID control on my quadcopter using the Tiva C series microcontroller but I have trouble making the PID stabilize the system.
While I was testing the PID, I noticed slow or weak response from PID controller (the quad shows no response at small angles). In other words, it seems that the quad's angle range has to be relatively large (above 15 degrees) for it to show a any response. Even then, the response always over shoots no matter what I, D gains I choose for my system. At low P, I can prevent overshoot but then it becomes too weak.
I am not sure if the PID algorithm is the problem or if its some kinda bad hardware configuration (low IMU sample rate or maybe bad PWM configurations), but I have strong doubts about my PID code as I noticed changing some of the gains did not improve the system response.
I will appreciate If someone can point out whether i'm doing anything wrong in the PID snippet for the pitch component I posted. I also have a roll PID but it is similar to the code I posted so I will leave that one out.
void pitchPID(int16_t pitch_conversion)
{
float current_pitch = pitch_conversion;
//d_temp_pitch is global variable
//i_temp_pitch is global variable
float pid_pitch=0; //pitch pid controller
float P_term, I_term, D_term;
float error_pitch = desired_pitch - current_pitch;
//if statement checks for error pitch in negative or positive direction
if ((error_pitch>error_max)||(error_pitch<error_min))
{
if (error_pitch > error_max) //negative pitch- rotor3&4 speed up
{
P_term = pitch_kp*error_pitch; //proportional
i_temp_pitch += error_pitch;//accumulate error
if (i_temp_pitch > iMax)
{
i_temp_pitch = iMax;
}
I_term = pitch_ki*i_temp_pitch;
if(I_term < 0)
{
I_term=-1*I_term;
}
D_term = pitch_kd*(d_temp_pitch-error_pitch);
if(D_term>0)
{
D_term=-1*D_term;
}
d_temp_pitch = error_pitch; //store current error for next iteration
pid_pitch = P_term+I_term+D_term;
if(pid_pitch<0)
{
pid_pitch=(-1)*pid_pitch;
}
//change rotor3&4
pitchPID_adjustment (pid_pitch, 'n'); //n for negative pitch
}
else if (error_pitch < error_min) // positive pitch- rotor 1&2 speed up
{
P_term = pitch_kp*error_pitch; //proportional
i_temp_pitch += error_pitch;
if (i_temp_pitch < iMin)
{
i_temp_pitch = iMin;
}
I_term = pitch_ki*i_temp_pitch;
if(I_term > 0)
{
I_term=-1*I_term;
}
D_term = pitch_kd*(d_temp_pitch - error_pitch);
if(D_term < 0)
{
D_term=-1*D_term;
}
d_temp_pitch = error_pitch;
pid_pitch = P_term+I_term+D_term;
if(pid_pitch<0)
{
pid_pitch=(-1)*pid_pitch;
}
print(pid_pitch);//pitch
printString("\r\n");
//change rotor1&2
pitchPID_adjustment(pid_pitch,'p'); //p for positive pitch
}
}
}
void pitchPID_adjustment(float pitchPIDcontrol, unsigned char pitch_attitude)
{
if (pitchPIDcontrol>(maximum_dutyCycle-set_dutyCycle))
{
pitchPIDcontrol=maximum_dutyCycle-set_dutyCycle;
}
switch (pitch_attitude){
//change rotor1&2
case 'p': //positive status
PWM0_2_CMPA_R += (pitchPIDcontrol);//(RED)//motor1
PWM0_0_CMPA_R += (pitchPIDcontrol);//(Yellow)//motor2
break;
//change rotor 3&4
case 'n': //negative status
PWM0_1_CMPA_R += pitchPIDcontrol;//(ORANGE)//motor3
PWM1_1_CMPA_R += pitchPIDcontrol;//(green)//motor4
break;
}
Also, can someone please tell me how this motor mixing works?:
Front =Throttle + PitchPID
Back =Throttle - PitchPID
Left =Throttle + RollPID
Right =Throttle - RollPID
vs what I did in the function:
void pitchPID_adjustment(float pitchPIDcontrol, unsigned char pitch_attitude)