Note that there are some explanatory texts on larger screens.

plurals
  1. POPID controller integral term causing extreme instability
    primarykey
    data
    text
    <p>I have a PID controller running on a robot that is designed to make the robot steer onto a compass heading. The PID correction is recalculated/applied at a rate of 20Hz.</p> <p>Although the PID controller works well in PD mode (IE, with the integral term zero'd out) even the slightest amount of integral will force the output unstable in such a way that the steering actuator is pushed to either the left or right extreme.</p> <p>Code:</p> <pre><code> private static void DoPID(object o) { // Bring the LED up to signify frame start BoardLED.Write(true); // Get IMU heading float currentHeading = (float)RazorIMU.Yaw; // We just got the IMU heading, so we need to calculate the time from the last correction to the heading read // *immediately*. The units don't so much matter, but we are converting Ticks to milliseconds int deltaTime = (int)((LastCorrectionTime - DateTime.Now.Ticks) / 10000); // Calculate error // (let's just assume CurrentHeading really is the current GPS heading, OK?) float error = (TargetHeading - currentHeading); LCD.Lines[0].Text = "Heading: "+ currentHeading.ToString("F2"); // We calculated the error, but we need to make sure the error is set so that we will be correcting in the // direction of least work. For example, if we are flying a heading of 2 degrees and the error is a few degrees // to the left of that ( IE, somewhere around 360) there will be a large error and the rover will try to turn all // the way around to correct, when it could just turn to the right a few degrees. // In short, we are adjusting for the fact that a compass heading wraps around in a circle instead of continuing // infinity on a line if (error &lt; -180) error = error + 360; else if (error &gt; 180) error = error - 360; // Add the error calculated in this frame to the running total SteadyError = SteadyError + (error * deltaTime); // We need to allow for a certain amount of tolerance. // If the abs(error) is less than the set amount, we will // set error to 0, effectively telling the equation that the // rover is perfectly on course. if (MyAbs(error) &lt; AllowError) error = 0; LCD.Lines[2].Text = "Error: " + error.ToString("F2"); // Calculate proportional term float proportional = Kp * error; // Calculate integral term float integral = Ki * (SteadyError * deltaTime); // Calculate derivative term float derivative = Kd * ((error - PrevError) / deltaTime); // Add them all together to get the correction delta // Set the steering servo to the correction Steering.Degree = 90 + proportional + integral + derivative; // We have applied the correction, so we need to *immediately* record the // absolute time for generation of deltaTime in the next frame LastCorrectionTime = DateTime.Now.Ticks; // At this point, the current PID frame is finished // ------------------------------------------------------------ // Now, we need to setup for the next PID frame and close out // The "current" error is now the previous error // (Remember, we are done with the current frame, so in // relative terms, the previous frame IS the "current" frame) PrevError = error; // Done BoardLED.Write(false); } </code></pre> <p>Does anyone have any idea why this is happening or how to fix it? </p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload