Simple PID

Files at this revision

API Documentation at this revision

Comitter:
williampeers
Date:
Mon Jul 31 04:01:31 2017 +0000
Commit message:
Denver version

Changed in this revision

pid_controller.cpp Show annotated file Show diff for this revision Revisions of this file
pid_controller.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 3ce55a50a6b3 pid_controller.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pid_controller.cpp	Mon Jul 31 04:01:31 2017 +0000
@@ -0,0 +1,225 @@
+//*********************************************************************************
+// Arduino PID Library Version 1.0.1 Modified Version for C++
+// Platform Independent
+// 
+// Revision: 1.1
+// 
+// Description: The PID Controller module originally meant for Arduino made
+// platform independent. Some small bugs present in the original Arduino source
+// have been rectified as well.
+// 
+// For a detailed explanation of the theory behind this library, go to:
+// http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/
+// 
+// Revisions can be found here:
+// https://github.com/tcleg
+// 
+// Modified by: Trent Cleghorn , <trentoncleghorn@gmail.com>
+// 
+// Copyright (C) Brett Beauregard , <br3ttb@gmail.com>
+// 
+//                                 GPLv3 License
+// 
+// This program is free software: you can redistribute it and/or modify it under 
+// the terms of the GNU General Public License as published by the Free Software 
+// Foundation, either version 3 of the License, or (at your option) any later 
+// version.
+// 
+// This program is distributed in the hope that it will be useful, but WITHOUT ANY 
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
+// PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License along with 
+// this program.  If not, see <http://www.gnu.org/licenses/>.
+//*********************************************************************************
+
+//*********************************************************************************
+// Headers
+//*********************************************************************************
+#include "pid_controller.h"
+
+//*********************************************************************************
+// Macros and Globals
+//*********************************************************************************
+#define CONSTRAIN(x,lower,upper)    ((x)<(lower)?(lower):((x)>(upper)?(upper):(x)))
+
+//*********************************************************************************
+// Public Class Functions
+//*********************************************************************************
+
+PIDControl::
+PIDControl (float kp, float ki, float kd, float sampleTimeSeconds, float minOutput, 
+            float maxOutput, PIDMode mode, PIDDirection controllerDirection)     	
+{
+    controllerDirection = controllerDirection;
+    mode = mode;
+    iTerm = 0.0f;
+    input = 0.0f;
+    lastInput = 0.0f;
+    output = 0.0f;
+    setpoint = 0.0f;
+    
+    if(sampleTimeSeconds > 0.0f)
+    {
+        sampleTime = sampleTimeSeconds;
+    }
+    else
+    {
+        // If the passed parameter was incorrect, set to 1 second
+        sampleTime = 1.0f;
+    }
+    
+    PIDOutputLimitsSet(minOutput, maxOutput);
+    PIDTuningsSet(kp, ki, kd);
+}
+        
+bool PIDControl::
+PIDCompute() 
+{
+    float error, dInput;
+
+    if(mode == MANUAL)
+    {
+        return false;
+    }
+    
+    // The classic PID error term
+    error = setpoint - input;
+    
+    // Compute the integral term separately ahead of time
+    iTerm += alteredKi * error;
+    
+    // Constrain the integrator to make sure it does not exceed output bounds
+    iTerm = CONSTRAIN(iTerm, outMin, outMax);
+    
+    // Take the "derivative on measurement" instead of "derivative on error"
+    dInput = input - lastInput;
+    
+    // Run all the terms together to get the overall output
+    output = alteredKp * error + iTerm - alteredKd * dInput;
+    
+    // Bound the output
+    output = CONSTRAIN(output, outMin, outMax);
+    
+    // Make the current input the former input
+    lastInput = input;
+    
+    return true;
+}
+     
+void PIDControl::
+PIDModeSet(PIDMode mode)                                                                                                                                       
+{
+    // If the mode changed from MANUAL to AUTOMATIC
+    if(mode != mode && mode == AUTOMATIC)
+    {
+        // Initialize a few PID parameters to new values
+        iTerm = output;
+        lastInput = input;
+        
+        // Constrain the integrator to make sure it does not exceed output bounds
+        iTerm = CONSTRAIN(iTerm, outMin, outMax);
+    }
+    
+    mode = mode;
+}
+
+void PIDControl::
+PIDOutputLimitsSet(float min, float max) 							  							  
+{
+    // Check if the parameters are valid
+    if(min >= max)
+    {
+        return;
+    }
+    
+    // Save the parameters
+    outMin = min;
+    outMax = max;
+    
+    // If in automatic, apply the new constraints
+    if(mode == AUTOMATIC)
+    {
+        output = CONSTRAIN(output, min, max);
+        iTerm  = CONSTRAIN(iTerm,  min, max);
+    }
+}
+
+void PIDControl::
+PIDTuningsSet(float kp, float ki, float kd)         	                                         
+{
+    // Check if the parameters are valid
+    if(kp < 0.0f || ki < 0.0f || kd < 0.0f)
+    {
+        return;
+    }
+    
+    // Save the parameters for displaying purposes
+    dispKp = kp;
+    dispKi = ki;
+    dispKd = kd;
+    
+    // Alter the parameters for PID
+    alteredKp = kp;
+    alteredKi = ki * sampleTime;
+    alteredKd = kd / sampleTime;
+    
+    // Apply reverse direction to the altered values if necessary
+    if(controllerDirection == REVERSE)
+    {
+        alteredKp = -(alteredKp);
+        alteredKi = -(alteredKi);
+        alteredKd = -(alteredKd);
+    }
+}
+
+void PIDControl::
+PIDTuningKpSet(float kp)
+{
+    PIDTuningsSet(kp, dispKi, dispKd);
+}
+
+void PIDControl::
+PIDTuningKiSet(float ki)
+{
+    PIDTuningsSet(dispKp, ki, dispKd);
+}
+
+void PIDControl::
+PIDTuningKdSet(float kd)
+{
+    PIDTuningsSet(dispKp, dispKi, kd);
+}
+
+void PIDControl::
+PIDControllerDirectionSet(PIDDirection controllerDirection)	  									  									  									  
+{
+    // If in automatic mode and the controller's sense of direction is reversed
+    if(mode == AUTOMATIC && controllerDirection == REVERSE)
+    {
+        // Reverse sense of direction of PID gain constants
+        alteredKp = -(alteredKp);
+        alteredKi = -(alteredKi);
+        alteredKd = -(alteredKd);
+    }
+    
+    controllerDirection = controllerDirection;
+}
+
+void PIDControl::
+PIDSampleTimeSet(float sampleTimeSeconds)                                                       									  									  									   
+{
+    float ratio;
+
+    if(sampleTimeSeconds > 0.0f)
+    {
+        // Find the ratio of change and apply to the altered values
+        ratio = sampleTimeSeconds / sampleTime;
+        alteredKi *= ratio;
+        alteredKd /= ratio;
+        
+        // Save the new sampling time
+        sampleTime = sampleTimeSeconds;
+    }
+}
+
diff -r 000000000000 -r 3ce55a50a6b3 pid_controller.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pid_controller.h	Mon Jul 31 04:01:31 2017 +0000
@@ -0,0 +1,383 @@
+//*********************************************************************************
+// Arduino PID Library Version 1.0.1 Modified Version for C++
+// Platform Independent
+// 
+// Revision: 1.1
+// 
+// Description: The PID Controller module originally meant for Arduino made
+// platform independent. Some small bugs present in the original Arduino source
+// have been rectified as well.
+// 
+// For a detailed explanation of the theory behind this library, go to:
+// http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/
+// 
+// Revisions can be found here:
+// https://github.com/tcleg
+// 
+// Modified by: Trent Cleghorn , <trentoncleghorn@gmail.com>
+// 
+// Copyright (C) Brett Beauregard , <br3ttb@gmail.com>
+// 
+//                                 GPLv3 License
+// 
+// This program is free software: you can redistribute it and/or modify it under 
+// the terms of the GNU General Public License as published by the Free Software 
+// Foundation, either version 3 of the License, or (at your option) any later 
+// version.
+// 
+// This program is distributed in the hope that it will be useful, but WITHOUT ANY 
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
+// PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License along with 
+// this program.  If not, see <http://www.gnu.org/licenses/>.
+//*********************************************************************************
+
+// 
+// Header Guard
+// 
+#ifndef PID_CONTROLLER_H
+#define PID_CONTROLLER_H
+
+//*********************************************************************************
+// Headers
+//*********************************************************************************
+#include <stdint.h>
+#include <stdbool.h>
+
+//*********************************************************************************
+// Macros and Globals
+//*********************************************************************************
+
+typedef enum
+{
+    MANUAL,
+    AUTOMATIC
+}
+PIDMode;
+
+typedef enum
+{
+    DIRECT,
+    REVERSE
+}
+PIDDirection;
+
+//*********************************************************************************
+// Class
+//*********************************************************************************
+
+class
+PIDControl
+{
+    public:
+        // 
+        // Constructor
+        // Description:
+        //      Initializes the PIDControl instantiation. This should be called at 
+        //      least once before any other PID functions are called on the 
+        //      instantiation.
+        // Parameters:
+        //      kp - Positive P gain constant value.
+        //      ki - Positive I gain constant value.
+        //      kd - Positive D gain constant value.
+        //      sampleTimeSeconds - Interval in seconds on which PIDCompute will be 
+        //          called.
+        //      minOutput - Constrain PID output to this minimum value.
+        //      maxOutput - Constrain PID output to this maximum value.
+        //      mode - Tells how the controller should respond if the user has 
+        //          taken over manual control or not.
+        //          MANUAL:    PID controller is off. User can manually control the 
+        //                     output.
+        //          AUTOMATIC: PID controller is on. PID controller controls the 
+        //                     output.
+        //      controllerDirection - The sense of direction of the controller
+        //          DIRECT:  A positive setpoint gives a positive output.
+        //          REVERSE: A positive setpoint gives a negative output.
+        // Returns:
+        //      Nothing.
+        // 
+        PIDControl(float kp, float ki, float kd, float sampleTimeSeconds, 
+                   float minOutput, float maxOutput, PIDMode mode, 
+                   PIDDirection controllerDirection);     	
+        
+        // 
+        // PID Compute
+        // Description:
+        //      Should be called on a regular interval defined by sampleTimeSeconds.
+        //      Typically, PIDSetpointSet and PIDInputSet should be called 
+        //      immediately before PIDCompute.
+        // Parameters:
+        //      None.
+        // Returns:
+        //      True if in AUTOMATIC. False if in MANUAL.
+        //                     
+        bool PIDCompute(); 
+        
+        // 
+        // PID Mode Set
+        // Description:
+        //      Sets the PID controller to a new mode. Tells how the controller 
+        //      should respond if the user has taken over manual control or not.
+        // Parameters:
+        //      mode - 
+        //          MANUAL:    PID controller is off. User can manually control the 
+        //                     output.
+        //          AUTOMATIC: PID controller is on. PID controller controls the 
+        //                     output.
+        // Returns:
+        //      Nothing.
+        //              
+        void PIDModeSet(PIDMode mode);                                                                                                                                       
+        
+        // 
+        // PID Output Limits Set
+        // Description:
+        //      Sets the new output limits. The new limits are applied to the PID
+        //      immediately.
+        // Parameters:
+        //      min - Constrain PID output to this minimum value.
+        //      max - Constrain PID output to this maximum value.
+        // Returns:
+        //      Nothing.
+        // 
+        void PIDOutputLimitsSet(float min, float max); 							  							  
+        
+        // 
+        // PID Tunings Set
+        // Description:
+        //      Sets the new gain constant values.
+        // Parameters:
+        //      kp - Positive P gain constant value.
+        //      ki - Positive I gain constant value.
+        //      kd - Positive D gain constant value.
+        // Returns:
+        //      Nothing.
+        // 
+        void PIDTuningsSet(float kp, float ki, float kd);         	                                         
+        
+        // 
+        // PID Tuning Gain Constant P Set
+        // Description:
+        //      Sets the proportional gain constant value.
+        // Parameters:
+        //      kp - Positive P gain constant value.
+        // Returns:
+        //      Nothing.
+        // 
+        void PIDTuningKpSet(float kp);
+        
+        // 
+        // PID Tuning Gain Constant I Set
+        // Description:
+        //      Sets the proportional gain constant value.
+        // Parameters:
+        //      ki - Positive I gain constant value.
+        // Returns:
+        //      Nothing.
+        // 
+        void PIDTuningKiSet(float ki);
+        
+        // 
+        // PID Tuning Gain Constant D Set
+        // Description:
+        //      Sets the proportional gain constant value.
+        // Parameters:
+        //      kd - Positive D gain constant value.
+        // Returns:
+        //      Nothing.
+        // 
+        void PIDTuningKdSet(float kd);
+        
+        // 
+        // PID Controller Direction Set
+        // Description:
+        //      Sets the new controller direction.
+        // Parameters:
+        //      controllerDirection - The sense of direction of the controller
+        //          DIRECT:  A positive setpoint gives a positive output
+        //          REVERSE: A positive setpoint gives a negative output
+        // Returns:
+        //      Nothing.
+        // 
+        void PIDControllerDirectionSet(PIDDirection controllerDirection);	  									  									  									  
+        
+        // 
+        // PID Sample Time Set
+        // Description:
+        //      Sets the new sampling time (in seconds).
+        // Parameters:
+        //      sampleTimeSeconds - Interval in seconds on which PIDCompute will be 
+        //          called.
+        // Returns:
+        //      Nothing.
+        // 
+        void PIDSampleTimeSet(float sampleTimeSeconds);                                                       									  									  									   
+        
+        // 
+        // PID Setpoint Set
+        // Description:
+        //      Alters the setpoint the PID controller will try to achieve.
+        // Parameters:
+        //      setpoint - The desired setpoint the PID controller will try to 
+        //          obtain.
+        // Returns:
+        //      Nothing.
+        // 
+        inline void PIDSetpointSet(float setpoint) { this->setpoint = setpoint; }
+        
+        // 
+        // PID Input Set
+        // Description:
+        //      Should be called before calling PIDCompute so the PID controller 
+        //      will have an updated input value to work with.
+        // Parameters:
+        //      input - The value the controller will work with.
+        // Returns:
+        //      Nothing.
+        // 
+        inline void PIDInputSet(float input) { this->input = input; }
+        
+        // 
+        // PID Output Get
+        // Description:
+        //      Typically, this function is called after PIDCompute in order to
+        //      retrieve the output of the controller.
+        // Parameters:
+        //      None.
+        // Returns:
+        //      The output of the specific PID controller.
+        // 
+        inline float PIDOutputGet() { return this->output; }
+        
+        // 
+        // PID Proportional Gain Constant Get
+        // Description:
+        //      Returns the proportional gain constant value the particular
+        //      controller is set to.
+        // Parameters:
+        //      None.
+        // Returns:
+        //      The proportional gain constant.
+        // 
+        inline float PIDKpGet() { return this->dispKp; }						  
+        
+        // 
+        // PID Integral Gain Constant Get
+        // Description:
+        //      Returns the integral gain constant value the particular
+        //      controller is set to.
+        // Parameters:
+        //      None.
+        // Returns:
+        //      The integral gain constant.
+        // 
+        inline float PIDKiGet() { return this->dispKi; }						  
+        
+        // 
+        // PID Derivative Gain Constant Get
+        // Description:
+        //      Returns the derivative gain constant value the particular
+        //      controller is set to.
+        // Parameters:
+        //      None.
+        // Returns:
+        //      The derivative gain constant.
+        // 
+        inline float PIDKdGet() { return this->dispKd; }						  
+        
+        // 
+        // PID Mode Get
+        // Description:
+        //      Returns the mode the particular controller is set to.
+        // Parameters:
+        //      None.
+        // Returns:
+        //      MANUAL or AUTOMATIC depending on what the user set the 
+        //      controller to.
+        // 
+        inline PIDMode PIDModeGet() { return this->mode; }						  
+        
+        // 
+        // PID Direction Get
+        // Description:
+        //      Returns the direction the particular controller is set to.
+        // Parameters:
+        //      None.
+        // Returns:
+        //      DIRECT or REVERSE depending on what the user set the
+        //      controller to.
+        // 
+        inline PIDDirection PIDDirectionGet() { return this->controllerDirection; }
+        
+    private:
+        // 
+        // Input to the PID Controller
+        // 
+        float input;
+        
+        // 
+        // Previous input to the PID Controller
+        // 
+        float lastInput;
+        
+        // 
+        // Output of the PID Controller
+        // 
+        float output;
+        
+        // 
+        // Gain constant values that were passed by the user
+        // These are for display purposes
+        // 
+        float dispKp;
+        float dispKi;
+        float dispKd;
+        
+        // 
+        // Gain constant values that the controller alters for
+        // its own use
+        // 
+        float alteredKp;
+        float alteredKi;
+        float alteredKd;
+        
+        // 
+        // The Integral Term
+        // 
+        float iTerm;
+        
+        // 
+        // The interval (in seconds) on which the PID controller
+        // will be called
+        // 
+        float sampleTime;
+        
+        // 
+        // The values that the output will be constrained to
+        // 
+        float outMin;
+        float outMax;
+        
+        // 
+        // The user chosen operating point
+        // 
+        float setpoint;
+        
+        // 
+        // The sense of direction of the controller
+        // DIRECT:  A positive setpoint gives a positive output
+        // REVERSE: A positive setpoint gives a negative output
+        // 
+        PIDDirection controllerDirection;
+        
+        // 
+        // Tells how the controller should respond if the user has
+        // taken over manual control or not
+        // MANUAL:    PID controller is off.
+        // AUTOMATIC: PID controller is on.
+        // 
+        PIDMode mode;
+};
+
+#endif // PID_CONTROLLER_H
\ No newline at end of file