Teensy 3.0 ADC details

Status
Not open for further replies.
hey everyone,

I'm new to this microcontroller programming stuff, so bear with me.

I just need to double check that I have the details about the ADC correct here:

The Teensy 3.0 has the MK20DX128 microprocessor, and so the datasheet here has the details.

Check page 37. So does this mean the Teensy 3.0 has a 16-bit ADC capable of 37-460 kSPS ? So can I expect the Teensy 3.0 to give me 16-bit ADC samples at something like 30 thousand per second? Or is this stuff only theoretical? Am I missing something here?


If someone can help with this (or if someone tried this before), it would be greatly appreciated.

Thanks in advance! May the Teensy be with you! :cool:

Oh, and where can I find the Teensyduino pinouts for the Teensy 3.0? It's not on the official website :confused:
 
I had a hard time finding them before, but they are now on the official page.

Teensy pinouts: http://www.pjrc.com/teensy/pinout.html

Thanks for posting that datasheet link, previously I was only aware of the 1227 page Freescale "K20 Sub-Family Reference Manual" K20P64M50SF0RM.pdf which lacks many specific parameters about the particular Teensy 3 chip.

Looks like you are correct about the hardware capabilities. AFAIK, for now you'd have to write your own code to realize that performance, because that speed requires (1) hardware averaging turned off and (2) continuous conversion mode. The Teensy 3 conversion rate as currently implemented is much slower.

From my post here http://dangerousprototypes.com/forum/viewtopic.php?f=2&t=4606 you can see that I observed about 2200 samples per second using analogRead()
 
Last edited:
I can't believe I missed that pinouts link XD


Great post! Certainly helpful!

I realistically only need about 2k samples per second, so I'm probably not going to write my own code :D

If this thing pulls off 2k SPS with 16-bit resolution, then HELL YEAH I'm buying one! :D

but I do notice that only 13-bits are achievable due to noise: what can I do (practically speaking) to raise the resolution as high as possible? 14-bits or 15-bits is what I'm trying to achieve. Any tips or posts that you can link to would be appreciated. Bear in mind that I'm a noob (so excuse any mistakes)

BTW, I am planning on having it connected through USB to a PC (if that makes a difference in the noise thingamajig)
 
Anything above 12 bits of resolution I would consider high-precision and you need to take increasing care with everything connected to the circuit, as the required accuracy goes up and tolerable noise goes down. The resolution of a 14 bit ADC is 1/16384 or 61 parts per million, that is 0.006 % of full scale. By the way, the most accurate resistor I have is a 0.01% part, they are expensive ($20 per resistor).

About the actual noise level, check my example code and results in the dangerousprototypes link. I found Paul's comment about 13 bits conservative, I was seeing peak-to-peak noise of 7 or 8 counts in a set of 10000 samples, and a standard deviation of about 1 count which in this case is about 50 microvolts. So if you average a lot of readings together, you can get equivalent to 16 bit resolution or even more (with tradeoff in sample rate). My ADC test setup was powered from a PC's USB port.

Noise is definitely affected by other circuits you have connected to the teensy, I even noticed there was a difference in the noise between different PC USB ports. My best noise result was from a Raspberry Pi USB port. In theory, running from a battery supply would be the best- unless you've got something else noisy also connected to the battery, or you're using a switching power converter.
 
Last edited:
See this post for some details about how to speed up the ADC. This PDF has the details of the ADC registers starting on page 587.

I'm seeing 7-12 microseconds per call to analogRead(). This is with no averaging.

I've posted my code here. I've added some comments there to explain what's going on. Use

make main_midi.hex

to build and upload to teensy3. Here's an example of a set of analogRead()s over 400 milliseconds, to give you an idea of the resolution (time on x axis, analog value on y):

marimbicile_test_conductive_thread_neoprene.png

I believe Paul is planning on making this stuff more configurable without resorting to register poking as I did.

The chip on the teensy3 can also do direct memory access (DMA) from the ADC. The quick reference guide discusses this on page 73, but I haven't seen anyone use it yet.

-c
 
