Teensy 3.6 ADC - Continuous read giving unexpected results

Status
Not open for further replies.

Qubit28

Member
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:

adc_low.PNG

adc_med.PNG

adc_high.PNG

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.
 
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 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.
 
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++;
    }
  }
 
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.


adc_high_good.PNG
 
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
 
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
 
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.
 
Is this like "polling" the ADC for new values?

And would this not occupy the processor fully with the constant polling?
 
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.
 
Status
Not open for further replies.
Back
Top