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
Diff: PID.cpp
- 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); }