PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

209 lines
6.9KB

  1. /* Example for triggering the ADC with Timer
  2. Valid for the current Teensy 3.x and 4.0.
  3. On Teensy 3.x this uses the PDB timer, and should work the same as the example adc_pdb.ino, but
  4. has been extended some to add additional command to read in a whole buffer of readings, using the
  5. timer.
  6. On Teensy 4, this uses one or two of the unused QTimers.
  7. Setting it up: The variables readPin must be defined for a pin that is valid for the first (or only)
  8. ADC. If the processor has a second ADC and is enabled, than readPin2 must be configured to be a pin
  9. that is valid on the second ADC.
  10. Example usage:
  11. Start the timers at some frequency: s 3000<cr>
  12. get a single read from the ADC(s): v<cr>
  13. print out the actual frequency: p<cr>
  14. Read in a whole buffer and print out data: t<cr>
  15. Stop the timers: s<cr>
  16. */
  17. #ifdef ADC_USE_TIMER
  18. #include <ADC.h>
  19. #include <ADC_util.h>
  20. const int readPin = A0; // ADC0
  21. #ifdef ADC_DUAL_ADCS
  22. const int readPin2 = A2; // ADC1
  23. #endif
  24. ADC *adc = new ADC(); // adc object;
  25. #define USE_ADC_0
  26. #define USE_ADC_1
  27. #define BUFFER_SIZE 500
  28. uint16_t buffer_ADC_0[BUFFER_SIZE];
  29. uint16_t buffer_adc_0_count = 0xffff;
  30. uint32_t delta_time_adc_0 = 0;
  31. uint16_t buffer_ADC_1[BUFFER_SIZE];
  32. uint16_t buffer_adc_1_count = 0xffff;
  33. uint32_t delta_time_adc_1 = 0;
  34. elapsedMillis timed_read_elapsed;
  35. void setup() {
  36. pinMode(LED_BUILTIN, OUTPUT);
  37. pinMode(readPin, INPUT);
  38. Serial.begin(9600);
  39. while (!Serial && millis() < 5000) ; // wait up to 5 seconds for serial monitor.
  40. Serial.println("Begin setup");
  41. ///// ADC0 ////
  42. adc->adc0->setAveraging(1); // set number of averages
  43. adc->adc0->setResolution(8); // set bits of resolution
  44. adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::VERY_HIGH_SPEED); // change the conversion speed
  45. adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED); // change the sampling speed
  46. ////// ADC1 /////
  47. #ifdef ADC_DUAL_ADCS
  48. pinMode(readPin2, INPUT);
  49. adc->adc1->setAveraging(1); // set number of averages
  50. adc->adc1->setResolution(8); // set bits of resolution
  51. adc->adc1->setConversionSpeed(ADC_CONVERSION_SPEED::VERY_HIGH_SPEED); // change the conversion speed
  52. adc->adc1->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED); // change the sampling speed
  53. #endif
  54. Serial.println("End setup");
  55. Serial.println("Enter a command such as: s 3000<cr> to start doing something");
  56. }
  57. char c = 0;
  58. int value;
  59. int value2;
  60. void loop() {
  61. if (Serial.available()) {
  62. c = Serial.read();
  63. if (c == 'v') { // value
  64. Serial.print("Value ADC0: ");
  65. value = (uint16_t)adc->adc0->readSingle(); // the unsigned is necessary for 16 bits, otherwise values larger than 3.3/2 V are negative!
  66. Serial.printf("%d = ", value);
  67. Serial.println(value * 3.3 / adc->adc0->getMaxValue(), DEC);
  68. #if defined(ADC_DUAL_ADCS) && defined(USE_ADC_1)
  69. Serial.print("Value ADC1: ");
  70. value2 = (uint16_t)adc->adc1->readSingle(); // the unsigned is necessary for 16 bits, otherwise values larger than 3.3/2 V are negative!
  71. Serial.printf("%d = ", value2);
  72. Serial.println(value2 * 3.3 / adc->adc1->getMaxValue(), DEC);
  73. #endif
  74. } else if (c == 's') { // start Timer, before pressing enter write the frequency in Hz
  75. uint32_t freq = Serial.parseInt();
  76. if (freq == 0) {
  77. Serial.println("Stop Timer.");
  78. adc->adc0->stopTimer();
  79. #ifdef ADC_DUAL_ADCS
  80. adc->adc1->stopTimer();
  81. #endif
  82. }
  83. else {
  84. Serial.print("Start Timer with frequency ");
  85. Serial.print(freq);
  86. Serial.println(" Hz.");
  87. adc->adc0->stopTimer();
  88. adc->adc0->startSingleRead(readPin); // call this to setup everything before the Timer starts, differential is also possible
  89. adc->adc0->enableInterrupts(adc0_isr);
  90. adc->adc0->startTimer(freq); //frequency in Hz
  91. #if defined(ADC_DUAL_ADCS) && defined(USE_ADC_1)
  92. adc->adc1->stopTimer();
  93. adc->adc1->startSingleRead(readPin2); // call this to setup everything before the Timer starts
  94. adc->adc1->enableInterrupts(adc1_isr);
  95. adc->adc1->startTimer(freq); //frequency in Hz
  96. #endif
  97. }
  98. } else if (c == 'p') { // print Timer stats
  99. Serial.print("Frequency: ");
  100. Serial.println(adc->adc0->getTimerFrequency());
  101. } else if (c == 't') { // Lets try a timed read
  102. timed_read_elapsed = 0;
  103. buffer_adc_0_count = 0;
  104. buffer_adc_1_count = 0;
  105. Serial.println("Starting Timed read");
  106. }
  107. }
  108. // Print errors, if any.
  109. if (adc->adc0->fail_flag != ADC_ERROR::CLEAR) {
  110. Serial.print("ADC0: "); Serial.println(getStringADCError(adc->adc0->fail_flag));
  111. }
  112. #if defined(ADC_DUAL_ADCS) && defined(USE_ADC_1)
  113. if (adc->adc1->fail_flag != ADC_ERROR::CLEAR) {
  114. Serial.print("ADC1: "); Serial.println(getStringADCError(adc->adc1->fail_flag));
  115. }
  116. #endif
  117. adc->resetError();
  118. // See if we have a timed read test that finished.
  119. if (delta_time_adc_0) printTimedADCInfo(ADC_0, buffer_ADC_0, delta_time_adc_0);
  120. if (delta_time_adc_1) printTimedADCInfo(ADC_1, buffer_ADC_1, delta_time_adc_1);
  121. //digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN));
  122. delay(10);
  123. }
  124. void printTimedADCInfo(uint8_t adc_num, uint16_t *buffer, uint32_t &delta_time) {
  125. uint32_t min_value = 0xffff;
  126. uint32_t max_value = 0;
  127. uint32_t sum = 0;
  128. for (int i = 0; i < BUFFER_SIZE; i++) {
  129. if (buffer[i] < min_value) min_value = buffer[i];
  130. if (buffer[i] > max_value) max_value = buffer[i];
  131. sum += buffer[i];
  132. }
  133. float average_value = (float)sum / BUFFER_SIZE; // get an average...
  134. float sum_delta_sq = 0;
  135. for (int i = 0; i < BUFFER_SIZE; i++) {
  136. int delta_from_center = (int)buffer[i] - average_value;
  137. sum_delta_sq += delta_from_center * delta_from_center;
  138. }
  139. int rms = sqrt(sum_delta_sq / BUFFER_SIZE);
  140. Serial.printf("ADC:%d delta time:%d freq:%d - min:%d max:%d avg:%d rms:%d\n", adc_num,
  141. delta_time, (1000 * BUFFER_SIZE) / delta_time,
  142. min_value, max_value, (int)average_value, rms);
  143. delta_time = 0;
  144. }
  145. // Make sure to call readSingle() to clear the interrupt.
  146. void adc0_isr() {
  147. uint16_t adc_val = adc->adc0->readSingle();
  148. if (buffer_adc_0_count < BUFFER_SIZE) {
  149. buffer_ADC_0[buffer_adc_0_count++] = adc_val;
  150. if (buffer_adc_0_count == BUFFER_SIZE) delta_time_adc_0 = timed_read_elapsed;
  151. }
  152. digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN) );
  153. #if defined(__IMXRT1062__) // Teensy 4.0
  154. asm("DSB");
  155. #endif
  156. }
  157. #ifdef ADC_DUAL_ADCS
  158. void adc1_isr() {
  159. uint16_t adc_val = adc->adc1->readSingle();
  160. if (buffer_adc_1_count < BUFFER_SIZE) {
  161. buffer_ADC_1[buffer_adc_1_count++] = adc_val;
  162. if (buffer_adc_1_count == BUFFER_SIZE) delta_time_adc_1 = timed_read_elapsed;
  163. }
  164. #if defined(__IMXRT1062__) // Teensy 4.0
  165. asm("DSB");
  166. #endif
  167. //digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN) );
  168. }
  169. #endif
  170. #else // make sure the example can run for any boards (automated testing)
  171. void setup() {}
  172. void loop() {}
  173. #endif // ADC_USE_TIMER