~gabe/flashlight-firmware/anduril2

« back to all changes in this revision

Viewing changes to loneoceans/gxb172/PID_v1.cpp

  • Committer: Selene Scriven
  • Date: 2019-09-18 22:18:49 UTC
  • mfrom: (188.4.19 trunk)
  • Revision ID: bzr@toykeeper.net-20190918221849-7h4hcvl07ea3b6g6
merged updates from trunk, including gcc7/8/9 compatibility

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**********************************************************************************************
 
2
 * Arduino PID Library - Version 1.2.1
 
3
 * by Brett Beauregard <br3ttb@gmail.com> brettbeauregard.com
 
4
 *
 
5
 * This Library is licensed under the MIT License
 
6
 **********************************************************************************************/
 
7
 
 
8
#if ARDUINO >= 100
 
9
  #include "Arduino.h"
 
10
#else
 
11
  #include "WProgram.h"
 
12
#endif
 
13
 
 
14
#include "PID_v1.h"
 
15
 
 
16
/*Constructor (...)*********************************************************
 
17
 *    The parameters specified here are those for for which we can't set up
 
18
 *    reliable defaults, so we need to have the user set them.
 
19
 ***************************************************************************/
 
20
PID::PID(double* Input, double* Output, double* Setpoint,
 
21
        double Kp, double Ki, double Kd, int POn, int ControllerDirection)
 
22
{
 
23
    myOutput = Output;
 
24
    myInput = Input;
 
25
    mySetpoint = Setpoint;
 
26
    inAuto = false;
 
27
 
 
28
    PID::SetOutputLimits(0, 255);                               //default output limit corresponds to
 
29
                                                                                                //the arduino pwm limits
 
30
 
 
31
    SampleTime = 100;                                                   //default Controller Sample Time is 0.1 seconds
 
32
 
 
33
    PID::SetControllerDirection(ControllerDirection);
 
34
    PID::SetTunings(Kp, Ki, Kd, POn);
 
35
 
 
36
    lastTime = millis()-SampleTime;
 
37
}
 
38
 
 
39
/*Constructor (...)*********************************************************
 
40
 *    To allow backwards compatability for v1.1, or for people that just want
 
41
 *    to use Proportional on Error without explicitly saying so
 
42
 ***************************************************************************/
 
43
 
 
44
PID::PID(double* Input, double* Output, double* Setpoint,
 
45
        double Kp, double Ki, double Kd, int ControllerDirection)
 
46
    :PID::PID(Input, Output, Setpoint, Kp, Ki, Kd, P_ON_E, ControllerDirection)
 
47
{
 
48
 
 
49
}
 
50
 
 
51
 
 
52
/* Compute() **********************************************************************
 
53
 *     This, as they say, is where the magic happens.  this function should be called
 
54
 *   every time "void loop()" executes.  the function will decide for itself whether a new
 
55
 *   pid Output needs to be computed.  returns true when the output is computed,
 
56
 *   false when nothing has been done.
 
57
 **********************************************************************************/
 
58
bool PID::Compute()
 
