PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

479 lines
15KB

  1. /* Test suite for the ADC library
  2. * Do not connect any pin of the board to anything while it's running
  3. * It uses the internal pulldown and pullup resistors to expose the pins to VDD or GND.
  4. */
  5. #include <ADC.h>
  6. #include <ADC_util.h>
  7. ADC *adc = new ADC(); // adc object
  8. #if defined(ADC_TEENSY_LC) // teensy LC
  9. #define PINS 13
  10. #define DIG_ADC_0_PINS 13
  11. #define DIG_ADC_1_PINS 0
  12. #define PINS_DIFF 2
  13. uint8_t adc_pins[] = {A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12};
  14. uint8_t adc_pins_dig_ADC_0[] = {A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12};
  15. uint8_t adc_pins_dig_ADC_1[] = {};
  16. uint8_t adc_pins_diff[] = {A10, A11};
  17. #elif defined(ADC_TEENSY_3_0) // teensy 3.0
  18. #define PINS 14
  19. #define DIG_ADC_0_PINS 10
  20. #define DIG_ADC_1_PINS 0
  21. #define PINS_DIFF 4
  22. uint8_t adc_pins[] = {A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13};
  23. uint8_t adc_pins_dig_ADC_0[] = {A0, A1, A2, A3, A4, A5, A6, A7, A8, A9};
  24. uint8_t adc_pins_dig_ADC_1[] = {};
  25. uint8_t adc_pins_diff[] = {A10, A11, A12, A13};
  26. #elif defined(ADC_TEENSY_3_1) || defined(ADC_TEENSY_3_2) // teensy 3.1/3.2
  27. #define PINS 21
  28. #define DIG_ADC_0_PINS 10
  29. #define DIG_ADC_1_PINS 8
  30. #define PINS_DIFF 4
  31. uint8_t adc_pins_dig_ADC_0[] = {
  32. A0,
  33. A1,
  34. A2,
  35. A3,
  36. A4,
  37. A5,
  38. A6,
  39. A7,
  40. A8,
  41. A9,
  42. };
  43. uint8_t adc_pins_dig_ADC_1[] = {A2, A3, A15, A16, A17, A18, A19, A20};
  44. uint8_t adc_pins_diff[] = {A10, A11, A12, A13};
  45. #elif defined(ADC_TEENSY_3_5) // Teensy 3.5
  46. #define PINS 27
  47. #define DIG_ADC_0_PINS 12
  48. #define DIG_ADC_1_PINS 11
  49. #define PINS_DIFF 2
  50. uint8_t adc_pins_dig_ADC_0[] = {A0, A1, A2, A3, A4, A5, A6, A7, A8, A9,
  51. A14, A15};
  52. uint8_t adc_pins_dig_ADC_1[] = {A2, A3, A12, A13, A16, A17, A18, A19, A20, A23, A24};
  53. uint8_t adc_pins_diff[] = {A10, A11};
  54. #elif defined(ADC_TEENSY_3_6) // Teensy 3.6
  55. #define PINS 25
  56. #define DIG_ADC_0_PINS 12
  57. #define DIG_ADC_1_PINS 11
  58. #define PINS_DIFF 2
  59. uint8_t adc_pins_dig_ADC_0[] = {A0, A1, A2, A3, A4, A5, A6, A7, A8, A9,
  60. A14, A15};
  61. uint8_t adc_pins_dig_ADC_1[] = {A2, A3, A12, A13, A16, A17, A18, A19, A20, A23, A24};
  62. uint8_t adc_pins_diff[] = {A10, A11};
  63. #elif defined(ADC_TEENSY_4) // Teensy 4
  64. #define PINS 14
  65. #define DIG_ADC_0_PINS 10
  66. #define DIG_ADC_1_PINS 10
  67. #define PINS_DIFF 0
  68. uint8_t adc_pins_dig_ADC_0[] = {A0, A1, A2, A3, A4, A5, A6, A7, A8, A9};
  69. uint8_t adc_pins_dig_ADC_1[] = {A0, A1, A2, A3, A4, A5, A6, A7, A8, A9};
  70. uint8_t adc_pins_diff[] = {};
  71. #elif defined(ADC_TEENSY_4_1) // Teensy 4.1
  72. #define PINS 18
  73. #define DIG_ADC_0_PINS 10
  74. #define DIG_ADC_1_PINS 10
  75. #define PINS_DIFF 0
  76. uint8_t adc_pins_dig_ADC_0[] = {A0, A1, A2, A3, A4, A5, A6, A7, A8, A9};
  77. uint8_t adc_pins_dig_ADC_1[] = {A0, A1, A2, A3, A4, A5, A6, A7, A8, A9};
  78. uint8_t adc_pins_diff[] = {};
  79. #endif // defined
  80. long int value = 0;
  81. #ifdef ADC_TEENSY_4
  82. const uint32_t num_samples = 10000;
  83. #else
  84. const uint32_t num_samples = 100;
  85. #endif
  86. // test the analog pins that also have a digital function
  87. // Teensy LC has 20-50 kOhm pullup, no idea about pulldown (do they exist?)
  88. // Teensy 3.0 has 22-50 kOhm pullup and pulldown
  89. // Teensy 3.1/3.2 has 20-50 kOhm pullup and pulldown
  90. // Teensy 3.5 has 20-50 kOhm pullup and pulldown
  91. // Teensy 3.6 has 20-50 kOhm pullup and pulldown
  92. // Teensy 4 has 100 kOhm pulldow, and 22 kOhm pullup, so pulldown will fail faster
  93. bool test_pullup_down(bool pullup, bool debug = false)
  94. {
  95. uint8_t mode = pullup ? INPUT_PULLUP : INPUT_PULLDOWN;
  96. const int max_val = adc->adc0->getMaxValue();
  97. bool pass_test = true;
  98. for (auto pin : adc_pins_dig_ADC_0)
  99. {
  100. pinMode(pin, mode);
  101. delay(10); // settle time
  102. value = adc->adc0->analogRead(pin);
  103. bool fail_condition = pullup ? (value < 0.95 * max_val) : (value > 0.05 * max_val);
  104. if (fail_condition)
  105. {
  106. if (debug)
  107. {
  108. Serial.print("Pin ");
  109. Serial.print(pin);
  110. Serial.print(": ");
  111. Serial.print("FAILED ");
  112. Serial.print(pullup ? "INPUT_PULLUP" : "INPUT_PULLDOWN");
  113. Serial.print("(");
  114. Serial.print(value);
  115. Serial.print(")");
  116. Serial.print("max_val: ");
  117. Serial.print(pullup ? (0.95 * max_val) : (0.05 * max_val));
  118. Serial.println(". ");
  119. }
  120. pass_test = false;
  121. }
  122. }
  123. #ifdef ADC_DUAL_ADCS
  124. for (auto pin : adc_pins_dig_ADC_1)
  125. {
  126. pinMode(pin, mode);
  127. delay(10); // settle time
  128. value = adc->adc1->analogRead(pin);
  129. bool fail_condition = pullup ? (value < 0.95 * max_val) : (value > 0.05 * max_val);
  130. if (fail_condition)
  131. {
  132. if (debug)
  133. {
  134. Serial.print("Pin ");
  135. Serial.print(pin);
  136. Serial.print(": ");
  137. Serial.print("FAILED ");
  138. Serial.print(pullup ? "INPUT_PULLUP" : "INPUT_PULLDOWN");
  139. Serial.print("(");
  140. Serial.print(value);
  141. Serial.print(")");
  142. Serial.print("max_val: ");
  143. Serial.print(pullup ? (0.95 * max_val) : (0.05 * max_val));
  144. Serial.println(". ");
  145. }
  146. pass_test = false;
  147. }
  148. }
  149. #endif
  150. return pass_test;
  151. }
  152. const uint8_t pin_cmp = A0;
  153. bool test_compare(bool debug = false)
  154. {
  155. bool pass_test = true;
  156. // measurement will be ready if value < 1.0V
  157. adc->adc0->enableCompare((int)(1.0 / 3.3 * adc->adc0->getMaxValue()), 0);
  158. pinMode(pin_cmp, INPUT_PULLUP); // set to max
  159. delay(10);
  160. // this should fail
  161. value = adc->adc0->analogRead(pin_cmp);
  162. if (adc->adc0->fail_flag != ADC_ERROR::COMPARISON)
  163. {
  164. if (debug)
  165. {
  166. Serial.println("Comparison didn't fail.");
  167. Serial.println(getStringADCError(adc->adc0->fail_flag));
  168. }
  169. pass_test = false;
  170. }
  171. adc->adc0->resetError();
  172. pinMode(pin_cmp, INPUT_PULLDOWN); // set to min
  173. delay(50);
  174. // this should be ok
  175. value = adc->adc0->analogRead(pin_cmp);
  176. if (adc->adc0->fail_flag == ADC_ERROR::COMPARISON)
  177. {
  178. if (debug)
  179. {
  180. Serial.println("Comparison didn't succeed.");
  181. Serial.println(getStringADCError(adc->adc0->fail_flag));
  182. Serial.println(value);
  183. }
  184. pass_test = false;
  185. }
  186. adc->adc0->resetError();
  187. adc->adc0->disableCompare();
  188. return pass_test;
  189. }
  190. bool test_compare_range(bool debug = false)
  191. {
  192. bool pass_test = true;
  193. // ready if value lies out of [1.0,2.0] V
  194. adc->adc0->enableCompareRange(1.0 * adc->adc0->getMaxValue() / 3.3, 2.0 * adc->adc0->getMaxValue() / 3.3, 0, 1);
  195. pinMode(pin_cmp, INPUT_PULLUP); // set to max
  196. // this should be ok
  197. value = adc->adc0->analogRead(pin_cmp);
  198. if (adc->adc0->fail_flag != ADC_ERROR::CLEAR)
  199. {
  200. if (debug)
  201. {
  202. Serial.println("Some other error happened when comparison should have succeeded.");
  203. Serial.println(getStringADCError(adc->adc0->fail_flag));
  204. }
  205. pass_test = false;
  206. }
  207. pinMode(pin_cmp, INPUT_PULLDOWN); // set to min
  208. adc->adc0->resetError();
  209. // this should be ok
  210. value = adc->adc0->analogRead(pin_cmp);
  211. if (adc->adc0->fail_flag != ADC_ERROR::CLEAR)
  212. {
  213. if (debug)
  214. {
  215. Serial.println("Some other error happened when comparison should have succeeded.");
  216. Serial.println(getStringADCError(adc->adc0->fail_flag));
  217. }
  218. pass_test = false;
  219. }
  220. adc->adc0->resetError();
  221. adc->adc0->disableCompare();
  222. return pass_test;
  223. }
  224. bool test_averages(bool debug = false)
  225. {
  226. elapsedMicros timeElapsed;
  227. bool pass_test = true;
  228. const uint8_t averages[] = {4, 8, 16, 32};
  229. float avg_times[4];
  230. volatile int value = 0;
  231. adc->adc0->setAveraging(1);
  232. timeElapsed = 0;
  233. for (uint32_t i = 0; i < num_samples; i++)
  234. {
  235. value += adc->adc0->analogRead(A0);
  236. }
  237. float one_avg_time = (float)timeElapsed / num_samples;
  238. // Serial.print("1: "); Serial.println(one_avg_time);
  239. // Serial.print("value: "); Serial.println(value/num_samples);
  240. for (uint8_t i = 0; i < 4; i++)
  241. {
  242. adc->adc0->setAveraging(averages[i]);
  243. timeElapsed = 0;
  244. value = 0;
  245. for (uint32_t j = 0; j < num_samples; j++)
  246. {
  247. value += adc->adc0->analogRead(A0);
  248. }
  249. float time = (float)timeElapsed / num_samples;
  250. avg_times[i] = time;
  251. // Serial.print(averages[i]); Serial.print(": "); Serial.print(time);
  252. // Serial.print(", "); Serial.println(time/one_avg_time);
  253. // Serial.print("value: "); Serial.println(value/num_samples);
  254. }
  255. // the 4 averages is not 4 times as long as the 1 average because
  256. // the first sample always takes longer, therefore the 4 avgs take about 3.5 times the first.
  257. // 8 avgs take twice as long as 4 and so on.
  258. // this is even worse for Teensy LC, where 4 avgs take about 2.6 more than none.
  259. if ((avg_times[0] < 2 * one_avg_time) || (avg_times[0] > 4 * one_avg_time))
  260. {
  261. pass_test = false;
  262. if (debug)
  263. {
  264. Serial.print("4 averages should take about 4 times longer than one, but it took ");
  265. Serial.print(avg_times[0] / one_avg_time);
  266. Serial.println(" times longer");
  267. }
  268. }
  269. // check that the times are between 80% and 120% their theoretical value.
  270. for (uint8_t i = 1; i < 4; i++)
  271. {
  272. if ((avg_times[i] < 2 * 0.8 * avg_times[i - 1]) || (avg_times[i] > 2 * 1.2 * avg_times[i - 1]))
  273. {
  274. pass_test = false;
  275. if (debug)
  276. {
  277. Serial.print(averages[i]);
  278. Serial.print(" averages should take about twice as long as ");
  279. Serial.print(averages[i - 1]);
  280. Serial.print(", but it took ");
  281. Serial.print(avg_times[i] / avg_times[i - 1]);
  282. Serial.println(" times longer.");
  283. }
  284. }
  285. }
  286. return pass_test;
  287. }
  288. bool test_all_combinations(bool debug = false)
  289. {
  290. bool pass_test = true;
  291. for (auto average : averages_list)
  292. {
  293. adc->adc0->setAveraging(average); // set number of averages
  294. adc->adc0->setAveraging(average); // set number of averages
  295. for (auto resolution : resolutions_list)
  296. {
  297. adc->adc0->setResolution(resolution); // set bits of resolution
  298. adc->adc0->setResolution(resolution); // set bits of resolution
  299. for (auto conv_speed : conversion_speed_list)
  300. {
  301. adc->adc0->setConversionSpeed(conv_speed); // change the conversion speed
  302. adc->adc0->setConversionSpeed(conv_speed); // change the conversion speed
  303. for (auto samp_speed : sampling_speed_list)
  304. {
  305. adc->adc0->setSamplingSpeed(samp_speed); // change the sampling speed
  306. adc->adc0->setSamplingSpeed(samp_speed); // change the sampling speed
  307. adc->adc0->wait_for_cal();
  308. #ifdef ADC_DUAL_ADCS
  309. adc->adc1->wait_for_cal();
  310. #endif
  311. bool test = test_pullup_down(true, false); // pullups have lower impedance for T4
  312. if (!test)
  313. {
  314. if (debug)
  315. {
  316. Serial.print("Average: ");
  317. Serial.print(average);
  318. Serial.print(", Resolution: ");
  319. Serial.print(resolution);
  320. Serial.print(", Conversion speed: ");
  321. Serial.print(getConversionEnumStr(conv_speed));
  322. Serial.print(", Sampling speed: ");
  323. Serial.print(getSamplingEnumStr(samp_speed));
  324. Serial.println(". PULLUP FAILED.");
  325. }
  326. // VERY_HIGH_SPEED are not guaranteed to work
  327. if ((conv_speed != ADC_CONVERSION_SPEED::VERY_HIGH_SPEED) || (samp_speed != ADC_SAMPLING_SPEED::VERY_HIGH_SPEED))
  328. {
  329. pass_test = false;
  330. }
  331. }
  332. digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN));
  333. }
  334. }
  335. }
  336. }
  337. return pass_test;
  338. }
  339. void resetSettings()
  340. {
  341. adc->adc0->setAveraging(16); // set number of averages
  342. adc->adc0->setResolution(12); // set bits of resolution
  343. adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::MED_SPEED); // change the conversion speed
  344. adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::MED_SPEED); // change the sampling speed
  345. #ifdef ADC_DUAL_ADCS
  346. adc->adc1->setAveraging(16); // set number of averages
  347. adc->adc1->setResolution(12); // set bits of resolution
  348. adc->adc1->setConversionSpeed(ADC_CONVERSION_SPEED::MED_SPEED); // change the conversion speed
  349. adc->adc1->setSamplingSpeed(ADC_SAMPLING_SPEED::MED_SPEED); // change the sampling speed
  350. adc->adc1->recalibrate();
  351. #endif
  352. }
  353. void setup()
  354. {
  355. pinMode(LED_BUILTIN, OUTPUT);
  356. Serial.begin(9600);
  357. ///// ADC0 ////
  358. // reference can be ADC_REFERENCE::REF_3V3, ADC_REFERENCE::REF_1V2 (not for Teensy LC) or ADC_REFERENCE::REF_EXT.
  359. //adc->setReference(ADC_REFERENCE::REF_1V2, ADC_0); // change all 3.3 to 1.2 if you change the reference to 1V2
  360. adc->adc0->setAveraging(16); // set number of averages
  361. adc->adc0->setResolution(12); // set bits of resolution
  362. adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::MED_SPEED); // change the conversion speed
  363. adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::MED_SPEED); // change the sampling speed
  364. adc->adc0->recalibrate();
  365. ////// ADC1 /////
  366. #ifdef ADC_DUAL_ADCS
  367. adc->adc1->setAveraging(16); // set number of averages
  368. adc->adc1->setResolution(12); // set bits of resolution
  369. adc->adc1->setConversionSpeed(ADC_CONVERSION_SPEED::MED_SPEED); // change the conversion speed
  370. adc->adc1->setSamplingSpeed(ADC_SAMPLING_SPEED::MED_SPEED); // change the sampling speed
  371. adc->adc1->recalibrate();
  372. #endif
  373. delay(2000);
  374. ////// START TESTS /////////////
  375. // do the tests
  376. bool pullup_test = test_pullup_down(true, false);
  377. resetSettings();
  378. Serial.print("PULLUP TEST ");
  379. Serial.println(pullup_test ? "PASS" : "FAIL");
  380. bool pulldown_test = test_pullup_down(false, false);
  381. resetSettings();
  382. Serial.print("PULLDOWN TEST ");
  383. Serial.println(pulldown_test ? "PASS" : "FAIL");
  384. bool compare_test = test_compare(true);
  385. resetSettings();
  386. Serial.print("COMPARE TEST ");
  387. Serial.println(compare_test ? "PASS" : "FAIL");
  388. bool compare_range_test = test_compare_range(true);
  389. resetSettings();
  390. Serial.print("COMPARE RANGE TEST ");
  391. Serial.println(compare_range_test ? "PASS" : "FAIL");
  392. bool averages_test = test_averages(true);
  393. resetSettings();
  394. Serial.print("AVERAGES TEST ");
  395. Serial.println(averages_test ? "PASS" : "FAIL");
  396. bool all_combinations_test = test_all_combinations(true);
  397. resetSettings();
  398. Serial.print("ALL COMBINATIONS TEST ");
  399. Serial.println(all_combinations_test ? "PASS" : "FAIL");
  400. if (pullup_test & pulldown_test & compare_test & compare_range_test & averages_test & all_combinations_test)
  401. {
  402. Serial.println("ALL TEST PASSED.");
  403. }
  404. }
  405. void loop()
  406. {
  407. // Print errors, if any.
  408. if (adc->adc0->fail_flag != ADC_ERROR::CLEAR)
  409. {
  410. Serial.print("ADC0: ");
  411. Serial.println(getStringADCError(adc->adc0->fail_flag));
  412. }
  413. #ifdef ADC_DUAL_ADCS
  414. if (adc->adc1->fail_flag != ADC_ERROR::CLEAR)
  415. {
  416. Serial.print("ADC1: ");
  417. Serial.println(getStringADCError(adc->adc1->fail_flag));
  418. }
  419. #endif
  420. adc->resetError();
  421. digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN));
  422. delay(500);
  423. }