Last edited:
Looks from the graph like if you've got plenty of processing power to spend, depending on A/D sample rate requirement, a median filter would be made to order to get super high precision. Generally a lot of applications don't care that much about absolute accuracy, but monotonicity, precision, and repeatability are always golden.
 
If this thing pulls off 2k SPS with 16-bit resolution, then HELL YEAH I'm buying one! :D

but I do notice that only 13-bits are achievable due to noise: what can I do (practically speaking) to raise the resolution as high as possible? 14-bits or 15-bits is what I'm trying to achieve.

Multiple samples and averaging can help (but reduces the effective sample rate, and is not terribly effective either).

Using an ADC which is not sitting in a noisy environment and has clean GND and Vcc gives a much bigger improvement. In other words, not the built-in one.

For example, I have used an ADS1115 sitting on a separate PCB with it's own regulated power supply. That gives me 15 bits single-ended or 16 bits in differential mode (although with a max sampling rate of 860 sps). Using the 5V from a USB-powered Arduino, on the other hand, I got only 12 bits of useful information.

BTW, I am planning on having it connected through USB to a PC (if that makes a difference in the noise thingamajig)
It does make a difference, yes; the 3V3 line becomes somewhat noisier due to noise from the PC (although, I would imagine, not as bad as with 5V Arduinos where the PC 5V is used directly; here the 5V feeds a 3V3 regulator).
 
@Nantonos

I previously looked into dedicated ADC chips (similar to the ADS1115), but the low sampling rate makes it unusable for my application. I haven't had much luck finding a dedicated ADC with high-resolution and high sampling rate and decent price. On top of that, most of the high resolution ADC chips are SMD (and I simply can't work with those).

So that's why I'm looking into the Teensy 3.0.

What if I use an external supply to power the Teensy 3.0 ? Would that improve the resolution and eliminate the noise? Solutions like this are what I'm effectively looking for (ideas are welcome; but don't go wild on me, I have a limited ability to acquire expensive components).

Also, I thought the Teensy was a 5V Arduino-ish device... 3.3V regulator? (I'm using the Teensy 2.0 and it doesn't have a 3.3V regulator. They changed that in the 3.0 Teensy?)


Thanks again! :cool:
 
Also, I thought the Teensy was a 5V Arduino-ish device... 3.3V regulator? (I'm using the Teensy 2.0 and it doesn't have a 3.3V regulator. They changed that in the 3.0 Teensy?)

My bad for asking an RTFM-worthy question; I just checked the website and realized the Teensy 3.0 has a 3.3V regulator. Also (obviously), its I/O pins operate at 3.3V
 
I previously looked into dedicated ADC chips (similar to the ADS1115), but the low sampling rate makes it unusable for my application. I haven't had much luck finding a dedicated ADC with high-resolution and high sampling rate and decent price.

Yes, that is my observation also. Once you move past 12-bit ADCs then you get I2C ADCs at 15-18bit (but often with 500, 200 sps) aimed at instrumentation applications, or you get I2S ADCs at 16-24bit and 44.1 - 192kHz sampling rates aimed at audio applications (and you need very careful board layout and testing to make sure you actually get that effective number of bits).
Having said which, Teensy 3.0 does support I2S so that is an option.

On top of that, most of the high resolution ADC chips are SMD (and I simply can't work with those).
I empathise (I got ADS1115 breakout boards with pre-soldered SMD from ebay).

What if I use an external supply to power the Teensy 3.0 ? Would that improve the resolution and eliminate the noise? Solutions like this are what I'm effectively looking for (ideas are welcome; but don't go wild on me, I have a limited ability to acquire expensive components).
It would remove the noise that comes from the PC via to 5V USB power; the main source of noise though is likely to be the Teensy itself. This does depend on what else the Teensy is doing at the time (eg PWM or any high-speed transfer is likely to induce noise). I have a vague memory that some ARM chips can go into a mostly-inactive low noise sleep state to give better ADC readings.

Also, I thought the Teensy was a 5V Arduino-ish device... 3.3V regulator? (I'm using the Teensy 2.0 and it doesn't have a 3.3V regulator. They changed that in the 3.0 Teensy?)

