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:
0:9a6f7aafe531
Child:
1:c307cd559154
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PID.cpp	Mon Nov 23 02:42:53 2015 +0000
@@ -0,0 +1,71 @@
+#include "PID.h"
+/*
+    Bryce Williams 11/19/2015
+    See PID.h for references as well as method descriptions
+*/
+
+PID::PID(float* setpoint, float* feedback, float* output,
+         float output_lower, float output_upper,
+         float  kp, float ki,  float kd, float Ts){
+    _Ts = Ts;           // Init params
+    _kp = kp; 
+    _ki = ki*Ts;        // Roll sample time into gain  
+    _kd = kd / Ts;      // Roll sample time into gain
+    
+    _setpoint = setpoint; 
+    _feedback = feedback; 
+    _output = output;
+    
+    _output_lower = output_lower;
+    _output_upper = output_upper;
+}
+
+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
+    i_accumulator = clip(*_output, _output_lower,
+                     _output_upper);    // P and D terms are zero, thus 
+                                        // i term is used to keep output unchanged
+    
+    sample_timer.attach(this, &PID::sample, _Ts);
+}
+
+void PID::stop(){
+    sample_timer.detach();
+}
+
+float PID::getError(){
+    return error;
+}
+
+void PID::set_parameters(float kp, float ki, float kd, float Ts){
+    stop();         // Disable Sample Interrupt... stop()
+    _Ts = Ts;       // Set New Sample Time
+    _kp = kp;       // Seet New Kp
+    _ki = ki*Ts;    // Roll sample time into gain  
+    _kd = kd / Ts;  // Roll sample time into gain
+    start();        // Enable Sample Interrupt... start()
+}
+
+void PID::sample(){
+    error = *_setpoint - *_feedback;
+
+    // Accumulate Integral Term such ki is applied to current error
+    // before adding to pool; avoids bumps if ki gain value is changed.
+    i_accumulator += _ki * error;
+    // Avoid "Windup" by clamping intergral term to output limits;
+    // essentially we stop integrating when we reach an upper or 
+    // lower bound.
+    i_accumulator = clip(i_accumulator, _output_lower, _output_upper);
+    
+    // Run it!
+    *_output = _kp*error + i_accumulator - _kd*(*_feedback - last_feedback);
+    last_feedback = *_feedback;
+    // Clamp Output
+    *_output = clip(*_output, _output_lower, _output_upper);
+}
+
+float PID::clip(float value, float lower, float upper){
+    return std::max(lower, std::min(value, upper));
+}
\ No newline at end of file