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

Files at this revision

API Documentation at this revision

Comitter:
electromotivated
Date:
Tue Nov 24 02:28:24 2015 +0000
Parent:
2:07397aa513c6
Child:
4:4ed1f5bccac8
Commit message:
Bug Fix: Flush i_accumulator in start() method to prevent output from hanging. Read comments in start() method in .cpp file for more info

Changed in this revision

PID.cpp Show annotated file Show diff for this revision Revisions of this file
--- 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);
 }