171 lines
6.4 KiB
C++
171 lines
6.4 KiB
C++
//******************************************************************************
|
|
//
|
|
// IPID.cpp - differential PID equation
|
|
// Ivo Carvalho 29/4/2011
|
|
//
|
|
//******************************************************************************
|
|
|
|
|
|
#include "IPID.h"
|
|
|
|
//OBJECTLOADREGISTER(IPID,"$Id: IPID.cpp,v 1.0 29/4/2011 14:22:36 ivoc Exp $")
|
|
// if cycle time is supplied
|
|
IPID::IPID(float set_Kp_constant, float set_Ki_constant, float set_Kd_constant, float set_T_constant, float set_upper_limit, float set_lower_limit){
|
|
|
|
this->Kp_constant = set_Kp_constant;
|
|
this->Ki_constant = set_Ki_constant;
|
|
this->Kd_constant = set_Kd_constant;
|
|
this->T_constant = set_T_constant;
|
|
this->P_realtime_constant = this->Kp_constant;
|
|
this->I_realtime_constant = this->Ki_constant * this->T_constant;
|
|
this->D_realtime_constant = this->Kd_constant / this->T_constant;
|
|
this->upper_limit = set_upper_limit;
|
|
this->lower_limit = set_lower_limit;
|
|
this->old_output = 0;
|
|
this->old_PV = 0;
|
|
this->old_old_PV = 0;
|
|
this->old_error = 0;
|
|
this->old_old_error = 0;
|
|
}
|
|
// create without cycle time, just with the constants used in realtime
|
|
IPID::IPID(float set_P_realtime_constant, float set_I_realtime_constant, float set_D_realtime_constant, float set_upper_limit, float set_lower_limit){
|
|
|
|
this->P_realtime_constant = set_P_realtime_constant;
|
|
this->I_realtime_constant = set_I_realtime_constant;
|
|
this->D_realtime_constant = set_D_realtime_constant;
|
|
this->T_constant = 0; //undefined
|
|
this->Kp_constant = 0;
|
|
this->Ki_constant = 0;
|
|
this->Kd_constant = 0;
|
|
this->upper_limit = set_upper_limit;
|
|
this->lower_limit = set_lower_limit;
|
|
this->old_output = 0;
|
|
this->old_PV = 0;
|
|
this->old_old_PV = 0;
|
|
this->old_error = 0;
|
|
this->old_old_error = 0;
|
|
}
|
|
|
|
// ********* Destructor ********************************************
|
|
IPID::~IPID(){
|
|
|
|
}
|
|
|
|
bool IPID::LoadOldOutputWithinLimits(float old_output_to_load){
|
|
|
|
if (old_output_to_load > upper_limit) old_output_to_load = upper_limit;
|
|
if (old_output_to_load < lower_limit) old_output_to_load = lower_limit;
|
|
this->old_output = old_output_to_load;
|
|
this->old_PV = 0;
|
|
this->old_old_PV = 0;
|
|
this->old_error = 0;
|
|
this->old_old_error = 0;
|
|
return True;
|
|
}
|
|
|
|
bool IPID::SetPIDConstants(float set_Kp_constant, float set_Ki_constant, float set_Kd_constant, float set_T_constant){
|
|
|
|
this->Kp_constant = set_Kp_constant;
|
|
this->Ki_constant = set_Ki_constant;
|
|
this->Kd_constant = set_Kd_constant;
|
|
this->T_constant = set_T_constant;
|
|
this->P_realtime_constant = this->Kp_constant;
|
|
this->I_realtime_constant = this->Ki_constant * this->T_constant;
|
|
this->D_realtime_constant = this->Kd_constant / this->T_constant;
|
|
return True;
|
|
}
|
|
|
|
bool IPID::SetRealtimePIDConstants(float set_P_realtime_constant, float set_I_realtime_constant, float set_D_realtime_constant){
|
|
|
|
this->P_realtime_constant = set_P_realtime_constant;
|
|
this->I_realtime_constant = set_I_realtime_constant;
|
|
this->D_realtime_constant = set_D_realtime_constant;
|
|
if (this->T_constant > 0){
|
|
this->Kp_constant = this->P_realtime_constant;
|
|
this->Ki_constant = this->I_realtime_constant / this->T_constant;
|
|
this->Kd_constant = this->D_realtime_constant * this->T_constant;
|
|
}
|
|
return True;
|
|
}
|
|
|
|
bool IPID::SetLimits(float set_upper_limit, float set_lower_limit){
|
|
|
|
this->upper_limit = set_upper_limit;
|
|
this->lower_limit = set_lower_limit;
|
|
return True;
|
|
}
|
|
|
|
float IPID::CalculatePID(float process_variable, float setpoint){
|
|
this->error = setpoint - process_variable;
|
|
|
|
this->old_output = this->old_output - this->P_realtime_constant * (process_variable - this->old_PV) + this->I_realtime_constant * this->error - this->D_realtime_constant * (process_variable - 2 * this->old_PV + process_variable - this->old_old_PV);
|
|
|
|
this->old_old_PV = this->old_PV;
|
|
this->old_PV = process_variable;
|
|
|
|
if(this->old_output > this->upper_limit) this->old_output = this->upper_limit;
|
|
if(this->old_output < this->lower_limit) this->old_output = this->lower_limit;
|
|
|
|
return this->old_output;
|
|
}
|
|
|
|
float IPID::CalculatePI(float process_variable, float setpoint){
|
|
this->error = setpoint - process_variable;
|
|
|
|
this->old_output = this->old_output - this->P_realtime_constant * (process_variable - this->old_PV) + this->I_realtime_constant * this->error;
|
|
|
|
this->old_old_PV = this->old_PV;
|
|
this->old_PV = process_variable;
|
|
|
|
if(this->old_output > this->upper_limit) this->old_output = this->upper_limit;
|
|
if(this->old_output < this->lower_limit) this->old_output = this->lower_limit;
|
|
|
|
return this->old_output;
|
|
}
|
|
|
|
float IPID::CalculateP(float process_variable, float setpoint){
|
|
this->error = setpoint - process_variable;
|
|
|
|
this->old_output = this->old_output - this->P_realtime_constant * (process_variable - this->old_PV);
|
|
|
|
this->old_old_PV = this->old_PV;
|
|
this->old_PV = process_variable;
|
|
|
|
if(this->old_output > this->upper_limit) this->old_output = this->upper_limit;
|
|
if(this->old_output < this->lower_limit) this->old_output = this->lower_limit;
|
|
|
|
return this->old_output;
|
|
}
|
|
|
|
float IPID::CalculatePID_types(float process_variable, float setpoint, float type){
|
|
this->error = setpoint - process_variable;
|
|
|
|
if(type==1)//Type A
|
|
this->old_output = this->old_output + this->Kp_constant*1000 * (this->error - this->old_error) + this->Ki_constant*1000 * this->error + this->Kd_constant*1000 * (this->error - 2 * this->old_error + this->old_old_error);
|
|
if(type==2)//Type B
|
|
this->old_output = this->old_output + this->Kp_constant*1000 * (this->error - this->old_error) + this->Ki_constant*1000 * this->error - this->Kd_constant*1000 * (process_variable - 2 * this->old_PV + this->old_old_PV);
|
|
if(type==3)//Type C
|
|
this->old_output = this->old_output - this->Kp_constant*1000 * (process_variable - this->old_PV) + this->Ki_constant*1000 * this->error - this->Kd_constant*1000 * (process_variable - 2 * this->old_PV + this->old_old_PV);
|
|
|
|
this->old_old_PV = this->old_PV;
|
|
this->old_PV = process_variable;
|
|
this->old_old_error = this->old_error;
|
|
this->old_error = this->error;
|
|
|
|
//if(this->old_output > this->upper_limit) this->old_output = this->upper_limit;
|
|
//if(this->old_output < this->lower_limit) this->old_output = this->lower_limit;
|
|
|
|
if(this->old_output > this->upper_limit) return this->upper_limit;
|
|
if(this->old_output < this->lower_limit) return this->lower_limit;
|
|
|
|
return this->old_output;
|
|
}
|
|
|
|
float IPID::ReturnErrorInPercentage(float process_variable, float setpoint){
|
|
this->error = setpoint - process_variable;
|
|
|
|
if (this->error < 0) this->error = 0 - this->error;
|
|
|
|
return ((100 * error)/(this->upper_limit - this->lower_limit)) ;
|
|
}
|