test_pid.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. #include "test.h"
  2. #include "pid.c"
  3. #include "util.c"
  4. #include "fixpt.c"
  5. static void check_common(void)
  6. {
  7. /* Check get/set setpoint */
  8. {
  9. struct pid pid;
  10. struct pid_k_set k;
  11. k.kp = float_to_fixpt(1.0);
  12. k.ki = float_to_fixpt(0.0);
  13. k.kd = float_to_fixpt(0.0);
  14. k.d_decay_div = float_to_fixpt(1.0);
  15. pid_init(&pid, &k,
  16. float_to_fixpt(-15.0), // I -lim
  17. float_to_fixpt(15.0), // I +lim
  18. float_to_fixpt(-15.0), // -lim
  19. float_to_fixpt(15.0)); // +lim
  20. pid_set_setpoint(&pid, int_to_fixpt(10));
  21. CHECK(pid_get_setpoint(&pid) == float_to_fixpt(10.0));
  22. }
  23. }
  24. static void check_P(void)
  25. {
  26. /* Check P-term with KP=1 */
  27. {
  28. struct pid pid;
  29. struct pid_k_set k;
  30. fixpt_t ret;
  31. k.kp = float_to_fixpt(1.0);
  32. k.ki = float_to_fixpt(0.0);
  33. k.kd = float_to_fixpt(0.0);
  34. k.d_decay_div = float_to_fixpt(1.0);
  35. pid_init(&pid, &k,
  36. float_to_fixpt(-15.0), // I -lim
  37. float_to_fixpt(15.0), // I +lim
  38. float_to_fixpt(-15.0), // -lim
  39. float_to_fixpt(15.0)); // +lim
  40. pid_set_setpoint(&pid, int_to_fixpt(10));
  41. ret = pid_run(&pid,
  42. float_to_fixpt(1.0), // dt
  43. float_to_fixpt(1.0)); // r
  44. CHECK(ret == float_to_fixpt(9.0));
  45. ret = pid_run(&pid,
  46. float_to_fixpt(1.0), // dt
  47. float_to_fixpt(2.0)); // r
  48. CHECK(ret == float_to_fixpt(8.0));
  49. ret = pid_run(&pid,
  50. float_to_fixpt(1.0), // dt
  51. float_to_fixpt(5.0)); // r
  52. CHECK(ret == float_to_fixpt(5.0));
  53. ret = pid_run(&pid,
  54. float_to_fixpt(1.0), // dt
  55. float_to_fixpt(5.0)); // r
  56. CHECK(ret == float_to_fixpt(5.0));
  57. }
  58. /* Check P-term with KP=3 */
  59. {
  60. struct pid pid;
  61. struct pid_k_set k;
  62. fixpt_t ret;
  63. k.kp = float_to_fixpt(3.0);
  64. k.ki = float_to_fixpt(0.0);
  65. k.kd = float_to_fixpt(0.0);
  66. k.d_decay_div = float_to_fixpt(1.0);
  67. pid_init(&pid, &k,
  68. float_to_fixpt(-15.0), // I -lim
  69. float_to_fixpt(15.0), // I +lim
  70. float_to_fixpt(-15.0), // -lim
  71. float_to_fixpt(15.0)); // +lim
  72. pid_set_setpoint(&pid, int_to_fixpt(10));
  73. ret = pid_run(&pid,
  74. float_to_fixpt(1.0), // dt
  75. float_to_fixpt(1.0)); // r
  76. CHECK(ret == float_to_fixpt(15.0));
  77. ret = pid_run(&pid,
  78. float_to_fixpt(1.5), // dt
  79. float_to_fixpt(2.0)); // r
  80. CHECK(ret == float_to_fixpt(15.0));
  81. ret = pid_run(&pid,
  82. float_to_fixpt(2.0), // dt
  83. float_to_fixpt(5.0)); // r
  84. CHECK(ret == float_to_fixpt(15.0));
  85. ret = pid_run(&pid,
  86. float_to_fixpt(1.0), // dt
  87. float_to_fixpt(7.0)); // r
  88. CHECK(ret == float_to_fixpt(9.0));
  89. ret = pid_run(&pid,
  90. float_to_fixpt(1.0), // dt
  91. float_to_fixpt(7.5)); // r
  92. CHECK(ret == float_to_fixpt(7.5));
  93. }
  94. /* Check P-term with KP=2.5 */
  95. {
  96. struct pid pid;
  97. struct pid_k_set k;
  98. fixpt_t ret;
  99. k.kp = float_to_fixpt(2.5);
  100. k.ki = float_to_fixpt(0.0);
  101. k.kd = float_to_fixpt(0.0);
  102. k.d_decay_div = float_to_fixpt(1.0);
  103. pid_init(&pid, &k,
  104. float_to_fixpt(-15.0), // I -lim
  105. float_to_fixpt(15.0), // I +lim
  106. float_to_fixpt(-15.0), // -lim
  107. float_to_fixpt(15.0)); // +lim
  108. pid_set_setpoint(&pid, int_to_fixpt(10));
  109. ret = pid_run(&pid,
  110. float_to_fixpt(1.0), // dt
  111. float_to_fixpt(1.0)); // r
  112. CHECK(ret == float_to_fixpt(15.0));
  113. ret = pid_run(&pid,
  114. float_to_fixpt(1.0), // dt
  115. float_to_fixpt(2.0)); // r
  116. CHECK(ret == float_to_fixpt(15.0));
  117. ret = pid_run(&pid,
  118. float_to_fixpt(1.0), // dt
  119. float_to_fixpt(5.0)); // r
  120. CHECK(ret == float_to_fixpt(12.5));
  121. ret = pid_run(&pid,
  122. float_to_fixpt(1.0), // dt
  123. float_to_fixpt(7.0)); // r
  124. CHECK(ret == float_to_fixpt(7.5));
  125. ret = pid_run(&pid,
  126. float_to_fixpt(1.0), // dt
  127. float_to_fixpt(7.5)); // r
  128. CHECK(ret == float_to_fixpt(6.25));
  129. }
  130. /* Check P-term with KP=-2.5 */
  131. {
  132. struct pid pid;
  133. struct pid_k_set k;
  134. fixpt_t ret;
  135. k.kp = float_to_fixpt(-2.5);
  136. k.ki = float_to_fixpt(0.0);
  137. k.kd = float_to_fixpt(0.0);
  138. k.d_decay_div = float_to_fixpt(1.0);
  139. pid_init(&pid, &k,
  140. float_to_fixpt(-15.0), // I -lim
  141. float_to_fixpt(15.0), // I +lim
  142. float_to_fixpt(-15.0), // -lim
  143. float_to_fixpt(15.0)); // +lim
  144. pid_set_setpoint(&pid, int_to_fixpt(10));
  145. ret = pid_run(&pid,
  146. float_to_fixpt(1.0), // dt
  147. float_to_fixpt(1.0)); // r
  148. CHECK(ret == float_to_fixpt(-15.0));
  149. ret = pid_run(&pid,
  150. float_to_fixpt(1.0), // dt
  151. float_to_fixpt(2.0)); // r
  152. CHECK(ret == float_to_fixpt(-15.0));
  153. ret = pid_run(&pid,
  154. float_to_fixpt(1.0), // dt
  155. float_to_fixpt(5.0)); // r
  156. CHECK(ret == float_to_fixpt(-12.5));
  157. ret = pid_run(&pid,
  158. float_to_fixpt(1.0), // dt
  159. float_to_fixpt(7.0)); // r
  160. CHECK(ret == float_to_fixpt(-7.5));
  161. ret = pid_run(&pid,
  162. float_to_fixpt(1.0), // dt
  163. float_to_fixpt(7.5)); // r
  164. CHECK(ret == float_to_fixpt(-6.25));
  165. }
  166. }
  167. static void check_I(void)
  168. {
  169. /* Check I-term with KI=1 */
  170. {
  171. struct pid pid;
  172. struct pid_k_set k;
  173. fixpt_t ret;
  174. k.kp = float_to_fixpt(0.0);
  175. k.ki = float_to_fixpt(1.0);
  176. k.kd = float_to_fixpt(0.0);
  177. k.d_decay_div = float_to_fixpt(1.0);
  178. pid_init(&pid, &k,
  179. float_to_fixpt(-15.0), // I -lim
  180. float_to_fixpt(15.0), // I +lim
  181. float_to_fixpt(-15.0), // -lim
  182. float_to_fixpt(15.0)); // +lim
  183. pid_set_setpoint(&pid, int_to_fixpt(10));
  184. ret = pid_run(&pid,
  185. float_to_fixpt(1.0), // dt
  186. float_to_fixpt(9.0)); // r
  187. CHECK(ret == float_to_fixpt(1.0));
  188. ret = pid_run(&pid,
  189. float_to_fixpt(1.0), // dt
  190. float_to_fixpt(9.0)); // r
  191. CHECK(ret == float_to_fixpt(2.0));
  192. ret = pid_run(&pid,
  193. float_to_fixpt(1.0), // dt
  194. float_to_fixpt(9.0)); // r
  195. CHECK(ret == float_to_fixpt(3.0));
  196. ret = pid_run(&pid,
  197. float_to_fixpt(1.0), // dt
  198. float_to_fixpt(10.0)); // r
  199. CHECK(ret == float_to_fixpt(3.0));
  200. ret = pid_run(&pid,
  201. float_to_fixpt(1.0), // dt
  202. float_to_fixpt(11.0)); // r
  203. CHECK(ret == float_to_fixpt(2.0));
  204. ret = pid_run(&pid,
  205. float_to_fixpt(3.0), // dt
  206. float_to_fixpt(11.0)); // r
  207. CHECK(ret == float_to_fixpt(-1.0));
  208. ret = pid_run(&pid,
  209. float_to_fixpt(0.5), // dt
  210. float_to_fixpt(11.0)); // r
  211. CHECK(ret == float_to_fixpt(-1.5));
  212. ret = pid_run(&pid,
  213. float_to_fixpt(0.5), // dt
  214. float_to_fixpt(11.0)); // r
  215. CHECK(ret == float_to_fixpt(-2.0));
  216. }
  217. /* Check I-term with KI=-1 */
  218. {
  219. struct pid pid;
  220. struct pid_k_set k;
  221. fixpt_t ret;
  222. k.kp = float_to_fixpt(0.0);
  223. k.ki = float_to_fixpt(-1.0);
  224. k.kd = float_to_fixpt(0.0);
  225. k.d_decay_div = float_to_fixpt(1.0);
  226. pid_init(&pid, &k,
  227. float_to_fixpt(-15.0), // I -lim
  228. float_to_fixpt(15.0), // I +lim
  229. float_to_fixpt(-15.0), // -lim
  230. float_to_fixpt(15.0)); // +lim
  231. pid_set_setpoint(&pid, int_to_fixpt(10));
  232. ret = pid_run(&pid,
  233. float_to_fixpt(1.0), // dt
  234. float_to_fixpt(9.0)); // r
  235. CHECK(ret == float_to_fixpt(-1.0));
  236. ret = pid_run(&pid,
  237. float_to_fixpt(1.0), // dt
  238. float_to_fixpt(9.0)); // r
  239. CHECK(ret == float_to_fixpt(-2.0));
  240. ret = pid_run(&pid,
  241. float_to_fixpt(1.0), // dt
  242. float_to_fixpt(9.0)); // r
  243. CHECK(ret == float_to_fixpt(-3.0));
  244. ret = pid_run(&pid,
  245. float_to_fixpt(1.0), // dt
  246. float_to_fixpt(10.0)); // r
  247. CHECK(ret == float_to_fixpt(-3.0));
  248. ret = pid_run(&pid,
  249. float_to_fixpt(1.0), // dt
  250. float_to_fixpt(11.0)); // r
  251. CHECK(ret == float_to_fixpt(-2.0));
  252. ret = pid_run(&pid,
  253. float_to_fixpt(3.0), // dt
  254. float_to_fixpt(11.0)); // r
  255. CHECK(ret == float_to_fixpt(1.0));
  256. ret = pid_run(&pid,
  257. float_to_fixpt(0.5), // dt
  258. float_to_fixpt(11.0)); // r
  259. CHECK(ret == float_to_fixpt(1.5));
  260. ret = pid_run(&pid,
  261. float_to_fixpt(0.5), // dt
  262. float_to_fixpt(11.0)); // r
  263. CHECK(ret == float_to_fixpt(2.0));
  264. }
  265. /* Check I-term with KI=1.5 */
  266. {
  267. struct pid pid;
  268. struct pid_k_set k;
  269. fixpt_t ret;
  270. k.kp = float_to_fixpt(0.0);
  271. k.ki = float_to_fixpt(1.5);
  272. k.kd = float_to_fixpt(0.0);
  273. k.d_decay_div = float_to_fixpt(1.0);
  274. pid_init(&pid, &k,
  275. float_to_fixpt(-15.0), // I -lim
  276. float_to_fixpt(15.0), // I +lim
  277. float_to_fixpt(-15.0), // -lim
  278. float_to_fixpt(15.0)); // +lim
  279. pid_set_setpoint(&pid, int_to_fixpt(10));
  280. ret = pid_run(&pid,
  281. float_to_fixpt(1.0), // dt
  282. float_to_fixpt(9.0)); // r
  283. CHECK(ret == float_to_fixpt(1.5));
  284. ret = pid_run(&pid,
  285. float_to_fixpt(1.0), // dt
  286. float_to_fixpt(9.0)); // r
  287. CHECK(ret == float_to_fixpt(3.0));
  288. ret = pid_run(&pid,
  289. float_to_fixpt(1.0), // dt
  290. float_to_fixpt(9.0)); // r
  291. CHECK(ret == float_to_fixpt(4.5));
  292. ret = pid_run(&pid,
  293. float_to_fixpt(1.0), // dt
  294. float_to_fixpt(10.0)); // r
  295. CHECK(ret == float_to_fixpt(4.5));
  296. ret = pid_run(&pid,
  297. float_to_fixpt(1.0), // dt
  298. float_to_fixpt(11.0)); // r
  299. CHECK(ret == float_to_fixpt(3.0));
  300. ret = pid_run(&pid,
  301. float_to_fixpt(3.0), // dt
  302. float_to_fixpt(11.0)); // r
  303. CHECK(ret == float_to_fixpt(-1.5));
  304. ret = pid_run(&pid,
  305. float_to_fixpt(0.5), // dt
  306. float_to_fixpt(11.0)); // r
  307. CHECK(ret == float_to_fixpt(-2.25));
  308. ret = pid_run(&pid,
  309. float_to_fixpt(0.5), // dt
  310. float_to_fixpt(11.0)); // r
  311. CHECK(ret == float_to_fixpt(-3.0));
  312. }
  313. }
  314. static void check_D(void)
  315. {
  316. /* Check D-term with KD=1 */
  317. {
  318. struct pid pid;
  319. struct pid_k_set k;
  320. fixpt_t ret;
  321. k.kp = float_to_fixpt(0.0);
  322. k.ki = float_to_fixpt(0.0);
  323. k.kd = float_to_fixpt(1.0);
  324. k.d_decay_div = float_to_fixpt(1.0);
  325. pid_init(&pid, &k,
  326. float_to_fixpt(-15.0), // I -lim
  327. float_to_fixpt(15.0), // I +lim
  328. float_to_fixpt(-15.0), // -lim
  329. float_to_fixpt(15.0)); // +lim
  330. pid_set_setpoint(&pid, int_to_fixpt(10));
  331. ret = pid_run(&pid,
  332. float_to_fixpt(1.0), // dt
  333. float_to_fixpt(9.0)); // r
  334. CHECK(ret == float_to_fixpt(1.0));
  335. ret = pid_run(&pid,
  336. float_to_fixpt(1.0), // dt
  337. float_to_fixpt(8.0)); // r
  338. CHECK(ret == float_to_fixpt(1.0));
  339. ret = pid_run(&pid,
  340. float_to_fixpt(1.0), // dt
  341. float_to_fixpt(7.0)); // r
  342. CHECK(ret == float_to_fixpt(1.0));
  343. ret = pid_run(&pid,
  344. float_to_fixpt(1.0), // dt
  345. float_to_fixpt(5.0)); // r
  346. CHECK(ret == float_to_fixpt(2.0));
  347. ret = pid_run(&pid,
  348. float_to_fixpt(1.0), // dt
  349. float_to_fixpt(5.0)); // r
  350. CHECK(ret == float_to_fixpt(0.0));
  351. ret = pid_run(&pid,
  352. float_to_fixpt(1.0), // dt
  353. float_to_fixpt(7.0)); // r
  354. CHECK(ret == float_to_fixpt(-2.0));
  355. }
  356. /* Check D-term with KD=-1 */
  357. {
  358. struct pid pid;
  359. struct pid_k_set k;
  360. fixpt_t ret;
  361. k.kp = float_to_fixpt(0.0);
  362. k.ki = float_to_fixpt(0.0);
  363. k.kd = float_to_fixpt(-1.0);
  364. k.d_decay_div = float_to_fixpt(1.0);
  365. pid_init(&pid, &k,
  366. float_to_fixpt(-15.0), // I -lim
  367. float_to_fixpt(15.0), // I +lim
  368. float_to_fixpt(-15.0), // -lim
  369. float_to_fixpt(15.0)); // +lim
  370. pid_set_setpoint(&pid, int_to_fixpt(10));
  371. ret = pid_run(&pid,
  372. float_to_fixpt(1.0), // dt
  373. float_to_fixpt(9.0)); // r
  374. CHECK(ret == float_to_fixpt(-1.0));
  375. ret = pid_run(&pid,
  376. float_to_fixpt(1.0), // dt
  377. float_to_fixpt(8.0)); // r
  378. CHECK(ret == float_to_fixpt(-1.0));
  379. ret = pid_run(&pid,
  380. float_to_fixpt(1.0), // dt
  381. float_to_fixpt(7.0)); // r
  382. CHECK(ret == float_to_fixpt(-1.0));
  383. ret = pid_run(&pid,
  384. float_to_fixpt(1.0), // dt
  385. float_to_fixpt(5.0)); // r
  386. CHECK(ret == float_to_fixpt(-2.0));
  387. ret = pid_run(&pid,
  388. float_to_fixpt(1.0), // dt
  389. float_to_fixpt(5.0)); // r
  390. CHECK(ret == float_to_fixpt(0.0));
  391. ret = pid_run(&pid,
  392. float_to_fixpt(1.0), // dt
  393. float_to_fixpt(7.0)); // r
  394. CHECK(ret == float_to_fixpt(2.0));
  395. }
  396. /* Check D-term with KD=1.5 */
  397. {
  398. struct pid pid;
  399. struct pid_k_set k;
  400. fixpt_t ret;
  401. k.kp = float_to_fixpt(0.0);
  402. k.ki = float_to_fixpt(0.0);
  403. k.kd = float_to_fixpt(1.5);
  404. k.d_decay_div = float_to_fixpt(1.0);
  405. pid_init(&pid, &k,
  406. float_to_fixpt(-15.0), // I -lim
  407. float_to_fixpt(15.0), // I +lim
  408. float_to_fixpt(-15.0), // -lim
  409. float_to_fixpt(15.0)); // +lim
  410. pid_set_setpoint(&pid, int_to_fixpt(10));
  411. ret = pid_run(&pid,
  412. float_to_fixpt(1.0), // dt
  413. float_to_fixpt(9.0)); // r
  414. CHECK(ret == float_to_fixpt(1.5));
  415. ret = pid_run(&pid,
  416. float_to_fixpt(1.0), // dt
  417. float_to_fixpt(8.0)); // r
  418. CHECK(ret == float_to_fixpt(1.5));
  419. ret = pid_run(&pid,
  420. float_to_fixpt(1.0), // dt
  421. float_to_fixpt(7.0)); // r
  422. CHECK(ret == float_to_fixpt(1.5));
  423. ret = pid_run(&pid,
  424. float_to_fixpt(1.0), // dt
  425. float_to_fixpt(5.0)); // r
  426. CHECK(ret == float_to_fixpt(3.0));
  427. ret = pid_run(&pid,
  428. float_to_fixpt(1.0), // dt
  429. float_to_fixpt(5.0)); // r
  430. CHECK(ret == float_to_fixpt(0.0));
  431. ret = pid_run(&pid,
  432. float_to_fixpt(1.0), // dt
  433. float_to_fixpt(7.0)); // r
  434. CHECK(ret == float_to_fixpt(-3.0));
  435. }
  436. }
  437. static void check_PID(void)
  438. {
  439. /* Check PID with KP=1.5, KI=1.5, KD=1.5 */
  440. {
  441. struct pid pid;
  442. struct pid_k_set k;
  443. fixpt_t ret;
  444. k.kp = float_to_fixpt(1.5);
  445. k.ki = float_to_fixpt(1.5);
  446. k.kd = float_to_fixpt(1.5);
  447. k.d_decay_div = float_to_fixpt(1.0);
  448. pid_init(&pid, &k,
  449. float_to_fixpt(-15.0), // I -lim
  450. float_to_fixpt(15.0), // I +lim
  451. float_to_fixpt(-15.0), // -lim
  452. float_to_fixpt(15.0)); // +lim
  453. pid_set_setpoint(&pid, int_to_fixpt(10));
  454. ret = pid_run(&pid,
  455. float_to_fixpt(1.0), // dt
  456. float_to_fixpt(9.0)); // r
  457. CHECK(ret == float_to_fixpt(4.5)); // (integr=1.5)
  458. ret = pid_run(&pid,
  459. float_to_fixpt(1.0), // dt
  460. float_to_fixpt(8.0)); // r
  461. CHECK(ret == float_to_fixpt(9.0)); // (integr=4.5)
  462. ret = pid_run(&pid,
  463. float_to_fixpt(1.0), // dt
  464. float_to_fixpt(8.0)); // r
  465. CHECK(ret == float_to_fixpt(10.5)); // (integr=7.5)
  466. ret = pid_run(&pid,
  467. float_to_fixpt(1.0), // dt
  468. float_to_fixpt(9.0)); // r
  469. CHECK(ret == float_to_fixpt(9.0)); // (integr=9.0)
  470. }
  471. }
  472. int main(void)
  473. {
  474. check_common();
  475. check_P();
  476. check_I();
  477. check_D();
  478. check_PID();
  479. return 0;
  480. }