Libary for control.

Dependencies:   FastPWM

Dependents:   RT2_Cuboid

Committer:
pmic
Date:
Thu May 05 09:18:40 2022 +0000
Revision:
10:eb29810d831b
Parent:
8:3a2131231969
Adjusted AvgFilter (damn...)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pmic 4:1cbd6af9836c 1 #include "PID_Cntrl.h"
pmic 4:1cbd6af9836c 2
pmic 4:1cbd6af9836c 3 /*
pmic 4:1cbd6af9836c 4 Ts
pmic 4:1cbd6af9836c 5 C(z) = (P + I ---------- + D * tustin(s / (tau_f * s + 1))) * tustin(1 / (tau_ro * s + 1))
pmic 4:1cbd6af9836c 6 1 - z^-1
pmic 4:1cbd6af9836c 7 - Corresponds to MATLAB command: C = pid(P, I, D, tau_f, Ts, 'IFormula', 'BackwardEuler', 'DFormula', 'Trapezoidal') * c2d(tf(1, [tau_ro 1]), Ts, 'tustin')
pmic 4:1cbd6af9836c 8 - Anti-Windup: Saturation of Ipart and u = P*e + IPart + DPart
pmic 4:1cbd6af9836c 9 */
pmic 4:1cbd6af9836c 10
pmic 4:1cbd6af9836c 11 PID_Cntrl::PID_Cntrl(float I, float Ts, float uMin, float uMax)
pmic 4:1cbd6af9836c 12 {
pmic 6:e93f67d98616 13 setup(I, Ts, uMin, uMax);
pmic 4:1cbd6af9836c 14 }
pmic 4:1cbd6af9836c 15
pmic 4:1cbd6af9836c 16 PID_Cntrl::PID_Cntrl(float P, float I, float Ts, float uMin, float uMax)
pmic 4:1cbd6af9836c 17 {
pmic 6:e93f67d98616 18 setup(P, I, Ts, uMin, uMax);
pmic 4:1cbd6af9836c 19 }
pmic 4:1cbd6af9836c 20
pmic 4:1cbd6af9836c 21 PID_Cntrl::PID_Cntrl(float P, float I, float D, float Ts, float uMin, float uMax)
pmic 4:1cbd6af9836c 22 {
pmic 6:e93f67d98616 23 setup(P, I, D, Ts, uMin, uMax);
pmic 4:1cbd6af9836c 24 }
pmic 4:1cbd6af9836c 25
pmic 4:1cbd6af9836c 26 PID_Cntrl::PID_Cntrl(float P, float I, float D, float tau_f, float Ts, float uMin, float uMax)
pmic 4:1cbd6af9836c 27 {
pmic 6:e93f67d98616 28 setup(P, I, D, tau_f, Ts, uMin, uMax);
pmic 4:1cbd6af9836c 29 }
pmic 4:1cbd6af9836c 30
pmic 4:1cbd6af9836c 31 PID_Cntrl::PID_Cntrl(float P, float I, float D, float tau_f, float tau_ro, float Ts, float uMin, float uMax)
pmic 4:1cbd6af9836c 32 {
pmic 6:e93f67d98616 33 setup(P, I, D, tau_f, tau_ro, Ts, uMin, uMax);
pmic 4:1cbd6af9836c 34 }
pmic 4:1cbd6af9836c 35
pmic 4:1cbd6af9836c 36 PID_Cntrl::~PID_Cntrl() {}
pmic 4:1cbd6af9836c 37
pmic 6:e93f67d98616 38 void PID_Cntrl::reset()
pmic 6:e93f67d98616 39 {
pmic 6:e93f67d98616 40 reset(0.0f);
pmic 6:e93f67d98616 41 }
pmic 6:e93f67d98616 42
pmic 4:1cbd6af9836c 43 void PID_Cntrl::reset(float initValue)
pmic 4:1cbd6af9836c 44 {
pmic 4:1cbd6af9836c 45 IPart = initValue;
pmic 4:1cbd6af9836c 46 Dpart = 0.0f;
pmic 4:1cbd6af9836c 47 d_old = 0.0f;
pmic 4:1cbd6af9836c 48 u_old = initValue;
pmic 4:1cbd6af9836c 49 uf = initValue;
pmic 4:1cbd6af9836c 50 }
pmic 4:1cbd6af9836c 51
pmic 6:e93f67d98616 52 void PID_Cntrl::setup(float I, float Ts, float uMin, float uMax)
pmic 4:1cbd6af9836c 53 {
pmic 4:1cbd6af9836c 54 P = 0.0f;
pmic 4:1cbd6af9836c 55 D = 0.0f;
pmic 4:1cbd6af9836c 56 double Ts_d = static_cast<double>( Ts );
pmic 6:e93f67d98616 57 tau_f = static_cast<float>( Ts_d/(0.95*pi) ); // unused
pmic 4:1cbd6af9836c 58 tau_ro = 0.0f;
pmic 6:e93f67d98616 59 setup(P, I, D, tau_f, tau_ro, Ts, uMin, uMax);
pmic 4:1cbd6af9836c 60 }
pmic 4:1cbd6af9836c 61
pmic 6:e93f67d98616 62 void PID_Cntrl::setup(float P, float I, float Ts, float uMin, float uMax)
pmic 4:1cbd6af9836c 63 {
pmic 4:1cbd6af9836c 64 D = 0.0f;
pmic 4:1cbd6af9836c 65 double Ts_d = static_cast<double>( Ts );
pmic 6:e93f67d98616 66 tau_f = static_cast<float>( Ts_d/(0.95*pi) ); // unused
pmic 4:1cbd6af9836c 67 tau_ro = 0.0f;
pmic 6:e93f67d98616 68 setup(P, I, D, tau_f, tau_ro, Ts, uMin, uMax);
pmic 4:1cbd6af9836c 69 }
pmic 4:1cbd6af9836c 70
pmic 6:e93f67d98616 71 void PID_Cntrl::setup(float P, float I, float D, float Ts, float uMin, float uMax)
pmic 4:1cbd6af9836c 72 {
pmic 4:1cbd6af9836c 73 double Ts_d = static_cast<double>( Ts );
pmic 4:1cbd6af9836c 74 tau_f = static_cast<float>( Ts_d/(0.95*pi) ); // 1.0/(0.95*2.0*pi*fnyq)
pmic 4:1cbd6af9836c 75 tau_ro = 0.0f;
pmic 6:e93f67d98616 76 setup(P, I, D, tau_f, tau_ro, Ts, uMin, uMax);
pmic 4:1cbd6af9836c 77 }
pmic 4:1cbd6af9836c 78
pmic 6:e93f67d98616 79 void PID_Cntrl::setup(float P, float I, float D, float tau_f, float Ts, float uMin, float uMax)
pmic 4:1cbd6af9836c 80 {
pmic 4:1cbd6af9836c 81 tau_ro = 0.0f;
pmic 6:e93f67d98616 82 setup(P, I, D, tau_f, tau_ro, Ts, uMin, uMax);
pmic 4:1cbd6af9836c 83 }
pmic 4:1cbd6af9836c 84
pmic 6:e93f67d98616 85 void PID_Cntrl::setup(float P, float I, float D, float tau_f, float tau_ro, float Ts, float uMin, float uMax)
pmic 4:1cbd6af9836c 86 {
pmic 6:e93f67d98616 87 setCoefficients(P, I, D, tau_f, tau_ro, Ts);
pmic 4:1cbd6af9836c 88 this->uMin = uMin;
pmic 4:1cbd6af9836c 89 this->uMax = uMax;
pmic 6:e93f67d98616 90 reset();
pmic 4:1cbd6af9836c 91 }
pmic 4:1cbd6af9836c 92
pmic 4:1cbd6af9836c 93 void PID_Cntrl::setCoeff_P(float P)
pmic 4:1cbd6af9836c 94 {
pmic 4:1cbd6af9836c 95 this->P = P;
pmic 4:1cbd6af9836c 96 }
pmic 4:1cbd6af9836c 97
pmic 4:1cbd6af9836c 98 void PID_Cntrl::setCoeff_I(float I)
pmic 4:1cbd6af9836c 99 {
pmic 4:1cbd6af9836c 100 this->I = I;
pmic 4:1cbd6af9836c 101 updateCoeff_I(I, Ts);
pmic 4:1cbd6af9836c 102 }
pmic 4:1cbd6af9836c 103
pmic 4:1cbd6af9836c 104 void PID_Cntrl::setCoeff_D(float D)
pmic 4:1cbd6af9836c 105 {
pmic 4:1cbd6af9836c 106 this->D = D;
pmic 4:1cbd6af9836c 107 updateCoeff_D(D, Ts, tau_f);
pmic 4:1cbd6af9836c 108 }
pmic 4:1cbd6af9836c 109
pmic 4:1cbd6af9836c 110 void PID_Cntrl::scale_PIDT2_param(float scale)
pmic 4:1cbd6af9836c 111 {
pmic 4:1cbd6af9836c 112 P = P_init * scale;
pmic 4:1cbd6af9836c 113 I = I_init * scale;
pmic 6:e93f67d98616 114 D = D_init * scale;
pmic 4:1cbd6af9836c 115 updateCoeff_I(I, Ts);
pmic 4:1cbd6af9836c 116 updateCoeff_D(D, Ts, tau_f);
pmic 4:1cbd6af9836c 117 }
pmic 4:1cbd6af9836c 118
pmic 4:1cbd6af9836c 119 float PID_Cntrl::update(float e)
pmic 4:1cbd6af9836c 120 {
pmic 8:3a2131231969 121 if(bi !=0) {
pmic 8:3a2131231969 122 IPart = saturate(IPart + bi*e, uMin, uMax);
pmic 8:3a2131231969 123 } else {
pmic 8:3a2131231969 124 IPart = 0.0f;
pmic 8:3a2131231969 125 }
pmic 4:1cbd6af9836c 126 Dpart = bd*(e - d_old) - ad*Dpart;
pmic 4:1cbd6af9836c 127 d_old = e;
pmic 4:1cbd6af9836c 128 float u = P*e + IPart + Dpart;
pmic 4:1cbd6af9836c 129 uf = saturate(bf*(u + u_old) - af*uf, uMin, uMax);
pmic 4:1cbd6af9836c 130 u_old = u;
pmic 4:1cbd6af9836c 131 return uf;
pmic 4:1cbd6af9836c 132 }
pmic 4:1cbd6af9836c 133
pmic 4:1cbd6af9836c 134 float PID_Cntrl::update(float e, float y)
pmic 4:1cbd6af9836c 135 {
pmic 8:3a2131231969 136 if(bi !=0) {
pmic 8:3a2131231969 137 IPart = saturate(IPart + bi*e, uMin, uMax);
pmic 8:3a2131231969 138 } else {
pmic 8:3a2131231969 139 IPart = 0.0f;
pmic 8:3a2131231969 140 }
pmic 4:1cbd6af9836c 141 Dpart = bd*(y - d_old) - ad*Dpart;
pmic 4:1cbd6af9836c 142 d_old = y;
pmic 4:1cbd6af9836c 143 float u = P*e + IPart - Dpart;
pmic 4:1cbd6af9836c 144 uf = saturate(bf*(u + u_old) - af*uf, uMin, uMax);
pmic 4:1cbd6af9836c 145 u_old = u;
pmic 4:1cbd6af9836c 146 return uf;
pmic 4:1cbd6af9836c 147 }
pmic 4:1cbd6af9836c 148
pmic 4:1cbd6af9836c 149 bool PID_Cntrl::update_param(int cntrlr_param, float value)
pmic 4:1cbd6af9836c 150 {
pmic 4:1cbd6af9836c 151 switch (cntrlr_param) {
pmic 4:1cbd6af9836c 152 case 0:
pmic 4:1cbd6af9836c 153 setCoeff_P(value);
pmic 4:1cbd6af9836c 154 return true;
pmic 4:1cbd6af9836c 155 break;
pmic 4:1cbd6af9836c 156 case 1:
pmic 4:1cbd6af9836c 157 setCoeff_I(value);
pmic 4:1cbd6af9836c 158 return true;
pmic 4:1cbd6af9836c 159 break;
pmic 4:1cbd6af9836c 160 case 2:
pmic 4:1cbd6af9836c 161 setCoeff_D(value);
pmic 4:1cbd6af9836c 162 return true;
pmic 4:1cbd6af9836c 163 break;
pmic 4:1cbd6af9836c 164 case 3:
pmic 4:1cbd6af9836c 165 this->tau_f = value;
pmic 4:1cbd6af9836c 166 break;
pmic 4:1cbd6af9836c 167 case 4:
pmic 4:1cbd6af9836c 168 this->tau_ro = value;
pmic 4:1cbd6af9836c 169 break;
pmic 4:1cbd6af9836c 170 case 5:
pmic 4:1cbd6af9836c 171 return false;
pmic 4:1cbd6af9836c 172 break;
pmic 4:1cbd6af9836c 173 case 6:
pmic 4:1cbd6af9836c 174 this->uMin = value;
pmic 4:1cbd6af9836c 175 return true;
pmic 4:1cbd6af9836c 176 break;
pmic 4:1cbd6af9836c 177 case 7:
pmic 4:1cbd6af9836c 178 this->uMax = value;
pmic 4:1cbd6af9836c 179 return true;
pmic 4:1cbd6af9836c 180 break;
pmic 4:1cbd6af9836c 181 default:
pmic 4:1cbd6af9836c 182 return false;
pmic 4:1cbd6af9836c 183 break;
pmic 4:1cbd6af9836c 184 }
pmic 4:1cbd6af9836c 185 updateCoeff_I(I, Ts);
pmic 4:1cbd6af9836c 186 updateCoeff_D(D, Ts, tau_f);
pmic 4:1cbd6af9836c 187 updateCoeff_RO(Ts, tau_ro);
pmic 4:1cbd6af9836c 188 return true;
pmic 4:1cbd6af9836c 189 }
pmic 4:1cbd6af9836c 190
pmic 4:1cbd6af9836c 191 void PID_Cntrl::set_limits(float uMin, float uMax)
pmic 4:1cbd6af9836c 192 {
pmic 4:1cbd6af9836c 193 this->uMin = uMin;
pmic 4:1cbd6af9836c 194 this->uMax = uMax;
pmic 4:1cbd6af9836c 195 }
pmic 4:1cbd6af9836c 196
pmic 6:e93f67d98616 197 float PID_Cntrl::prewarp(float T, float Ts)
pmic 6:e93f67d98616 198 {
pmic 6:e93f67d98616 199 double T_d = static_cast<double>( T );
pmic 6:e93f67d98616 200 double Ts_d = static_cast<double>( Ts );
pmic 6:e93f67d98616 201 return static_cast<float>( Ts_d/(2.0*tan(Ts_d/(2.0*T_d))) );
pmic 6:e93f67d98616 202 }
pmic 6:e93f67d98616 203
pmic 4:1cbd6af9836c 204 float PID_Cntrl::get_ulimit()
pmic 4:1cbd6af9836c 205 {
pmic 4:1cbd6af9836c 206 return uMax;
pmic 4:1cbd6af9836c 207 }
pmic 4:1cbd6af9836c 208
pmic 4:1cbd6af9836c 209 float PID_Cntrl::get_P_gain()
pmic 4:1cbd6af9836c 210 {
pmic 4:1cbd6af9836c 211 return P;
pmic 4:1cbd6af9836c 212 }
pmic 4:1cbd6af9836c 213
pmic 4:1cbd6af9836c 214 float PID_Cntrl::get_bd()
pmic 4:1cbd6af9836c 215 {
pmic 4:1cbd6af9836c 216 return bd;
pmic 4:1cbd6af9836c 217 }
pmic 4:1cbd6af9836c 218
pmic 4:1cbd6af9836c 219 float PID_Cntrl::get_ad()
pmic 4:1cbd6af9836c 220 {
pmic 4:1cbd6af9836c 221 return ad;
pmic 4:1cbd6af9836c 222 }
pmic 4:1cbd6af9836c 223
pmic 6:e93f67d98616 224 void PID_Cntrl::setCoefficients(float P, float I, float D, float tau_f, float tau_ro, float Ts)
pmic 4:1cbd6af9836c 225 {
pmic 4:1cbd6af9836c 226 /* store parameters */
pmic 4:1cbd6af9836c 227 this->P = P;
pmic 4:1cbd6af9836c 228 this->I = I;
pmic 4:1cbd6af9836c 229 this->D = D;
pmic 4:1cbd6af9836c 230 this->tau_f = tau_f;
pmic 4:1cbd6af9836c 231 this->tau_ro = tau_ro;
pmic 4:1cbd6af9836c 232 this->Ts = Ts;
pmic 4:1cbd6af9836c 233 updateCoeff_I(I, Ts);
pmic 4:1cbd6af9836c 234 updateCoeff_D(D, Ts, tau_f);
pmic 4:1cbd6af9836c 235 updateCoeff_RO(Ts, tau_ro);
pmic 4:1cbd6af9836c 236
pmic 4:1cbd6af9836c 237 /* store initial parameters */
pmic 4:1cbd6af9836c 238 this->P_init = P;
pmic 4:1cbd6af9836c 239 this->I_init = I;
pmic 4:1cbd6af9836c 240 this->D_init = D;
pmic 4:1cbd6af9836c 241 }
pmic 4:1cbd6af9836c 242
pmic 4:1cbd6af9836c 243 float PID_Cntrl::saturate(float u, float uMin, float uMax)
pmic 4:1cbd6af9836c 244 {
pmic 4:1cbd6af9836c 245 if(u > uMax) {
pmic 4:1cbd6af9836c 246 u = uMax;
pmic 4:1cbd6af9836c 247 } else if(u < uMin) {
pmic 4:1cbd6af9836c 248 u = uMin;
pmic 4:1cbd6af9836c 249 }
pmic 4:1cbd6af9836c 250 return u;
pmic 4:1cbd6af9836c 251 }
pmic 4:1cbd6af9836c 252
pmic 4:1cbd6af9836c 253 void PID_Cntrl::updateCoeff_I(float I, float Ts)
pmic 4:1cbd6af9836c 254 {
pmic 4:1cbd6af9836c 255 double I_d = static_cast<double>( I );
pmic 4:1cbd6af9836c 256 double Ts_d = static_cast<double>( Ts );
pmic 4:1cbd6af9836c 257 bi = static_cast<float>( I_d*Ts_d );
pmic 4:1cbd6af9836c 258 }
pmic 4:1cbd6af9836c 259
pmic 4:1cbd6af9836c 260 void PID_Cntrl::updateCoeff_D(float D, float Ts, float tau_f)
pmic 4:1cbd6af9836c 261 {
pmic 4:1cbd6af9836c 262 double D_d = static_cast<double>( D );
pmic 4:1cbd6af9836c 263 double Ts_d = static_cast<double>( Ts );
pmic 4:1cbd6af9836c 264 double tau_f_d = static_cast<double>( tau_f );
pmic 4:1cbd6af9836c 265 bd = static_cast<float>( 2.0*D_d/(Ts_d + 2.0*tau_f_d) );
pmic 4:1cbd6af9836c 266 ad = static_cast<float>( (Ts_d - 2.0*tau_f_d)/(Ts_d + 2.0*tau_f_d) );
pmic 4:1cbd6af9836c 267 }
pmic 4:1cbd6af9836c 268
pmic 4:1cbd6af9836c 269 void PID_Cntrl::updateCoeff_RO(float Ts, float tau_ro)
pmic 4:1cbd6af9836c 270 {
pmic 4:1cbd6af9836c 271 double Ts_d = static_cast<double>( Ts );
pmic 4:1cbd6af9836c 272 double tau_ro_d = static_cast<double>( tau_ro );
pmic 4:1cbd6af9836c 273 bf = static_cast<float>( Ts_d/(Ts_d + 2.0*tau_ro_d) );
pmic 4:1cbd6af9836c 274 af = static_cast<float>( (Ts_d - 2.0*tau_ro_d)/(Ts_d + 2.0*tau_ro_d) );
pmic 4:1cbd6af9836c 275 }