This is a copy of the Reference Standard PID controller ala controlguru.com

Fork of PID by FRDM-K64F Code Share

Revision:
2:55bf0f813bb4
Parent:
1:117e0c36eb22
Child:
3:316f974b7f98
diff -r 117e0c36eb22 -r 55bf0f813bb4 PID.cpp
--- a/PID.cpp	Mon Jan 25 22:29:38 2016 +0000
+++ b/PID.cpp	Wed Jan 27 21:32:11 2016 +0000
@@ -1,291 +1,337 @@
 /**
-* Includes
-*/
+ * @author Aaron Berk
+ *
+ * @section LICENSE
+ *
+ * Copyright (c) 2010 ARM Limited
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @section DESCRIPTION
+ * 
+ * A PID controller is a widely used feedback controller commonly found in
+ * industry.
+ *
+ * This library is a port of Brett Beauregard's Arduino PID library:
+ *
+ *  http://www.arduino.cc/playground/Code/PIDLibrary
+ *
+ * The wikipedia article on PID controllers is a good place to start on
+ * understanding how they work:
+ *
+ *  http://en.wikipedia.org/wiki/PID_controller
+ *
+ * For a clear and elegant explanation of how to implement and tune a
+ * controller, the controlguru website by Douglas J. Cooper (who also happened
+ * to be Brett's controls professor) is an excellent reference:
+ *
+ *  http://www.controlguru.com/
+ */
+ 
+/**
+ * Includes
+ */
 #include "PID.h"
-
+ 
 PID::PID(float Kc, float tauI, float tauD, float interval) {
-
+ 
     usingFeedForward = false;
-    inAuto = false;
-
-    //Default the limits to the full range of I/O.
-    //Make sure to set these to more appropriate limits for your application.
-    setInputLimits(0.0, 100.0);
-    setOutputLimits(0.0,100.0);
-
+    inAuto           = false;
+ 
+    //Default the limits to the full range of I/O: 3.3V
+    //Make sure to set these to more appropriate limits for
+    //your application.
+    setInputLimits(0.0, 3.3);
+    setOutputLimits(0.0, 3.3);
+ 
     tSample_ = interval;
-
+ 
     setTunings(Kc, tauI, tauD);
-
-    setPoint_ = 0.0;
-    processVariable_ = 0.0;
-    prevProcessVariable_ = 0.0;
-    controllerOutput_ = 0.0;
+ 
+    setPoint_             = 0.0;
+    processVariable_      = 0.0;
+    prevProcessVariable_  = 0.0;
+    controllerOutput_     = 0.0;
     prevControllerOutput_ = 0.0;
-
+ 
     accError_ = 0.0;
-    bias_ = 0.0;
-
+    bias_     = 0.0;
+    
     realOutput_ = 0.0;
-
+ 
 }
-
+ 
 void PID::setInputLimits(float inMin, float inMax) {
-
+ 
     //Make sure we haven't been given impossible values.
     if (inMin >= inMax) {
         return;
     }
-
+ 
     //Rescale the working variables to reflect the changes.
     prevProcessVariable_ *= (inMax - inMin) / inSpan_;
-    accError_ *= (inMax - inMin) / inSpan_;
-
+    accError_            *= (inMax - inMin) / inSpan_;
+ 
     //Make sure the working variables are within the new limits.
     if (prevProcessVariable_ > 1) {
         prevProcessVariable_ = 1;
-    }
-    else if (prevProcessVariable_ < 0) {
+    } else if (prevProcessVariable_ < 0) {
         prevProcessVariable_ = 0;
     }
-
-    inMin_ = inMin;
-    inMax_ = inMax;
+ 
+    inMin_  = inMin;
+    inMax_  = inMax;
     inSpan_ = inMax - inMin;
-
+ 
 }
-
+ 
 void PID::setOutputLimits(float outMin, float outMax) {
-
+ 
     //Make sure we haven't been given impossible values.
     if (outMin >= outMax) {
         return;
     }
-
+ 
     //Rescale the working variables to reflect the changes.
     prevControllerOutput_ *= (outMax - outMin) / outSpan_;
-
+ 
     //Make sure the working variables are within the new limits.
     if (prevControllerOutput_ > 1) {
         prevControllerOutput_ = 1;
-    }
-    else if (prevControllerOutput_ < 0) {
+    } else if (prevControllerOutput_ < 0) {
         prevControllerOutput_ = 0;
     }
-
-    outMin_ = outMin;
-    outMax_ = outMax;
+ 
+    outMin_  = outMin;
+    outMax_  = outMax;
     outSpan_ = outMax - outMin;
-
+ 
 }
-
+ 
 void PID::setTunings(float Kc, float tauI, float tauD) {
-
+ 
     //Verify that the tunings make sense.
     if (Kc == 0.0 || tauI < 0.0 || tauD < 0.0) {
         return;
     }
-
+ 
     //Store raw values to hand back to user on request.
     pParam_ = Kc;
     iParam_ = tauI;
     dParam_ = tauD;
-
+ 
     float tempTauR;
-
+ 
     if (tauI == 0.0) {
         tempTauR = 0.0;
-    }
-    else {
+    } else {
         tempTauR = (1.0 / tauI) * tSample_;
     }
-
+ 
     //For "bumpless transfer" we need to rescale the accumulated error.
-    //if (inAuto) {
-        //if (tempTauR == 0.0) {
-            //accError_ = 0.0;
-        //}
-        //else {
+    if (inAuto) {
+        if (tempTauR == 0.0) {
+            accError_ = 0.0;
+        } else {
             accError_ *= (Kc_ * tauR_) / (Kc * tempTauR);
-        //}
-    //}
-
-    Kc_ = Kc;
+        }
+    }
+ 
+    Kc_   = Kc;
     tauR_ = tempTauR;
     tauD_ = tauD / tSample_;
-
+ 
 }
-
+ 
 void PID::reset(void) {
-
+ 
     float scaledBias = 0.0;
-
+ 
     if (usingFeedForward) {
         scaledBias = (bias_ - outMin_) / outSpan_;
-    }
-    else {
+    } else {
         scaledBias = (realOutput_ - outMin_) / outSpan_;
     }
-
+ 
     prevControllerOutput_ = scaledBias;
-    prevProcessVariable_ = (processVariable_ - inMin_) / inSpan_;
-
+    prevProcessVariable_  = (processVariable_ - inMin_) / inSpan_;
+ 
     //Clear any error in the integral.
     accError_ = 0;
-
+ 
 }
-
+ 
 void PID::setMode(int mode) {
-
+ 
     //We were in manual, and we just got set to auto.
     //Reset the controller internals.
     if (mode != 0 && !inAuto) {
         reset();
     }
-
+ 
     inAuto = (mode != 0);
-
+ 
 }
-
+ 
 void PID::setInterval(float interval) {
-
+ 
     if (interval > 0) {
         //Convert the time-based tunings to reflect this change.
-        tauR_ *= (interval / tSample_);
+        tauR_     *= (interval / tSample_);
         accError_ *= (tSample_ / interval);
-        tauD_ *= (interval / tSample_);
-        tSample_ = interval;
+        tauD_     *= (interval / tSample_);
+        tSample_   = interval;
     }
-
+ 
 }
-
+ 
 void PID::setSetPoint(float sp) {
-
+ 
     setPoint_ = sp;
-
+ 
 }
-
+ 
 void PID::setProcessValue(float pv) {
-
+ 
     processVariable_ = pv;
-
+ 
 }
-
+ 
 void PID::setBias(float bias){
-
+ 
     bias_ = bias;
     usingFeedForward = 1;
-
+ 
 }
-
-float PID::compute(float pv,  float sp) {
-
-    //enregistrer variables dans var interne
-    processVariable_ = pv; //ce que l'on mesure
-    setPoint_ = sp;  // ce que l'on veut atteindre
-
+ 
+float PID::compute() {
+ 
     //Pull in the input and setpoint, and scale them into percent span.
     float scaledPV = (processVariable_ - inMin_) / inSpan_;
-
+ 
     if (scaledPV > 1.0) {
         scaledPV = 1.0;
-    }
-    else if (scaledPV < 0.0) {
+    } else if (scaledPV < 0.0) {
         scaledPV = 0.0;
     }
-
+ 
     float scaledSP = (setPoint_ - inMin_) / inSpan_;
     if (scaledSP > 1.0) {
         scaledSP = 1;
-    }
-    else if (scaledSP < 0.0) {
+    } else if (scaledSP < 0.0) {
         scaledSP = 0;
     }
-
+ 
     float error = scaledSP - scaledPV;
-
+ 
     //Check and see if the output is pegged at a limit and only
     //integrate if it is not. This is to prevent reset-windup.
     if (!(prevControllerOutput_ >= 1 && error > 0) && !(prevControllerOutput_ <= 0 && error < 0)) {
         accError_ += error;
     }
-
+ 
     //Compute the current slope of the input signal.
     float dMeas = (scaledPV - prevProcessVariable_) / tSample_;
-    //float dMeas = (scaledPV - prevProcessVariable_);
-
+ 
     float scaledBias = 0.0;
-
+ 
     if (usingFeedForward) {
         scaledBias = (bias_ - outMin_) / outSpan_;
     }
-
+ 
     //Perform the PID calculation.
     controllerOutput_ = scaledBias + Kc_ * (error + (tauR_ * accError_) - (tauD_ * dMeas));
-    //controllerOutput_ = Kc_ * error + tauR_ * accError_ + tauD_ * dMeas;
-
+ 
     //Make sure the computed output is within output constraints.
     if (controllerOutput_ < 0.0) {
         controllerOutput_ = 0.0;
-    }
-    else if (controllerOutput_ > 1.0) {
+    } else if (controllerOutput_ > 1.0) {
         controllerOutput_ = 1.0;
     }
-
+ 
     //Remember this output for the windup check next time.
     prevControllerOutput_ = controllerOutput_;
     //Remember the input for the derivative calculation next time.
-    prevProcessVariable_ = scaledPV;
-
+    prevProcessVariable_  = scaledPV;
+ 
     //Scale the output from percent span back out to a real world number.
     return ((controllerOutput_ * outSpan_) + outMin_);
-
+ 
 }
-
+ 
 float PID::getInMin() {
-
+ 
     return inMin_;
-
+ 
 }
-
+ 
 float PID::getInMax() {
-
+ 
     return inMax_;
-
+ 
 }
-
+ 
 float PID::getOutMin() {
-
+ 
     return outMin_;
-
+ 
+}
+ 
+float PID::getOutMax() {
+ 
+    return outMax_;
+ 
+}
+ 
+float PID::getInterval() {
+ 
+    return tSample_;
+ 
 }
-
-float PID::getOutMax() {
-
-    return outMax_;
+ 
+float PID::getPParam() {
+ 
+    return pParam_;
+ 
+}
+ 
+float PID::getIParam() {
+ 
+    return iParam_;
+ 
+}
+ 
+float PID::getDParam() {
+ 
+    return dParam_;
+ 
+}
+ 
+            
 
-}
-
-float PID::getInterval() {
-
-    return tSample_;
 
-}
+            
 
-float PID::getPParam() {
-
-    return pParam_;
 
-}
+    
 
-float PID::getIParam() {
-
-    return iParam_;
 
-}
 
-float PID::getDParam() {
 
-    return dParam_;
 
-}
\ No newline at end of file