59
{
 
60
   if(!inAuto) return false;
 
61
   unsigned long now = millis();
 
62
   unsigned long timeChange = (now - lastTime);
 
63
   if(timeChange>=SampleTime)
 
64
   {
 
65
      /*Compute all the working error variables*/
 
66
      double input = *myInput;
 
67
      double error = *mySetpoint - input;
 
68
      double dInput = (input - lastInput);
 
69
      outputSum+= (ki * error);
 
70
 
 
71
      /*Add Proportional on Measurement, if P_ON_M is specified*/
 
72
      if(!pOnE) outputSum-= kp * dInput;
 
73
 
 
74
      if(outputSum > outMax) outputSum= outMax;
 
75
      else if(outputSum < outMin) outputSum= outMin;
 
76
 
 
77
      /*Add Proportional on Error, if P_ON_E is specified*/
 
78
            double output;
 
79
      if(pOnE) output = kp * error;
 
80
      else output = 0;
 
81
 
 
82
      /*Compute Rest of PID Output*/
 
83
      output += outputSum - kd * dInput;
 
84
 
 
85
            if(output > outMax) output = outMax;
 
86
      else if(output < outMin) output = outMin;
 
87
            *myOutput = output;
 
88
 
 
89
      /*Remember some variables for next time*/
 
90
      lastInput = input;
 
91
      lastTime = now;
 
92
            return true;
 
93
   }
 
94
   else return false;
 
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(double Kp, double Ki, double Kd, int POn)
 
103
{
 
104
   if (Kp<0 || Ki<0 || Kd<0) return;
 
105
 
 
106
   pOn = POn;
 
107
   pOnE = POn == P_ON_E;
 
108
 
 
109
   dispKp = Kp; dispKi = Ki; dispKd = Kd;
 
110
 
 
111
   double SampleTimeInSec = ((double)SampleTime)/1000;
 
112
   kp = Kp;
 
113
   ki = Ki * SampleTimeInSec;
 
114
   kd = Kd / SampleTimeInSec;
 
115
 
 
116
  if(controllerDirection ==REVERSE)
 
117
   {
 
118
      kp = (0 - kp);
 
119
      ki = (0 - ki);
 
120
      kd = (0 - kd);
 
121
   }
 
122
}
 
123
 
 
124
/* SetTunings(...)*************************************************************
 
125
 * Set Tunings using the last-rembered POn setting
 
126
 ******************************************************************************/
 
127
void PID::SetTunings(double Kp, double Ki, double Kd){
 
128
    SetTunings(Kp, Ki, Kd, pOn); 
 
129
}
 
130
 
 
131
/* SetSampleTime(...) *********************************************************
 
132
 * sets the period, in Milliseconds, at which the calculation is performed
 
133
 ******************************************************************************/
 
134
void PID::SetSampleTime(int NewSampleTime)
 
135
{
 
136
   if (NewSampleTime > 0)
 
137
   {
 
138
      double ratio  = (double)NewSampleTime
 
139
                      / (double)SampleTime;
 
140
      ki *= ratio;
 
141
      kd /= ratio;
 
142
      SampleTime = (unsigned long)NewSampleTime;
 
143
   }
 
144
}
 
145
 
 
146
/* SetOutputLimits(...)****************************************************
 
147
 *     This function will be used far more often than SetInputLimits.  while
 
148
 *  the input to the controller will generally be in the 0-1023 range (which is
 
149
 *  the default already,)  the output will be a little different.  maybe they'll
 
150
 *  be doing a time window and will need 0-8000 or something.  or maybe they'll
 
151
 *  want to clamp it from 0-125.  who knows.  at any rate, that can all be done
 
152
 *  here.
 
153
 **************************************************************************/
 
154
void PID::SetOutputLimits(double Min, double Max)
 
155
{
 
156
   if(Min >= Max) return;
 
157
   outMin = Min;
 
158
   outMax = Max;
 
159
 
 
160
   if(inAuto)
 
161
   {
 
162
           if(*myOutput > outMax) *myOutput = outMax;
 
163
           else if(*myOutput < outMin) *myOutput = outMin;
 
164
 
 
165
           if(outputSum > outMax) outputSum= outMax;
 
166
           else if(outputSum < outMin) outputSum= outMin;
 
167
   }
 
168
}
 
169
 
 
170
/* SetMode(...)****************************************************************
 
171
 * Allows the controller Mode to be set to manual (0) or Automatic (non-zero)
 
172
 * when the transition from manual to auto occurs, the controller is
 
173
 * automatically initialized
 
174
 ******************************************************************************/
 
175
void PID::SetMode(uint8_t Mode)
 
176
{
 
177
    bool newAuto = (Mode == AUTOMATIC);
 
178
    if(newAuto && !inAuto)
 
179
    {  /*we just went from manual to auto*/
 
180
        PID::Initialize();
 
181
    }
 
182
    inAuto = newAuto;
 
183
}
 
184
 
 
185
/* Initialize()****************************************************************
 
186
 *      does all the things that need to happen to ensure a bumpless transfer
 
187
 *  from manual to automatic mode.
 
188
 ******************************************************************************/
 
189
void PID::Initialize()
 
190
{
 
191
   outputSum = *myOutput;
 
192
   lastInput = *myInput;
 
193
   if(outputSum > outMax) outputSum = outMax;
 
194
   else if(outputSum < outMin) outputSum = outMin;
 
195
}
 
196
 
 
197
/* SetControllerDirection(...)*************************************************
 
198
 * The PID will either be connected to a DIRECT acting process (+Output leads
 
199
 * to +Input) or a REVERSE acting process(+Output leads to -Input.)  we need to
 
200
 * know which one, because otherwise we may increase the output when we should
 
201
 * be decreasing.  This is called from the constructor.
 
202
 ******************************************************************************/
 
203
void PID::SetControllerDirection(int Direction)
 
204
{
 
205
   if(inAuto && Direction !=controllerDirection)
 
206
   {
 
207
            kp = (0 - kp);
 
208
      ki = (0 - ki);
 
209
      kd = (0 - kd);
 
210
   }
 
211
   controllerDirection = Direction;
 
212
}
 
213
 
 
214
/* Status Funcions*************************************************************
 
215
 * Just because you set the Kp=-1 doesn't mean it actually happened.  these
 
216
 * functions query the internal state of the PID.  they're here for display
 
217
 * purposes.  this are the functions the PID Front-end uses for example
 
218
 ******************************************************************************/
 
219
double PID::GetKp(){ return  dispKp; }
 
220
double PID::GetKi(){ return  dispKi;}
 
221
double PID::GetKd(){ return  dispKd;}
 
222
int PID::GetMode(){ return  inAuto ? AUTOMATIC : MANUAL;}
 
223
int PID::GetDirection(){ return controllerDirection;}
 
224