Forum Rule: Always post complete source code & details to reproduce any issue!

# Thread: Speeding up ADC to <5us per conversion

1. ## Speeding up ADC to <5us per conversion

I am working on a project which sampling a measurement frequently - at the slowest we need to sample every 5us. I've tested the ADC using analogread() on the Teensy 3.0 and have found it takes 20 - 23us to read an analog signal, which is just a bit too slow for our application. I've read through previous posts and it seems that Paul recently updated analogread to make it faster, which is why it's as fast as it is now (thanks for that, btw!) - but it's still too slow for what we're trying to do. I also know (or think I know) that the ADC itself is quite fast - it's 818Ksps in 16 bit or 461Ksps in <13 bit (~1 - 2 microseconds) based on reading page 36 and 37 of the K20 manual (http://cache.freescale.com/files/32b...0P64M50SF0.pdf).

So far, I've tried a few things:

I tried to comment out some not completely necessary parts of the analogread() command in the analog.c library in the teensy core (commented out the calibration and the "if pin X then Y" part):

{
int result;
/*
if (pin >= 14) {
if (pin <= 23) {
pin -= 14; // 14-23 are A0-A9
} else if (pin >= 34 && pin <= 39) {
pin -= 24; // 34-37 are A10-A13, 38 is temp sensor, 39 is vref
} else {
return 0; // all others are invalid
}
}

//return 0;
if (calibrating) wait_for_cal();
//pin = 5; // PTD1/SE5b, pin 14, analog 0
*/
while ((ADC0_SC1A & ADC_SC1_COCO) == 0) {
yield();
// wait
//serial_print(".");
}
//serial_print("\n");
result = ADC0_RA >> analog_right_shift;
//serial_phex16(result >> 3);
//serial_print("\n");
return result;
};

These changes didn't help much (saved about 1us).

I'm currently trying to use the port register directly (as per this http://forum.pjrc.com/threads/17532-...PIO_PDIR-_PDOR thread), but it's a bit confusing a slow going.

So I have 2 basic questions:

1) What exactly is it that's taking that 20us? The ADC itself is only taking part of it so I know that something else is taking up the rest, but I can't figure out what it is. If someone understands the breakdown of that 20us I'd love to hear it.
2) How can I reduce that time? I found a lot of posts for the ATMega using a prescaler to increase the response of the ADC while decreasing the accuracy, but I haven't been able to figure out how to do this on the Teensy's ADC. Is the port register shifting the way to go, or something else?

Sorry if this is a noob question, I'm fairly new at this but learning fast. Thanks,

Greg

2. I don't know much about it, but it might be faster if you reduce the resolution. I doubt that it averages multiple rapidly taken ADC values by default but there is a setting for that.

//bit resolution

//not sure if it goes down to zero.

3. I also imagine it would be faster if you ADC sampled directly to DMA. cmason posted some code here:

But, if you were able to sample every 5us(200000Hz), that gives you at best ~500 clock cycles to do something else. It's hard to imagine that you could do anything with the data other than throw it away.
I would think that DMA and interrupts would be required, and maybe you could send it straight to an sdcard.

Maybe you could electrically connect 4 teensy3's and sync them up, and have them alternate taking samples, merging the data later. Sounds problematic but just wondering.

4. Be sure you turn off the averaging.

5. Update:

Definitely turning off the averaging made the biggest difference - that gets the speed down to 3us from the standard 20us for a single analog read! Also, my labmate Chris developed a neat little trick for actually identifying when the analogread() was pulling the sample: Pull one digital pin HIGH, and connect it to a cap. On the other side of the cap, connect the analog pin through a resistor. When the digital pin goes LOW, the cap discharges at a known rate (based on the size of the cap and resistor RC constant) which is either calculable or visible on the scope. If you do a digitalwrite --> LOW followed immediately by an analogRead, the analongRead result tells you exactly where on that cap discharge curve you are. That means, you can tell exactly how many seconds it takes in the analogRead to actually pull the signal (you have to factor in about a us for the digitalWrite call)! We used a .1uF cap and a 50k resistor. Pretty neat trick, Chris is a pretty smart fella. At 3us, I'm not sure how useful it is for me right now, but it seemed worth sharing

I found that changing the analogReadRes() did not speed up analogRead at all, surprisingly.

I'm not sure if interrupts will be required for our specifications, but I definitely need to figure out how to store sufficient data quickly if we're going to take this many samples... I think I'm going to try the SD card option next as you suggested linuxgeek.

I'm going to document all my results on a General Discussion post on this project here if you want to keep up with it further: http://forum.pjrc.com/threads/23508-...photosynthesis

Greg

6. There are some bits in the control registers of the ADC to deliberately slow the ADC sampling down (typically for precision with higher source impedance drives).
You might want to check that the default values of these are to your liking.

The higher the rate you run the ADC the more care you have to have in the analog circuitry feeding it
as you may just be converting more high frequency noise and not getting better data. If your goal is to save the spinlocked CPU cycles you will want to redo the ADC for interrupts
(from a timer to control the rate, perhaps). There is an advantage of the spinlock though. It means the Teensy isn't changing external pins during the adc conversion
which would lower accuracy.

7. Originally Posted by adrianfreed
There are some bits in the control registers of the ADC to deliberately slow the ADC sampling down (typically for precision with higher source impedance drives).
FWIW, there is some dense ADC reading starting on p. 600 of the hardware guide to this chip. Print it out, have a coffee, read it a couple of times. There are functionalities described there that are yet to be implemented in the Teensy environment, such as differential channels, etc. Per the manual, higher ADC clock-speeds are allowable at lower resolutions - but you need to take care re: how fast to make the ADC vs. the desired accuracy, source impedance, etc. No such thing as a free lunch.