pid.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. #include "pid.h"
  2. #include <QtMath>
  3. PID::PID()
  4. {
  5. //-----------------------------------------
  6. // PID参数
  7. //-----------------------------------------
  8. kp = 4.0;
  9. ki = 0.02;
  10. kd = 2.0;
  11. integral = 0;
  12. lastError = 0;
  13. // 积分最大值
  14. integralMax = 100;
  15. }
  16. //====================================================
  17. // 加热控制
  18. //====================================================
  19. double PID::calculate(double target, double current)
  20. {
  21. // PID执行周期
  22. const double dt = 0.5;
  23. double error = target - current;
  24. //-----------------------------------------
  25. // 1. 65℃以前
  26. //
  27. // 快速升温
  28. //-----------------------------------------
  29. if(current < 65.0)
  30. {
  31. integral = 0;
  32. lastError = error;
  33. return 100.0;
  34. }
  35. //-----------------------------------------
  36. // 2. 65~68℃
  37. //
  38. // 开始提前降低加热功率
  39. //
  40. // 65℃ -> 80%
  41. // 68℃ -> 40%
  42. //-----------------------------------------
  43. if(current < 68.0)
  44. {
  45. integral = 0;
  46. lastError = error;
  47. double duty = 80.0 - (current - 65.0) / 3.0 * 40.0;
  48. return qBound(0.0, duty, 100.0);
  49. }
  50. //-----------------------------------------
  51. // 3. 68℃以后
  52. //
  53. // 正式进入PID控温
  54. //-----------------------------------------
  55. //-----------------------------------------
  56. // 积分
  57. //-----------------------------------------
  58. integral += error * dt;
  59. integral = qBound(-integralMax,integral,integralMax);
  60. //-----------------------------------------
  61. // 微分
  62. //-----------------------------------------
  63. double derivative = (error - lastError) / dt;
  64. lastError = error;
  65. //-----------------------------------------
  66. // PID
  67. //-----------------------------------------
  68. double output =
  69. kp * error +
  70. ki * integral +
  71. kd * derivative;
  72. //-----------------------------------------
  73. // 4. 70℃附近
  74. //
  75. // 防止到达目标后继续大功率加热
  76. //-----------------------------------------
  77. if(current >= 70.0)
  78. {
  79. if(output > 25.0)
  80. output = 25.0;
  81. }
  82. //-----------------------------------------
  83. // 5. 71℃以后
  84. //
  85. // 进一步限制加热
  86. //-----------------------------------------
  87. if(current >= 71.0)
  88. {
  89. if(output > 10.0)
  90. output = 10.0;
  91. }
  92. //-----------------------------------------
  93. // 6. 72℃保护
  94. //
  95. // 超过控制范围,停止加热
  96. //-----------------------------------------
  97. if(current >= 72.0)
  98. {
  99. output = 0.0;
  100. // 清除积分,避免降温后仍然异常
  101. integral = 0;
  102. }
  103. //-----------------------------------------
  104. // 最终限幅
  105. //-----------------------------------------
  106. return qBound(0.0, output, 100.0);
  107. }
  108. //====================================================
  109. // 风扇控制
  110. //====================================================
  111. double PID::calculateFanDuty(double temp)
  112. {
  113. double duty;
  114. //-----------------------------------------
  115. // 68℃以前
  116. //
  117. // 固定10%
  118. //-----------------------------------------
  119. if(temp < 68.0)
  120. {
  121. duty = 10.0;
  122. }
  123. //-----------------------------------------
  124. // 68~72℃
  125. //
  126. // 10% -> 60%
  127. //-----------------------------------------
  128. else if(temp <= 72.0)
  129. {
  130. duty = 10.0 + (temp - 68.0) / 4.0 * 50.0;
  131. }
  132. //-----------------------------------------
  133. // 72~75℃
  134. //
  135. // 60% -> 100%
  136. //-----------------------------------------
  137. else if(temp <= 75.0)
  138. {
  139. duty = 60.0 + (temp - 72.0) / 3.0 * 40.0;
  140. }
  141. //-----------------------------------------
  142. // 75℃以上
  143. //
  144. // 全速
  145. //-----------------------------------------
  146. else
  147. {
  148. duty = 100.0;
  149. }
  150. return qBound(10.0, duty, 100.0);
  151. }
  152. //====================================================
  153. // 第二组风扇控制
  154. //====================================================
  155. double PID::calculateFanDuty1(double temp)
  156. {
  157. double duty;
  158. //-----------------------------------------
  159. // 30℃以下
  160. //-----------------------------------------
  161. if(temp <= 30.0)
  162. {
  163. duty = 10.0;
  164. }
  165. //-----------------------------------------
  166. // 30~40℃
  167. //
  168. // 0 -> 50%
  169. //-----------------------------------------
  170. else if(temp <= 40.0)
  171. {
  172. duty = (temp - 30.0) / 10.0 * 40.0;
  173. }
  174. //-----------------------------------------
  175. // 40~45℃
  176. //
  177. // 50 -> 100%
  178. //-----------------------------------------
  179. else if(temp <= 45.0)
  180. {
  181. duty = 50.0 + (temp - 40.0) / 5.0 * 50.0;
  182. }
  183. //-----------------------------------------
  184. // 45℃以上
  185. //-----------------------------------------
  186. else
  187. {
  188. duty = 100.0;
  189. }
  190. return qBound(0.0, duty, 100.0);
  191. }