PID-regler integral-term verursacht extreme Instabilität

Habe ich einen PID-regler auf einem Roboter, der konzipiert ist, um den Roboter zu Steuern auf einen kompasskurs. Die PID-Korrektur wird neu berechnet/angewendet bei einer rate von 20 Hz.

Obwohl der PID-regler funktioniert gut im PD-Modus (DH, mit den integral-term zero D) sogar die geringste Höhe des integralen zwingen, den Ausgang instabil, so dass die Lenk-Aktuator betätigt wird, um entweder den linken oder rechten extremen.

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 < -180)
            error = error + 360;
        else if (error > 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) < 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);
    }

Hat jemand eine Idee warum das passiert oder wie man es beheben?

  • 120-Zeichen lange Zeilen? 80 (79) bitte.
  • Was rennst du dies auf? PID ist eine Echtzeit-Anwendung, sondern C# auf .Net Micro ist nicht Echtzeit-fähig, und die meisten Ziele haben keine FPU, also die floating-point-Umsetzung könnte il riet zu.
InformationsquelleAutor chris12892 | 2010-10-10
Schreibe einen Kommentar