I am trying to tune PID controllers for my drone. There are 3 controllers, one each for Pitch, Yaw and Roll. I have gotten Yaw tuned to a reasonable amount and I am assuming the values for Kp, Ki and Kd are pretty much the same for pitch and roll.
Currently, for pitch and roll, I have Kp = 0.5, and Ki=Kd=0. I am trying to set Kp right now before I move on to Ki and Kd, but no matter what value I put there, the drone (which I have hanging from a string along its center of gravity) oscillates with increasing amplitude until it is completely out of control. Changing Kp only seems to affect how quickly the oscillations increase in amplitude.
Is this the wrong strategy to tune the coefficients or do I have the wrong test setup?
Thank you for your help.
PID Controller code: (Arduino C++)
/**
* Calculate motor speed for each motor of an X quadcopter depending on received instructions and measures from sensor
* by applying PID control.
*
* (4) (2) x
* \ / z ↑
* X \|
* / \ +----→ y
* (3) (1)
*
* Motors 4 & 1 run clockwise.
* Motors 2 & 3 run counter-clockwise.
*
* Each motor output is considered as a servomotor. As a result, value range is about 1000µs to 2000µs
*/
void pidController() {
unsigned long t = micros();
float dt = (t-timer2)/1000000.0;
float delta_err[3] = {0, 0, 0}; // Error deltas in that order : Yaw, Pitch, Roll
// Calculate sum of errors : Integral coefficients
error_sum[YAW] += errors[YAW]*dt;
error_sum[PITCH] += errors[PITCH]*dt;
error_sum[ROLL] += errors[ROLL]*dt;
// Calculate error delta : Derivative coefficients
delta_err[YAW] = (errors[YAW] - previous_error[YAW])/dt;
delta_err[PITCH] = (errors[PITCH] - previous_error[PITCH])/dt;
delta_err[ROLL] = (errors[ROLL] - previous_error[ROLL])/dt;
// Save current error as previous_error for next time
previous_error[YAW] = errors[YAW];
previous_error[PITCH] = errors[PITCH];
previous_error[ROLL] = errors[ROLL];
// PID = e.Kp + ∫e.Ki + Δe.Kd
float yaw_pid = (errors[YAW] * YAWp) + (error_sum[YAW] * YAWi) + (delta_err[YAW] * YAWd);
float pitch_pid = (errors[PITCH] * PITCHp) + (error_sum[PITCH] * PITCHi) + (delta_err[PITCH] * PITCHd);
float roll_pid = (errors[ROLL] * ROLLp) + (error_sum[ROLL] * ROLLi) + (delta_err[ROLL] * ROLLd);
// Calculate pulse duration for each ESC
pulse_length_esc1 = constrain(holdingthrottle - roll_pid + pitch_pid - yaw_pid, 1000, THROTTLE_LIMIT); //holdingthrottle = 1400, THROTTLE_LIMIT=2000
pulse_length_esc2 = constrain(holdingthrottle + roll_pid + pitch_pid + yaw_pid, 1000, THROTTLE_LIMIT);
pulse_length_esc3 = constrain(holdingthrottle - roll_pid - pitch_pid + yaw_pid, 1000, THROTTLE_LIMIT);
pulse_length_esc4 = constrain(holdingthrottle + roll_pid - pitch_pid - yaw_pid, 1000, THROTTLE_LIMIT);
}