Yes, (and in the Arduino Due). They are 3V3 Arduino-ish devices with 'pay attention where you put that 5V logic signal' warnings. :D
 
thanks for the information.

The Teensy probably won't be doing a lot of stuff (only reading ADC and sending through USB), but I guess there is no way to find out how much noise there will be without trying it myself.

Thanks again, everyone! May the Teensy be with you! :cool:
 
How about a dedicated AREF?

Multiple samples and averaging can help (but reduces the effective sample rate, and is not terribly effective either).
Depends on the rate of change, no? I thought the Atmel paper on oversampling and decimation was pretty interesting. But in general, this approach seems limited to slow-moving measurements.

Using an ADC which is not sitting in a noisy environment and has clean GND and Vcc gives a much bigger improvement. In other words, not the built-in one.
I agree wholeheartedly. But I also have had tremendous trouble getting external ADCs to behave as expected. The benefit of an internal ADC is that there are no SPI issues that easily cause trouble, etc. In order to mitigate as much as possible, I was thinking of supplying power directly to the 3.3V pin with a KF33 LDO linear regulator, some big caps, some little caps, etc. for 3.3V power. The power input into the KF33 is a bit noisy (cui switch-mode power supply) but the caps should help with that.

AREF in turn will be supplied with a proper reference, I was thinking 2.5V to make interfacing with 5V sensors easy. What I wonder is how to enable differential measurements on the built-in ADC?

Also, as I understand it, not all ADC pins support 16 bit resolution? Which ones on the Teensy 3.0 do?
 
Just an update (to help others):

I tried the ADC of the Teensy3, and I noticed it had a TON of noise on it (practically not even close to 16-bit. Maybe even 13 or 12). It was THAT bad. So, I thought the noise could be coming from the USB power.

So I ran the Teensy off of battery power (disconnected USB power) to see if I can get a low noise level. Unfortunately, it had no positive effect (noise didn't decrease, but the Teensy started acting erratically with regards to USB serial communications).

So, @Nantonos was right, the noise is coming from the Teensy itself. (Incidentally, I was working on a digital accelerometer with 16-bit ADC and output [me thinking I can get high resolution good signal], and I basically noticed the same kind of noise coming from the sensor itself)!

Lesson learned: getting higher resolution ADC (like 16-bit or so) will not be of any use if your signal source is noisy.

Thanks to all Teensy peeps who helped!
 
Couple of thoughts...

When you say you ran it off battery power - was that using the internal Voltage regulator via the VIN pin or were you supplying power to the 3.3V terminal directly? I ask as one potential source of noise, IMO, is the voltage regulator inside the chip. I believe using a beefy external voltage regulator + 100uF cap and supplying power to the 3.3V pins directly will help in this regard.

Additionally, my application is looking at using the differential pins. With any luck, much of the interference you're reporting will cancel itself out. However, there are only two pairs of such pins that are accessible on the T3, and one of them requires the soldering of a SMD wire header to the underside of the Teensy. One of my signal sources had a relatively high impedance and was also not unipolar, so I am using an AD8137 to act a buffer, level shifter, etc.

For the other input pins, smoothing inputs through the use of a small capacitor like a 100pF 0805 may also help.
 
I wanted to thank you for taking the time to reply. :D

I ran it off 3 AA batteries (4.5V) regulated to 3.3V (by a typical LD33V fixed regulator). However, I connected that through the VIN pin (had no idea that I could've bypassed the internal regulator and straight into the 3.3V pin). Also, I didn't have a capacitor attached.

So, basically, if I apply power from that same setup (except this time to the 3.3V pin), you think the noise will be removed? I'll give it a shot. (I'll be extra careful when I apply power to my Teensy3 since I'm bypassing its regulator [remembers the time I was stupidly probing with the USB pins of the Teensy while it was on. It's a miracle it survived all those shorts!])


