Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 11 of 11

Thread: Teensy 3.6 ADC - Continuous read giving unexpected results

  1. #1
    Junior Member
    Join Date
    Mar 2019
    Posts
    6

    Teensy 3.6 ADC - Continuous read giving unexpected results

    I am testing out the ADC functionality of my new Teensy 3.6 and have encountered an issue I do not understand. I setup a simple test using the signal generator on my oscilloscope to output a 5 kHz sine wave into pin 17 on the Teensy. The ground connection on the signal generator was made to the Analog Ground pin. Here is the code I used:


    Code:
    #include <ADC.h>
    
    #define SAMPLE_NO 1000
    
    const int readPin = A3;
    int j;
    float buffer[SAMPLE_NO];
    
    ADC *adc = new ADC();
    
    void setup() {
    
    	//Read pin is A3 (pin 17) on Teensy 3.6
    	//Oscilloscope signal generator attached to A3 and Analog GND
    	pinMode(readPin, INPUT);
    	delay(6000);
    	Serial.begin(115200);
    	Serial.println("Teeny beginning data acquisition...");
    
    	//Configure ADC_0 for Continuous measurement
    	adc->setAveraging(1);
    	adc->setResolution(16);
    	adc->setSamplingSpeed(ADC_SAMPLING_SPEED::LOW_SPEED);
    	adc->setConversionSpeed(ADC_CONVERSION_SPEED::LOW_SPEED);
    	adc->setReference(ADC_REFERENCE::REF_1V2);
    	adc->startContinuous(readPin, ADC_0);
    	delay(1000);
    
    	//Start measurement timer
    	elapsedMicros dt;
    	j = 0;
    	uint16_t value;
    
    	//Fill buffer with ADC_0 output values
    	while (j < SAMPLE_NO) {
    		value = (uint16_t) adc->analogReadContinuous(ADC_0);
    		buffer[j] = value*1.2/adc->getMaxValue(ADC_0);
    		j++;
    	}
    
    	adc->stopContinuous();
    
    	//Convert buffer to float values and print to Serial
    	Serial.print("Measurement time [us]: ");
    	Serial.println(dt);
    	Serial.println("Buffer Values [V]: ");
    
    	for (int i = 0; i<SAMPLE_NO; i++) {
    		Serial.println(buffer[i], 5);
    	}
    
    	Serial.println();
    
    
    }
    
    void loop() {}
    And here is the output I got for different ADC speeds:

    Click image for larger version. 

Name:	adc_low.PNG 
Views:	182 
Size:	39.5 KB 
ID:	16174

    Click image for larger version. 

Name:	adc_med.PNG 
Views:	142 
Size:	42.0 KB 
ID:	16175

    Click image for larger version. 

Name:	adc_high.PNG 
Views:	127 
Size:	41.0 KB 
ID:	16176

    I am thoroughly confused by this data. It seems clear that the program is collecting 1000 samples within 487 us for each speed. That gives a sampling speed of roughly 2 Msps! How is this possible? I feel like I am missing something simple. I hope someone can help me out.

  2. #2
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,912
    I haven't used this but I suspect that you need to wait for the conversion to complete. Add this statement before doing analogReadContinuous:
    Code:
        while(isConverting(ADC_0));
    Pete

  3. #3
    Junior Member
    Join Date
    Mar 2019
    Posts
    6
    Quote Originally Posted by el_supremo View Post
    I haven't used this but I suspect that you need to wait for the conversion to complete. Add this statement before doing analogReadContinuous:
    Code:
        while(isConverting(ADC_0));
    Pete
    I tried that and it didn't work. Just got hung up in the while loop.

  4. #4
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,771
    try
    Code:
      while (j < SAMPLE_NO) {
        if (adc->isComplete(ADC_0)) {
          value = (uint16_t) adc->analogReadContinuous(ADC_0);
          buffer[j] = value * 1.2 / adc->getMaxValue(ADC_0);
          j++;
        }
      }

  5. #5
    Junior Member
    Join Date
    Mar 2019
    Posts
    6
    Quote Originally Posted by manitou View Post
    try
    Code:
      while (j < SAMPLE_NO) {
        if (adc->isComplete(ADC_0)) {
          value = (uint16_t) adc->analogReadContinuous(ADC_0);
          buffer[j] = value * 1.2 / adc->getMaxValue(ADC_0);
          j++;
        }
      }
    That worked! Thanks. I'd still like to understand what was happening with my initial code though. It appears that the program was filling up the buffer with 1000 samples as fast as possible, regardless of the state of the ADC. But, if that is the case, why did I get a sine wave at all? It seems like I should have gotten mostly the same values over and over.


    Click image for larger version. 

Name:	adc_high_good.PNG 
Views:	186 
Size:	61.9 KB 
ID:	16183

  6. #6
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,912
    It seems like I should have gotten mostly the same values over and over
    You did. That's why the LOW and MED speed output has a "staircase" instead of a smooth sine wave. You didn't wait for the conversion to finish so the function returns the same value as last time until there is a new value.

    Pete

  7. #7
    Junior Member
    Join Date
    Mar 2019
    Posts
    2
    Quote Originally Posted by manitou View Post
    try
    Code:
      while (j < SAMPLE_NO) {
        if (adc->isComplete(ADC_0)) {
          value = (uint16_t) adc->analogReadContinuous(ADC_0);
          buffer[j] = value * 1.2 / adc->getMaxValue(ADC_0);
          j++;
        }
      }


    Hi
    I want to ask if you can help me understand what you have done in this code and why ??
    thanks in advance

  8. #8
    Junior Member
    Join Date
    Dec 2018
    Posts
    3
    The if statement basically says, "if and only if the conversion is done, the result will be read and j incremented". So after the last conversion result has been read and the current conversion is still going, adc->isComplete(ADC_0) evaluates to false and nothing will be done in the while loop. After the current conversion is done, adc->isComplete(ADC_0) evaluates to true so that the code following if statement is executed. Calling analogReadContinuous(), however, not only reads the result, but also reset the "isComplete" status, so the next time you call adc->isComplete(ADC_0) it evaluates to false. And this goes on and on, until you get all samples you want.

  9. #9
    Senior Member
    Join Date
    May 2019
    Posts
    133
    Is this like "polling" the ADC for new values?

    And would this not occupy the processor fully with the constant polling?

  10. #10
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,771
    Quote Originally Posted by tschrama View Post
    Is this like "polling" the ADC for new values?

    And would this not occupy the processor fully with the constant polling?
    yep. Using continuous with DMA and interrupt when DMA buffer full would be better. ADC lib probably has DMA examples.

  11. #11
    Senior Member
    Join Date
    May 2019
    Posts
    133
    Thx manituo.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •