123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- #ifndef _PID_SOURCE_
- #define _PID_SOURCE_
- #include <iostream>
- #include <cmath>
- #include <QDebug>
- #include "pid.h"
- using namespace std;
- #define STAGE_INIT (0)
- #define STAGE_LOW (1)
- #define STAGE_MID (2)
- #define STAGE_HIGH (3)
- class PIDImpl
- {
- public:
- PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki);
- PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI);
- PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI, double maxStep);
- ~PIDImpl();
- double calculate( double setpoint, double pv );
- double calculate_v2( double setpoint, double pv );
- void reset();
- private:
- double _dt;
- double _max;
- double _min;
- double _Kp;
- double _Kd;
- double _Ki;
- double _pre_error;
- double _integral;
- double _maxI;
- double _maxStep;
- double _pre_output;
- double _start_pv;
- double _critical_output;
- int _stage;
- };
- PID::PID( double dt, double max, double min, double Kp, double Kd, double Ki)
- {
- pimpl = new PIDImpl(dt,max,min,Kp,Kd,Ki);
- }
- PID::PID( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI)
- {
- pimpl = new PIDImpl(dt,max,min,Kp,Kd,Ki,maxI);
- }
- PID::PID( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI, double maxStep)
- {
- pimpl = new PIDImpl(dt,max,min,Kp,Kd,Ki,maxI, maxStep);
- }
- double PID::calculate( double setpoint, double pv )
- {
- return pimpl->calculate(setpoint,pv);
- }
- double PID::calculate_v2( double setpoint, double pv )
- {
- return pimpl->calculate_v2(setpoint,pv);
- }
- void PID::reset()
- {
- return pimpl->reset();
- }
- PID::~PID()
- {
- delete pimpl;
- }
- /**
- * Implementation
- */
- PIDImpl::PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki) :
- _dt(dt),
- _max(max),
- _min(min),
- _Kp(Kp),
- _Kd(Kd),
- _Ki(Ki),
- _pre_error(0),
- _integral(0)
- {
- _maxI = 0;
- _maxStep = 0;
- _pre_output = 0;
- _start_pv = 0;
- _critical_output = 0;
- _stage = STAGE_INIT;
- }
- /**
- * Implementation
- */
- PIDImpl::PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI) :
- _dt(dt),
- _max(max),
- _min(min),
- _Kp(Kp),
- _Kd(Kd),
- _Ki(Ki),
- _pre_error(0),
- _integral(0),
- _maxI(maxI)
- {
- _maxStep = 0;
- _pre_output = 0;
- _start_pv = 0;
- _critical_output = 0;
- _stage = STAGE_INIT;
- }
- /**
- * Implementation
- */
- PIDImpl::PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI, double maxStep) :
- _dt(dt),
- _max(max),
- _min(min),
- _Kp(Kp),
- _Kd(Kd),
- _Ki(Ki),
- _pre_error(0),
- _integral(0),
- _maxI(maxI),
- _maxStep(maxStep)
- {
- _pre_output = 0;
- _start_pv = 0;
- _critical_output = 0;
- _stage = STAGE_INIT;
- }
- double PIDImpl::calculate( double setpoint, double pv )
- {
- // Calculate error
- double error = setpoint - pv;
- // Proportional term
- double Pout = _Kp * error;
- // Integral term
- _integral += error * _dt;
- double Iout = _Ki * _integral;
- //积分限幅
- if(_maxI > 0){
- if(Iout > _maxI){
- Iout = _maxI;
- }else if(Iout < -_maxI){
- Iout = -_maxI;
- }
- }
- // Derivative term
- double derivative = (error - _pre_error) / _dt;
- double Dout = _Kd * derivative;
- qDebug("calculate : pOut : %f, Iout: %f, Dout: %f ", Pout, Iout, Dout);
- // Calculate total output
- //double output = Pout + Iout + Dout;
- double output = Pout + Iout ;//+ Dout;
- // Restrict to max/min
- if( output > _max )
- output = _max;
- else if( output < _min )
- output = _min;
- // Save error to previous error
- _pre_error = error;
- if(_maxStep > 0){
- if(output - _pre_output > _maxStep){
- output = _pre_output + _maxStep;
- } else if(_pre_output - output > _maxStep){
- output = _pre_output - _maxStep;
- }
- }
- _pre_output = output;
- return output;
- }
- double PIDImpl::calculate_v2( double setpoint, double pv )
- {
- // Calculate error
- double error = setpoint - pv;
- // Proportional term
- double Pout = _Kp * error;
- // Integral term
- _integral += error * _dt;
- double Iout = _Ki * _integral;
- // Derivative term
- double derivative = (error - _pre_error) / _dt;
- double Dout = _Kd * derivative;
- qDebug("calculate_V2 : pOut : %f, Iout: %f, Dout: %f ", Pout, Iout, Dout);
- // Calculate total output
- //double output = Pout + Iout + Dout;
- double output = Pout + Iout ;//+ Dout;
- // Restrict to max/min
- if( output > _max )
- output = _max;
- else if( output < _min )
- output = _min;
- // Save error to previous error
- _pre_error = error;
- //belows add by avansguo
- if(STAGE_INIT == _stage){
- _start_pv = pv;
- _stage = STAGE_LOW;
- }else{
- if(pv < _start_pv){
- _start_pv = pv;
- qDebug("calculate _start_pv: %f ", _start_pv);
- }
- }
- if(_critical_output < 1.0){
- if(derivative <= (-0.02)){ //压力开始增加了,记录前值作为临界值
- _critical_output = _pre_output;
- qDebug("calculate _critical_output: %f ", _critical_output);
- }
- }
- double _distance = 0;
- if(setpoint - _start_pv < 0.5){
- _distance = 1;
- }else{
- _distance = error/(setpoint - _start_pv);
- }
- if(_distance <= 0.2){
- output = _critical_output + (_distance+0.1)*( _pre_output - _critical_output);
- }else if((_distance > 0.2) &&(_distance <= 0.5)){
- if(derivative > (-0.02)){ //压力不变或在下降
- }else if(derivative < (-0.2)){
- output = _pre_output+Dout;
- _integral = output;
- }{
- output = _pre_output;
- _integral = output;
- }
- }else{
- if(derivative < (-0.2)){
- output = _pre_output+Dout;
- _integral = output;
- }else if(derivative > (-0.02)){ //压力不变或在下降
- //解决当 开始压力与初始压力差距太小, 积分太慢的问题
- if(output-_pre_output < 2){
- output = _pre_output+2;
- _integral = output;
- }
- }else{
- output = _pre_output;
- _integral = output;
- }
- //
- }
- _pre_output = output;
- return output;
- }
- void PIDImpl::reset()
- {
- _pre_error = 0;
- _integral = 0;
- _pre_output = 0;
- _start_pv = 0;
- _critical_output = 0;
- _stage = STAGE_INIT;
- }
- PIDImpl::~PIDImpl()
- {
- }
- #endif
|