Also, I previously read about differential pins (the analog ones), but I really didn't know what they would be used for. If I'm guessing correctly (from what you said), the noise from the ADC would cancel itself out BECAUSE the differential pins would basically be taking the difference between the signal pin (the one I'm measuring) and the straight-up 3.3V. Am I on to something here? Or is my understanding flawed? I don't think soldering a wire on the bottom of the T3 is too difficult for me to do (it's about time I bought decent soldering equipment)

And finally, I don't understand what you mean by using a small capacitor for the other input pins? Which ones do you mean? (in my case, I only care about reading ONE analog pin to the highest accuracy possible).
 
The advantage of an external regulator and a large capacitor is that spikes in power demand due to the ADC or other operations have less of an impact - the capacitors soak up the excess demand before the regulator can react to a drop in voltage. I'd use something like a 10V and up, 100uF aluminum or tantalum cap, along with a 0.1uF ceramic cap to help filter spikes. As I understand it, the large cap takes care of voltage dips while the small cap takes care of high frequency noise. And yes, I'd feed the output of the external voltage regulator / cap combo directly into the 3V3 pins.

However, in order for this to this to work, you either have to have no plug in the USB port, or you need to disconnect / cut the VIN-VUSB pad connection on the underside of the Teensy board (see the schematic). Otherwise, your USB connection will continue to provide power to the on-board regulator and then the on-board regulator will be fighting with the external regulator - not a good idea. The downside to this operation is that you'll either have to solder bridge that connection again to power the teensy from USB in the future or always plug it into a board with a voltage regulator (which is what I do).

The Teensy has a Unipolar ADC, which means it can only accept positive signals from 0-AREF. Usually AREF = VCC unless you overpower the internal AREF voltage with an external reference AND (this is important!) remember to set the AREF voltage to external within setup() of your teensy program.

If you want to be extra careful, use a reference that has an enable pin - then have the teensy only enable the external reference for the AREF pin after the Teensy software has enabled the external reference setting in setup(). One can choose from many different reference sources, I like the AD1582 for simple applications and the LM4132 for a reference with an external enable pin. These external references will provide more stable power to the ADC to use as a point of comparison, hence improving its accuracy. Remember to also provide caps on the input and output of the reference to help it provide the AREF pin with stable power.

The series reference voltage output has to be somewhere between the minimum ADC reference voltage (about 1.71V) and VCC. I have used 2.5V in the past but there are many good options such as 3V, 1.8V, etc. that these references are available at. I'd select the reference on its basis to maintain a given output, and how well it allows you to envelop the output of your sensor. Thus, a 1.8V or 2.048V reference would be ideal for a signal that may vary from 0-1.8V, for example. The reason to go with a 2.048V reference even if you expect the signal not to exceed 1.8V is simply caution to provide some 'headroom' for spikes.

As for single-ended vs. differential ADC operation, the benefit of using a differential input is that you can usually eliminate a lot of the common-mode noise. For example, if the ADC positive input is depressed somewhat due to a dip in voltage or a bit of interference on the signal line(s), then the same dip will also happen on the negative input, also depressing it. Since the ADC measures the difference between the two signals, such dips, spikes, pops, whatever are hence largely eliminated. Differential measurements are hence a popular feature for high-bit ADCs since noise becomes a serious concern once an ADC goes over 12 bits or so.

Keep in mind that you have to maintain "polarity" with the differential inputs - one is has a name ends in M and the other in P. P designates positive, M (minus?) Negative. Even though the terms positive and negative are used, both inputs have to be between 0 and the AREF voltage.

A10 = ADC Channel D0 Positive Input
A11 = ADC Channel D0 Negative Input

A12 = ADC Channel D3 Positive Input
A13 = ADC Channel D3 Negative Input

You will have to drop deeper down into the C syntax to get to these differential channels as Paul has not yet implemented these differential channels, AFAIK, in the simple-to-use Arduino IDE. Also keep in mind that the differences between the M and P terminals are additive and somewhat counterintuitive until you think about it for a moment. Thus, any voltage above 0 on the P terminal is additive while any voltage below AREF is subtractive on the M terminal. For example, if you have a AREF = 2V and a M signal of 1V and a P signal @ 1.5V then the difference being measured = 1+(2-1.5)=1.5V. Foe this example, the maximum output is measured with the P terminal at AREF and the M terminal at 0V. Similarly the minimum is when P is at zero volts and M is at 2V.

As I understand it, the Teensy ADC uses a small capacitor to charge and discharge to determine a given input voltage. Thus, providing the ADC with a low-impedance signal is a good idea - a high resistance input would potentially not allow the 4.5pF (?) capacitor inside the ADC to charge fully before the ADC attempts to determine the voltage. On one of my circuits I am using a AD8137 differential amplifier as a buffer and level shifter. The op amp basically provides plenty of signal and also converts the bipolar input signal (coming from a transformer) to two unipolar signals that can be used by the differential inputs of the Teensy ADC.

For slow-moving signals you can also try adding a capacitor from the analog input pin to ground to help absorb spikes and also help allow the SAR ADC in the Teensy quickly charge to a given voltage. High-bit differential signal paths will frequently feature a cap to GND on each signal path. You can combine such caps with a carefully-chosen resistor on each input to create a filter to take out high-frequency noise - see some high-bit ADC spec sheets to see what I mean. For example, for the AD7753 power measurement chip, they recommend a 1k resistor and a 1nF cap on each line.

Lastly, you can consider over-sampling in software, again a workable solution for slow-moving signals.
 
Last edited:
@Constantin: That's some good info. Thanks! I'll make sure and revisit this when I get to the point of fully using the ADC on the T3.
 
@Constantin: That's some good info. Thanks! I'll make sure and revisit this when I get to the point of fully using the ADC on the T3.

Thanks for the kind words but also allow some time for the more qualified to respond. I'm just a ME that happens to enjoy this topic but there is a lot yet for me to learn about these wonderful boards and their many functions.
 
@Constantin

I just realized that I never knew the impedance value of the signal. It turns out it's around 32kHz, but I have no idea what that means (is it too high in this case?)

But, first, the attempt to bypass the internal voltage regulator. I already previously cut the VIN pad (in fact, I soldered it back on yesterday and just desoldered it again today). I will attempt to bypass the regulator by using the 3.3V pin as you mentioned earlier.

As for external reference pins, I've always been using a voltage divider from the 3.3v regulator (gets about 1.55V). However, I always keep it connected to the AREF pin (I never used an enable pin to turn it on and off; does that mean that I'm damaging my T3?). Also, aren't voltage regulators practically the same as voltage reference sources in this application?

As for the differential pins, I wanted to thank you for the long and educational post. I'll re-read it as I go on and try to figure it out (if my above attempt fails to fix the noise issue).

Oversampling is not an option, since I need to maintain a very high sampling rate (~2kHz).


Lol, you're only an ME and you know this much? 0_o Wow, I'm amazed (I thought being a BioE and tinkering with Teensy's was cool. I guess I have a long way to go; a really fun way, though) :cool:
 
I'll let the more knowledgeable pipe up, but here is my first stab at answering your question:

Since the Teensy 3 ADC uses a SAR circuit, you need to ensure that the input impedance isn't too high to allow the capacitor to charge quickly enough. The worst case capacitance of the ADC = 10pF. Your source impedance is 32kOhm, the input impedance = 6kOhm, so the time constant = RC = 38,000 x 10e-12 = 0.000000038 seconds. Per this TI application guide allow at least 14 time constants/sample for the ADC to fully charge up = 5.37e-7s.

The sample time ranges from about 6 ADC cycles to 26, depending on what flags have been set. Assuming you're using the default clock rate (48MHz) and a 8:1 clock divisor (ADIV) that gets you to 6MHz for the ADC clock. The 'allowable' range for source resistance then becomes 1200 Ohm to 24kOhm for 16 bit operation. The last page of the TI manual has a nice formula to calculate your options.

So at 32k Ohm source resistance, this does not look good. If external fixes are not an option (i.e. use a buffer) I'd slow the ADC clock a further 50% by setting ADICLK to 01 and hence get a ADC clock speed of 3MHz and a allowable input source resistance of up to 48kOhm. One downside of such an approach, however, is a slowing of the ADC, so you may not get nearly as many samples/s as you may have hoped. For the math, see the the ADC section in the K20 manual (around page 600).

The K20 manual suggests using a 0.01uF high frequency capacitor from each analog input pin to GND. The reason a capacitor on the input side can be useful is that it allows the ADC capacitor to be charged almost instantaneously and the input voltage dithers less. To put things in perspective, a 0.01uF capacitor has about 1,000 times the capacitance of the input capacitor inside the ADC. Thus, the ADC can "hit" the 0.01uF capacitor and it will not put even a dent in the 0.01uF capacitor's voltage before being fully charged. However, select input filtering caps carefully to ensure that they don't interfere with the signal being measured - too large a value may perhaps smooth the input signal excessively, while too small a value will do nothing. The rule of thumb I have read about is using a capacitor with at least 50x the value of the ADC capacitor, so a 0.5nF cap should do but a 1nF cap might be easier to source. But if the manual mentions the use of 0.01uF caps, then those are the ones I'm planning on trying out.

I would never use a voltage divider for AREF if you're in a single-ended application and are trying for high resolution. At the very least use a shunt reference (diode + resistor) or a series reference if you really want a stable voltage. Note the line regulation, drift, and other parameters. Voltage regulators usually do not feature the same line regulation, drift, or accuracy specs as a series reference. There is a reason that a AD1582 is as expensive as it is. I also happen to like them because of their small size.

I am surprised that oversampling is not an option. You said you need a 2kHz sampling rate... well, the ADC can theoretically go up to 461ksamples/s (in 16 bit mode) though in real life the number is significantly lower. But that still suggests a lot of headroom re: oversampling and decimating, allowing you to boost your ENOB by as much as 3 maybe even 4 bits, depending on how much you can dedicate the CPU to sampling the ADC and it's efficiency in processing the results.
 
Last edited:
@Constantin

thanks again for the massive amount of knowledge passed down. I will try to respond point by point.

- I tried bypassing the internal regulator in the T3 (using 3.3V reg), and I kept getting the same noise, with and without caps. In fact, things started getting crazy with the analog readings (random spikes all over the place; I'm sure it's not the signal source that's responsible for this). I might have damaged the Teensy (I doubt it), or maybe there is something wrong with the way I disconnected the VIN pad from VUSB. To check, I used a continuity tester and an impedance measurement (no short indicated; path is open). I then plugged in the T3 through USB only and checked VIN (I actually got 0.63V, which is confusing me now). There doesn't seem to be a short, and I think the problem lies somewhere else (i.e. in the AREF that I'm using). That's why I'll resolder the VIN and VUSB and run the T3 off USB power from now on.

- ok, so it seems like the high impedance of the signal won't be an issue for the ADC.

- should I still use a capacitor across VIN and GND (assuming I power using USB)? The 0.1 uF, or the 1nF? Or both?

- From what you explained about the difference between voltage regulators and reference sources, it seems that the noise problem might be coming from the AREF pin (but, are voltage regulators THAT bad?). I'll buy a reference source, and see if that helps.

- I assumed that oversampling is not possible, because I recall that the T3 barely barely got 2k samples/s even with AnalogReadAveraging(0)... I'll try again to make sure.

FYI, I only need to use one of the T3's analog pins (but at the most accurate and fastest possible).
 
As a start, I would suggest a dedicated voltage source for the AREF pin and setup() to include a external setting for the AREF source. I would include plenty of external capacitors, a minimum of 10uF and 0.1uF from AREF to AGND plus the same on the incoming side of the voltage regulator also (i.e. VUSB or VIN to GND, for example).

The 1nF capacitor should be applied from whichever Analog in pin you're using (i.e. A10, for example) to AGND.

You can get much faster sampling if you drop down into the registers directly and measure from there. Additionally, Paul has updated his code to allow faster sampling. As for ADC accuracy, here is a statement from the Freescale datasheet:
The 16-bit accuracy specifications listed in Table 23 and Table 24 are achievable on the differential pins ADCx_DP0, ADCx_DM0. All other ADC channels meet the 13-bit differential/12-bit single-ended accuracy specifications.
That would be pins A10 and A11 on the Teensy.
 
Last edited:
Status
Not open for further replies.
Back
Top