pid.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. #ifndef _PID_SOURCE_
  2. #define _PID_SOURCE_
  3. #include <iostream>
  4. #include <cmath>
  5. #include <QDebug>
  6. #include "pid.h"
  7. using namespace std;
  8. #define STAGE_INIT (0)
  9. #define STAGE_LOW (1)
  10. #define STAGE_MID (2)
  11. #define STAGE_HIGH (3)
  12. class PIDImpl
  13. {
  14. public:
  15. PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki);
  16. PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI);
  17. PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI, double maxIstep, double maxDstep);
  18. ~PIDImpl();
  19. double calculate( double setpoint, double pv );
  20. double calculate_v2( double setpoint, double pv );
  21. void reset();
  22. private:
  23. double _dt;
  24. double _max;
  25. double _min;
  26. double _Kp;
  27. double _Kd;
  28. double _Ki;
  29. double _pre_error;
  30. double _integral;
  31. double _maxI;
  32. double _maxIstep;
  33. double _maxDstep;
  34. double _pre_output;
  35. double _start_pv;
  36. double _critical_output;
  37. int _stage;
  38. };
  39. PID::PID( double dt, double max, double min, double Kp, double Kd, double Ki)
  40. {
  41. pimpl = new PIDImpl(dt,max,min,Kp,Kd,Ki);
  42. }
  43. PID::PID( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI)
  44. {
  45. pimpl = new PIDImpl(dt,max,min,Kp,Kd,Ki,maxI);
  46. }
  47. PID::PID( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI, double maxIstep, double maxDstep)
  48. {
  49. pimpl = new PIDImpl(dt,max,min,Kp,Kd,Ki,maxI, maxIstep, maxDstep);
  50. }
  51. double PID::calculate( double setpoint, double pv )
  52. {
  53. return pimpl->calculate(setpoint,pv);
  54. }
  55. double PID::calculate_v2( double setpoint, double pv )
  56. {
  57. return pimpl->calculate_v2(setpoint,pv);
  58. }
  59. void PID::reset()
  60. {
  61. return pimpl->reset();
  62. }
  63. PID::~PID()
  64. {
  65. delete pimpl;
  66. }
  67. /**
  68. * Implementation
  69. */
  70. PIDImpl::PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki) :
  71. _dt(dt),
  72. _max(max),
  73. _min(min),
  74. _Kp(Kp),
  75. _Kd(Kd),
  76. _Ki(Ki),
  77. _pre_error(0),
  78. _integral(0)
  79. {
  80. _maxI = 0;
  81. _maxIstep = 0;
  82. _maxDstep = 0;
  83. _pre_output = 0;
  84. _start_pv = 0;
  85. _critical_output = 0;
  86. _stage = STAGE_INIT;
  87. }
  88. /**
  89. * Implementation
  90. */
  91. PIDImpl::PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI) :
  92. _dt(dt),
  93. _max(max),
  94. _min(min),
  95. _Kp(Kp),
  96. _Kd(Kd),
  97. _Ki(Ki),
  98. _pre_error(0),
  99. _integral(0),
  100. _maxI(maxI)
  101. {
  102. _maxIstep = 0;
  103. _maxDstep = 0;
  104. _pre_output = 0;
  105. _start_pv = 0;
  106. _critical_output = 0;
  107. _stage = STAGE_INIT;
  108. }
  109. /**
  110. * Implementation
  111. */
  112. PIDImpl::PIDImpl( double dt, double max, double min, double Kp, double Kd, double Ki, double maxI, double maxIstep, double maxDstep) :
  113. _dt(dt),
  114. _max(max),
  115. _min(min),
  116. _Kp(Kp),
  117. _Kd(Kd),
  118. _Ki(Ki),
  119. _pre_error(0),
  120. _integral(0),
  121. _maxI(maxI),
  122. _maxIstep(maxIstep),
  123. _maxDstep(maxDstep)
  124. {
  125. _pre_output = 0;
  126. _start_pv = 0;
  127. _critical_output = 0;
  128. _stage = STAGE_INIT;
  129. }
  130. double PIDImpl::calculate( double setpoint, double pv )
  131. {
  132. // Calculate error
  133. double error = setpoint - pv;
  134. // Proportional term
  135. double Pout = _Kp * error;
  136. // Integral term
  137. if(setpoint < 0.05){
  138. _integral += error * _dt;
  139. }
  140. double Iout = _Ki * _integral;
  141. //积分限幅
  142. if(_maxI > 0){
  143. if(Iout > _maxI){
  144. Iout = _maxI;
  145. }else if(Iout < -_maxI){
  146. Iout = -_maxI;
  147. }
  148. }
  149. // Derivative term
  150. double derivative = (error - _pre_error) / _dt;
  151. double Dout = _Kd * derivative;
  152. qDebug("calculate : pOut : %f, Iout: %f, Dout: %f ", Pout, Iout, Dout);
  153. // Calculate total output
  154. //double output = Pout + Iout + Dout;
  155. double output = Pout + Iout ;//+ Dout;
  156. // Save error to previous error
  157. _pre_error = error;
  158. if(_maxIstep > 0 && output - _pre_output > _maxIstep){
  159. output = _pre_output + _maxIstep;
  160. }else if(_maxDstep > 0 && _pre_output - output > _maxDstep){
  161. output = _pre_output - _maxDstep;
  162. }
  163. // Restrict to max/min
  164. if( output > _max )
  165. output = _max;
  166. else if( output < _min )
  167. output = _min;
  168. _pre_output = output;
  169. return output;
  170. }
  171. double PIDImpl::calculate_v2( double setpoint, double pv )
  172. {
  173. // Calculate error
  174. double error = setpoint - pv;
  175. // Proportional term
  176. double Pout = _Kp * error;
  177. // Integral term
  178. _integral += error * _dt;
  179. double Iout = _Ki * _integral;
  180. // Derivative term
  181. double derivative = (error - _pre_error) / _dt;
  182. double Dout = _Kd * derivative;
  183. qDebug("calculate_V2 : pOut : %f, Iout: %f, Dout: %f ", Pout, Iout, Dout);
  184. // Calculate total output
  185. //double output = Pout + Iout + Dout;
  186. double output = Pout + Iout ;//+ Dout;
  187. // Restrict to max/min
  188. if( output > _max )
  189. output = _max;
  190. else if( output < _min )
  191. output = _min;
  192. // Save error to previous error
  193. _pre_error = error;
  194. //belows add by avansguo
  195. if(STAGE_INIT == _stage){
  196. _start_pv = pv;
  197. _stage = STAGE_LOW;
  198. }else{
  199. if(pv < _start_pv){
  200. _start_pv = pv;
  201. qDebug("calculate _start_pv: %f ", _start_pv);
  202. }
  203. }
  204. if(_critical_output < 1.0){
  205. if(derivative <= (-0.02)){ //压力开始增加了,记录前值作为临界值
  206. _critical_output = _pre_output;
  207. qDebug("calculate _critical_output: %f ", _critical_output);
  208. }
  209. }
  210. double _distance = 0;
  211. if(setpoint - _start_pv < 0.5){
  212. _distance = 1;
  213. }else{
  214. _distance = error/(setpoint - _start_pv);
  215. }
  216. if(_distance <= 0.2){
  217. output = _critical_output + (_distance+0.1)*( _pre_output - _critical_output);
  218. }else if((_distance > 0.2) &&(_distance <= 0.5)){
  219. if(derivative > (-0.02)){ //压力不变或在下降
  220. }else if(derivative < (-0.2)){
  221. output = _pre_output+Dout;
  222. _integral = output;
  223. }{
  224. output = _pre_output;
  225. _integral = output;
  226. }
  227. }else{
  228. if(derivative < (-0.2)){
  229. output = _pre_output+Dout;
  230. _integral = output;
  231. }else if(derivative > (-0.02)){ //压力不变或在下降
  232. //解决当 开始压力与初始压力差距太小, 积分太慢的问题
  233. if(output-_pre_output < 2){
  234. output = _pre_output+2;
  235. _integral = output;
  236. }
  237. }else{
  238. output = _pre_output;
  239. _integral = output;
  240. }
  241. //
  242. }
  243. _pre_output = output;
  244. return output;
  245. }
  246. void PIDImpl::reset()
  247. {
  248. _pre_error = 0;
  249. _integral = 0;
  250. _pre_output = 0;
  251. _start_pv = 0;
  252. _critical_output = 0;
  253. _stage = STAGE_INIT;
  254. }
  255. PIDImpl::~PIDImpl()
  256. {
  257. }
  258. #endif