Basic but robust PID library

Dependents:   ESP8266_pid_mtrPos_webserver_SDcard_v2 ESP8266_pid_mtrSpeed_Webserver_SDcard ESP8266_pid_spd_and_pos_webserver_SDcard ESP8266_pid_redbot_webserver ... more

Revision:
3:6c2c985408df
Parent:
1:c307cd559154
Child:
4:4ed1f5bccac8
--- a/PID.cpp	Tue Nov 24 00:17:55 2015 +0000
+++ b/PID.cpp	Tue Nov 24 02:28:24 2015 +0000
@@ -23,10 +23,51 @@
 void PID::start(){
     // Start up such we avoid bumps... (see "Initialization" section in
     // the reference link found in the header file).
-    last_feedback = *_feedback;   // Eliminate derivative kick at start/restart
+    last_feedback = *_feedback;         // Eliminate derivative kick at start/restart
     i_accumulator = clip(*_output, _output_lower,
                      _output_upper);    // P and D terms are zero, thus 
                                         // i term is used to keep output unchanged
+    /*
+        If Ki is set to zero we must "flush" the intergral accumulator. 
+        
+        Reason:
+        If we don't "flush", i_accumulator will hold the output value from line
+        above, and because Ki is now zero only zeros will be added to 
+        i_accumulator in the sample method, and thus i_accumulator is left 
+        unchanged from here on out. i_accumulator is now a constant of value
+        output from line above and will ALWAYS appear in the output. i.e.
+        
+        Here is the BUG if we DON'T FLUSH
+        
+        _ki = 0;            // User set ki = zero using  PID::set_parameters()
+        
+        THEN when PID::set_parameters() calls PID::start() (this method)
+        
+        i_accumulator = output;     // From line above
+        
+        Then when PID::sample() is called everytime...
+        
+        sample(){
+            i_accumulator += _ki * error;   // Now this is equivalent to 
+                                            // i_accumulator = output + 0
+                                            // which always equals output
+                                            // value from line above
+
+            i_accumulator = clip(i_accumulator, _output_lower, _output_upper);
+            
+            // Run it!
+            *_output = _kp*error + i_accumulator - _kd*(*_feedback - last_feedback);
+                // i_accumulator is fixed at value output from line above
+                // i.e. i_accumulator = clip(*_output, _output_lower,
+                                              _output_upper) = output;
+            last_feedback = *_feedback;
+            // Clamp Output
+            *_output = clip(*_output, _output_lower, _output_upper);
+                // Here *_output will always be offset by "output" value
+                // from line above 
+        }   
+    */
+    if(-0.00001 <= _ki && _ki <= 0.00001) i_accumulator = 0;
     sample_timer.attach(this, &PID::sample, _Ts);
 }