Subversion Repositories HomeAutomation

Rev

Rev 2277 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /**********************************************************************************************
  2.  * C PID Library - Version 1.0.1
  3.  * modified by Linus Lundin <linus.lundin@gmail.com (ported c to be used with AVR-GCC)
  4.  * originally by Brett Beauregard <br3ttb@gmail.com> brettbeauregard.com
  5.  *
  6.  * This Library is licensed under a GPLv3 License
  7.  **********************************************************************************************/
  8.  
  9. #include "PID_v1.h"
  10. #include <drivers/timer/timer.h>
  11. void PID_Initialize(PidType* pid);
  12. void PID_Limit(PidType* pid, FloatType *var);
  13.  
  14. /*Constructor (...)*********************************************************
  15.  *    The parameters specified here are those for for which we can't set up
  16.  *    reliable defaults, so we need to have the user set them.
  17.  ***************************************************************************/
  18. void PID_init(PidType* pid, FloatType* Input, FloatType* Output, FloatType* Setpoint, FloatType Kp, FloatType Ki, FloatType Kd,
  19.     PidDirectionType ControllerDirection) {
  20.  
  21.  
  22.   PID_SetOutputLimits(pid, 0, 0xffff);
  23.  
  24.   //default Controller Sample Time is 0.1 seconds
  25.   pid->SampleTime = 100;
  26.  
  27.   PID_SetControllerDirection(pid, ControllerDirection);
  28.   PID_SetTunings(pid, Kp, Ki, Kd);
  29.  
  30.   pid->lastTime = Timer_GetTicks() - pid->SampleTime;
  31.   pid->mode = PID_Mode_Manual;
  32.   pid->myInput = Input;
  33.   pid->myOutput = Output;
  34.   pid->mySetpoint = Setpoint;
  35.   pid->MaxKd = 10.0;
  36. }
  37.  
  38. /* Compute() **********************************************************************
  39.  *   This, as they say, is where the magic happens.  this function should be called
  40.  *   every time "void loop()" executes.  the function will decide for itself whether a new
  41.  *   pid Output needs to be computed.  returns true when the output is computed,
  42.  *   false when nothing has been done.
  43.  **********************************************************************************/
  44. bool PID_Compute(PidType* pid)
  45. {
  46.   if (pid->mode == PID_Mode_Manual)
  47.   {
  48.     return false;
  49.   }
  50.   unsigned long now = Timer_GetTicks();
  51.   unsigned long timeChange = (now - pid->lastTime);
  52.   if (timeChange >= pid->SampleTime)
  53.   {
  54.     // Compute all the working error variables
  55.     FloatType input = *pid->myInput;
  56.  
  57.     // compute pid_t Output
  58.     FloatType error = *pid->mySetpoint - input;
  59.     FloatType dInput = (input - pid->lastInput);
  60.  
  61.     pid->PTerm = pid->kp * error;
  62.     pid->ITerm += ( pid->ki * error );
  63.     PID_Limit(pid, &pid->ITerm);
  64.     pid->DTerm = - pid->kd * dInput / ( pid->MaxKd < MAX_KD_MIN ? 1.0 : 1.0 + pid->kd / pid->MaxKd );
  65.  
  66.     // compute PID Output
  67.     FloatType output = pid->PTerm + pid->ITerm + pid->DTerm;
  68.     PID_Limit(pid, &output);
  69.     *pid->myOutput = output;
  70.  
  71.     // remember some variables for next time
  72.     pid->lastInput = input;
  73.     pid->lastTime = now;
  74.     return true;
  75.   }
  76.   else
  77.   {
  78.     return false;
  79.   }
  80. }
  81.  
  82. /* Limit(...)******************************************************************
  83.  * bound supplied variable to (outMin, outMax)
  84.  ******************************************************************************/
  85. void PID_Limit(PidType* pid, FloatType *var)
  86. {
  87.   if (*var < pid->outMin)
  88.   {
  89.     *var = pid->outMin;
  90.   }
  91.   else if (*var > pid->outMax)
  92.   {
  93.     *var = pid->outMax;
  94.   }
  95. }
  96.  
  97. /* SetTunings(...)*************************************************************
  98.  * This function allows the controller's dynamic performance to be adjusted.
  99.  * it's called automatically from the constructor, but tunings can also
  100.  * be adjusted on the fly during normal operation
  101.  ******************************************************************************/
  102. void PID_SetTunings(PidType* pid, FloatType Kp, FloatType Ki, FloatType Kd)
  103. {
  104.   if ((Kp < 0.0) || (Ki < 0.0) || (Kd < 0.0))
  105.   {
  106.     return;
  107.   }
  108.  
  109.   pid->dispKp = Kp;
  110.   pid->dispKi = Ki;
  111.   pid->dispKd = Kd;
  112.  
  113.   FloatType SampleTimeInSec = ((FloatType) pid->SampleTime) / 1000.0;
  114.   pid->kp = Kp;
  115.   pid->ki = Ki * SampleTimeInSec;
  116.   pid->kd = Kd / SampleTimeInSec;
  117.  
  118.   if (pid->controllerDirection == PID_Direction_Reverse) {
  119.     pid->kp = (0.0 - pid->kp);
  120.     pid->ki = (0.0 - pid->ki);
  121.     pid->kd = (0.0 - pid->kd);
  122.   }
  123. }
  124.  
  125. /* SetSampleTime(...) *********************************************************
  126.  * sets the period, in Milliseconds, at which the calculation is performed 
  127.  ******************************************************************************/
  128. void PID_SetSampleTime(PidType* pid, uint32_t NewSampleTime)
  129. {
  130.   if (NewSampleTime > 0) {
  131.     FloatType ratio = (FloatType) NewSampleTime / (FloatType) pid->SampleTime;
  132.     pid->ki *= ratio;
  133.     pid->kd /= ratio;
  134.     pid->SampleTime = (uint32_t) NewSampleTime;
  135.   }
  136. }
  137.  
  138. /* SetOutputLimits(...)****************************************************
  139.  *     This function will be used far more often than SetInputLimits.  while
  140.  *  the input to the controller will generally be in the 0-1023 range (which is
  141.  *  the default already,)  the output will be a little different.  maybe they'll
  142.  *  be doing a time window and will need 0-8000 or something.  or maybe they'll
  143.  *  want to clamp it from 0-125.  who knows.  at any rate, that can all be done
  144.  *  here.
  145.  **************************************************************************/
  146. void PID_SetOutputLimits(PidType* pid, FloatType newMin, FloatType newMax) {
  147.   if (newMin >= newMax) {
  148.     return;  
  149.   }
  150.   pid->outMin = newMin;
  151.   pid->outMax = newMax;
  152.  
  153.   if (pid->mode == PID_Mode_Automatic)
  154.   {
  155.     PID_Limit(pid, pid->myOutput);
  156.     PID_Limit(pid, &pid->ITerm);
  157.   }
  158. }
  159.  
  160. /* SetMode(...)****************************************************************
  161.  * Allows the controller Mode to be set to manual (0) or Automatic (non-zero)
  162.  * when the transition from manual to auto occurs, the controller is
  163.  * automatically initialized
  164.  ******************************************************************************/
  165. void PID_SetMode(PidType* pid, PidModeType newMode)
  166. {
  167.   if (newMode != pid->mode)
  168.   {
  169.     // just changed mode
  170.     PID_Initialize(pid);
  171.     pid->mode = newMode;
  172.   }
  173. }
  174.  
  175. /* Initialize()****************************************************************
  176.  *  does all the things that need to happen to ensure a bumpless transfer
  177.  *  from manual to automatic mode.
  178.  ******************************************************************************/
  179. void PID_Initialize(PidType* pid)
  180. {
  181.   pid->ITerm = *pid->myOutput;
  182.   pid->lastInput = *pid->myInput;
  183.   PID_Limit(pid, &pid->ITerm);
  184. }
  185.  
  186. /* SetControllerDirection(...)*************************************************
  187.  * The PID will either be connected to a DIRECT acting process (+Output leads
  188.  * to +Input) or a REVERSE acting process(+Output leads to -Input.)  we need to
  189.  * know which one, because otherwise we may increase the output when we should
  190.  * be decreasing.  This is called from the constructor.
  191.  ******************************************************************************/
  192. void PID_SetControllerDirection(PidType* pid, PidDirectionType newDirection)
  193. {
  194.   if ((pid->mode == PID_Mode_Automatic) && (newDirection != pid->controllerDirection))
  195.   {
  196.     pid->kp = (0.0 - pid->kp);
  197.     pid->ki = (0.0 - pid->ki);
  198.     pid->kd = (0.0 - pid->kd);
  199.   }  
  200.   pid->controllerDirection = newDirection;
  201. }
  202.  
  203. /* pid_set_max_Kd(...)*********************************************************
  204.  * set maximum derivative gain
  205.  * Default 0 means no maximum.
  206.  ******************************************************************************/
  207. void PID_SetMaxKd(PidType* pid, FloatType newMaxKd )
  208. {
  209.   if ( newMaxKd < MAX_KD_MIN )
  210.   {
  211.     // no limit to Kd
  212.     newMaxKd = 0.0;
  213.   }
  214.   pid->MaxKd = newMaxKd;
  215. }  
  216.  
  217. /* Status Functions************************************************************
  218.  * Just because you set the Kp=-1 doesn't mean it actually happened.  these
  219.  * functions query the internal state of the PID.  they're here for display
  220.  * purposes.  this are the functions the PID Front-end uses for example
  221.  ******************************************************************************/
  222. FloatType PID_GetKp(PidType* pid) {
  223.   return pid->dispKp;
  224. }
  225. FloatType PID_GetKi(PidType* pid) {
  226.   return pid->dispKi;
  227. }
  228. FloatType PID_GetKd(PidType* pid) {
  229.   return pid->dispKd;
  230. }
  231. FloatType PID_GetMin(PidType* pid) {
  232.   return pid->outMin;
  233. }
  234. FloatType PID_GetMax(PidType* pid) {
  235.   return pid->outMax;
  236. }
  237.  
  238. PidModeType PID_GetMode(PidType* pid) {
  239.   return pid->mode;
  240. }
  241.  
  242. PidDirectionType PID_GetDirection(PidType* pid) {
  243.   return pid->controllerDirection;
  244. }
  245.  
  246. FloatType PID_GetPTerm(PidType* pid)
  247. {
  248.   return  pid->PTerm;
  249. }
  250.  
  251. FloatType PID_GetITerm(PidType* pid)
  252. {
  253.   return  pid->ITerm;
  254. }
  255.  
  256. FloatType PID_GetDTerm(PidType* pid)
  257. {
  258.   return  pid->DTerm;
  259. }
  260.  
  261.