PDA

View Full Version : Interesting observation on the ADC of Teensy 3.0



darkness
01-12-2013, 09:09 AM
Hi,

I'm trying to design a smart discharger for my batteries in order to determine their capacity and automatically shut off the discharge when the batteries go below a certain voltage. In my course of preparing the software and hardware, I realised a very interesting phenomenon across the various analog channels available in the Teensy 3.0. As I need to be able to accurately compare the voltages at different points in my circuit, I needed all of the ADC channels to be matched. I built a simple circuit such that I connect a single battery across every analog channel (A0-A9), measured their ADC values and plotted a frequency histogram of the data. The numbers are quite interesting:


A0 A1 A2 A3 A4 A5 A6 A7 A8 A9
1685 0 1 0 0 0 0 0 0 0 0
1686 0 0 0 0 0 0 0 0 0 0
1687 0 0 1 0 0 0 0 0 0 0
1688 0 0 0 0 0 0 0 0 0 0
1689 0 0 0 0 0 0 0 0 0 0
1690 1 0 0 1 0 0 1 0 0 0
1691 0 1 0 0 3 1 2 0 0 0
1692 6 0 1 1 1 1 1 3 1 2
1693 4 0 4 0 1 2 4 2 2 6
1694 5 0 10 0 4 6 5 3 3 4
1695 8 7 5 7 3 2 7 3 6 8
1696 6 8 13 13 4 8 9 11 4 3
1697 22 19 19 7 10 8 14 8 9 9
1698 37 23 20 24 15 12 17 23 20 15
1699 78 36 33 33 27 26 18 34 23 28
1700 199 57 52 58 67 42 39 53 54 42
1701 412 166 118 166 106 85 104 112 97 82
1702 1050 336 253 360 267 196 223 242 189 165
1703 2330 805 573 813 622 455 478 542 433 360
1704 4909 1840 1381 1854 1523 1057 1149 1261 1040 897
1705 8853 3879 2931 3893 3168 2396 2425 2768 2298 2071
1706 13871 7329 5824 7504 6168 4941 4820 5470 4775 4238
1707 18777 12130 10182 12323 10463 8846 8848 9669 8458 7650
1708 21312 17360 15143 16868 15723 13737 13682 14547 13378 12508
1709 20422 20620 19592 20535 19600 18495 18379 19102 18384 17418
1710 16712 21209 20843 20729 21094 21162 20840 21024 20879 20580
1711 11106 18254 19394 17892 19285 20120 20054 19664 20070 20551
1712 6432 12895 14980 12986 14558 16339 16534 15597 16498 17228
1713 3212 7824 9831 8145 9540 11308 11383 10540 11729 12726
1714 1572 4093 5719 4339 5325 6848 6858 6073 7104 7818
1715 681 1969 3007 2223 2664 3470 3600 3145 3762 4310
1716 255 875 1419 917 1274 1640 1648 1498 1849 2133
1717 113 399 639 449 517 750 728 591 778 922
1718 46 168 258 176 228 274 323 264 349 369
1719 19 87 119 73 84 111 137 116 153 178
1720 14 32 53 37 52 50 69 59 49 76
1721 7 18 22 20 29 29 35 22 36 32
1722 8 22 15 16 13 16 16 12 17 30
1723 12 12 15 7 18 15 11 11 12 9
1724 4 4 11 9 10 12 11 8 10 7
1725 0 6 3 5 10 11 7 5 11 7
1726 0 4 5 3 5 11 3 7 6 3


The frequency histogram may be more telling:
http://i280.photobucket.com/albums/kk182/darkytoothpaste/freqhist_zps7d936acb.png

From top view:
http://i280.photobucket.com/albums/kk182/darkytoothpaste/freqhist2_zps080613a7.png

Notice that moving from channel A0 to A9, there is an offset in the "earlier" channels compared to the rest. The channels start to be more matched in terms of their output starting from A1. However, channel A0 is offset by at least 2 ADC values compared to A1-A9. Therefore, if you need matched ADC outputs, seems like channels A1 to A9 are better suited and A0 should not be used. For more critical applications, seems like channels A5 to A9 are very well matched and A1 to A4 are also well matched.

Further more, when I connect the ground of the battery to AGND, I'm getting a lot of noise on the circuit (the ADC values generated above are based on connection to AGND). From the values above, the variance is in the region of around 7 ADC units (using a resolution of 12 bits). However, when I connect to GND instead of AGND, the variance is around only 1.5 ADC units. So which ground reference pin should I be using in this case? Also, I have also tried to connect a 1uF capacitor across the ADC channels to ground for the analog pins that I'm reading. Is that a good practice and recommended?

Nantonos
01-12-2013, 10:55 AM
That is an interesting finding. Could you post more details of your circuit and code?

In particular, I wonder if you always measured the channels in order (say, A0 then A1 ... A9) and if so, whether the same results are obtained if you measure in the opposite order (A9, A8 ... A0)?

Also, you mentioned a battery - can this be considered to have a uniform voltage over the time taken to run your tests?

darkness
01-12-2013, 03:17 PM
Nantonos, I couldn't believe it but when I swapped the reading sequence around, indeed now A9 has a higher reading than A0. I'm still generating data as I'm typing this (around 30k data points). I probably would be able to post some results in an hour's time or so (intending to generate at least 200k readings per channel).

I did not insert any delays between consecutive reads from channel to channel. There is only a delay at the end of reading all of the channels. I suspect by inserting a delay between reads may stabilise the results. I will try that after generating this set of results.

As for whether the battery voltage remains stable throughout the test should be immaterial to the outcome of this test. A decreasing voltage should theoretically only increase the spread of data points, but should not result in the
"sweeping effect" of the voltage reading across the channels.

The picture of the circuit is as below. It's basically just a direct connection of the positive terminal of the battery to all of the analog channels being tested. The negative terminal is connected to AGND. There are capacitors across some of the analog channels to ground to reduce the ADC noise. The two crocodile clips (right at the bottom of the picture) goes to the battery.

http://i280.photobucket.com/albums/kk182/darkytoothpaste/2013-01-12-2323_zps6f0a42ac.jpg

The code that I used is as follows:



#define NUM_SAMPLES 1 // number of samples to take between intervals
#define SAMPLING_INTERVAL 1 // sampling intervals in seconds
#define SAMPLING_RESOLUTION 12 // resolution in bits


elapsedMillis sinceLastInput;
double powerDissipated = 0;
int elapsedSeconds = 0;

// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(115200);
analogReadRes(SAMPLING_RESOLUTION);
analogReference(DEFAULT);
}

// the loop routine runs over and over again forever:
void loop() {

int sensorValue1, sensorValue2, sensorValue3, sensorValue4, x;
int sensorValue5, sensorValue6, sensorValue7, sensorValue8, sensorValue9, sensorValue10;

sinceLastInput = 0;
sensorValue1 = 0;
sensorValue2 = 0;
sensorValue3 = 0;
sensorValue4 = 0;
sensorValue5 = 0;
sensorValue6 = 0;
sensorValue7 = 0;
sensorValue8 = 0;
sensorValue9 = 0;
sensorValue10 = 0;

for (x=0; x<NUM_SAMPLES; x++)
{
// // read the input on analog pin 0:
// sensorValue1 += analogRead(A0);
// sensorValue2 += analogRead(A1);
// sensorValue3 += analogRead(A2);
// sensorValue4 += analogRead(A3);
// sensorValue5 += analogRead(A4);
// sensorValue6 += analogRead(A5);
// sensorValue7 += analogRead(A6);
// sensorValue8 += analogRead(A7);
// sensorValue9 += analogRead(A8);
// sensorValue10 += analogRead(A9);


// read the input on analog pin 0:
sensorValue10 += analogRead(A9);
sensorValue9 += analogRead(A8);
sensorValue8 += analogRead(A7);
sensorValue7 += analogRead(A6);
sensorValue6 += analogRead(A5);
sensorValue5 += analogRead(A4);
sensorValue4 += analogRead(A3);
sensorValue3 += analogRead(A2);
sensorValue2 += analogRead(A1);
sensorValue1 += analogRead(A0);

// delay((SAMPLING_INTERVAL*1000 - 200)/NUM_SAMPLES);
}

elapsedSeconds += SAMPLING_INTERVAL;

Serial.print(elapsedSeconds);
Serial.print(", ");
Serial.print(sensorValue1/NUM_SAMPLES);
Serial.print(", ");
Serial.print(sensorValue2/NUM_SAMPLES);
Serial.print(", ");
Serial.print(sensorValue3/NUM_SAMPLES);
Serial.print(", ");
Serial.print(sensorValue4/NUM_SAMPLES);
Serial.print(", ");
Serial.print(sensorValue5/NUM_SAMPLES);
Serial.print(", ");
Serial.print(sensorValue6/NUM_SAMPLES);
Serial.print(", ");
Serial.print(sensorValue7/NUM_SAMPLES);
Serial.print(", ");
Serial.print(sensorValue8/NUM_SAMPLES);
Serial.print(", ");
Serial.print(sensorValue9/NUM_SAMPLES);
Serial.print(", ");
Serial.print(sensorValue10/NUM_SAMPLES);
Serial.print(", ");

Serial.println();


while (sinceLastInput < SAMPLING_INTERVAL * 10) {};


}

darkness
01-12-2013, 03:41 PM
This is the result of swapping the read sequence from A9 backwards to A0.



A0 A1 A2 A3 A4 A5 A6 A7 A8 A9
1702 0 0 0 0 0 0 0 3 0 1
1703 1 0 0 0 0 2 0 4 0 5
1704 4 0 0 4 0 1 4 42 3 81
1705 5 3 6 18 4 4 57 327 32 573
1706 67 11 47 79 22 57 487 1609 324 2611
1707 421 123 261 474 307 567 2345 5302 1963 8177
1708 2027 667 1151 2045 1516 2623 8069 19741 6432 31396
1709 6130 2568 3762 6154 5092 8363 35093 59078 29561 71582
1710 21744 7276 10530 18975 16819 34835 77105 68478 77650 53787
1711 62018 26209 36421 53154 54061 75315 51671 28751 57906 18531
1712 65255 65857 70775 64705 69209 51741 14209 7436 14670 5245
1713 26299 59909 48767 32987 33271 14661 3356 2033 3791 1085
1714 6950 22403 15496 10595 9534 4047 740 390 813 143
1715 1909 6144 4531 3207 2740 895 94 33 80 17
1716 346 1748 1182 709 575 115 6 10 8 3
1717 50 267 257 109 76 11 1 0 4 0
1718 9 48 42 21 8 0 0 0 0 0
1719 2 3 8 1 3 0 0 0 0 0
1720 0 1 1 0 0 0 0 0 0 0


http://i280.photobucket.com/albums/kk182/darkytoothpaste/freqreverse_zps36da6833.png

I'm going to add a 3ms delay between reads and see if it improves the situation (not sure if this simulates a sample and hold?). Be posting again soon.

Jp3141
01-12-2013, 04:34 PM
You are using the internal ADC reference which doesn't have the same accuracy/stability as 12-bit readings would need. It is possible that during your run the MCU temperature is changing and that changes the reference which in turn changes the apparent reading.

You could test this by also converting the internal temperature sensor -- it is on analog channel 0x26 (38 decimal). Its output isn't in deg. C (and needs manual calibration). You can get an approximate value in deg. C by doing:
tempeatureC = 432 - analogRead(0x26)*0.02936

(note -- these were appropriate cal. constants for my board; others may vary).

darkness
01-12-2013, 06:51 PM
Results with 3ms delay between all reads.



1701 0 0 0 1 0 0 0 1 0 0
1702 2 0 1 0 0 2 0 6 1 2
1703 19 2 3 5 5 6 18 37 2 1
1704 119 25 52 88 32 39 178 263 12 55
1705 641 163 212 480 249 285 864 1339 106 407
1706 2649 818 1005 1711 1217 1513 3938 5184 764 1957
1707 9547 2999 3348 6038 4533 6626 18478 20251 3048 7184
1708 31961 10573 11784 19963 16774 26099 46712 44856 14273 26465
1709 47921 34349 35714 42274 42484 49804 39439 36339 46953 48419
1710 24213 47412 45818 35738 39895 30244 12301 12815 44106 29091
1711 6184 21536 20146 13719 14747 8017 2464 3052 12531 8756
1712 1340 5462 5227 3772 3878 1921 457 669 2507 2159
1713 293 1313 1284 935 930 327 71 102 561 371
1714 30 239 278 176 153 42 5 11 58 53
1715 8 31 48 23 26 0 1 1 4 5
1716 0 4 4 2 2 1 0 0 0 1
1717 0 0 2 1 1 0 0 0 0 0


http://i280.photobucket.com/albums/kk182/darkytoothpaste/freq-ran_zpscec1c21f.png

Jp3141, I do have a TL1431 that I could probably setup to test it out with. The only problem is that it is a SMD component and it would not fit my breadboard. I would need some kind of breakout board to hook it up to the Teensy.

I'm not sure if temperature would be a contributory factor but I can test it out. However, temperature should not affect individual channels right? If they have an effect on the reading it should be across all channels and showing a greater variance in the readings (i.e., more noise).

Jp3141
01-12-2013, 07:37 PM
Yes, any temperature effect (or drift) should affect all channels. But if the part is warming up (I think the internal temperature rises by about 2-4 deg. C when running Teensy code) as you scan the channels, could that cause an observed drift ? Try warming or cooling the part (hair dryer).

Otherwise, isn't your span within the accuracy spec of the ADC ? (http://cache.freescale.com/files/32bit/doc/data_sheet/K20P64M50SF0.pdf?fpsp=1 page 38).

PaulStoffregen
01-12-2013, 09:47 PM
Are you using the 1.2 volt internal reference, or the 3.3 volt VCC as reference?

Jp3141
01-12-2013, 10:14 PM
Are you using the 1.2 volt internal reference, or the 3.3 volt VCC as reference?

He has analogReference(DEFAULT); which uses the 3.3 V supply as a reference -- it's probably noisy, and of course is not guaranteed very tightly. I guess he's using NiCd cells (count of 1710 = 3.3*1710/4096 ~ 1.4 V (overcharged ?)

'darkness' -- is it possible that the 3.3 V noise is correlated with your measurements ? Perhaps the CPU current consumption is a function of the portion of code that is running ?

PaulStoffregen
01-12-2013, 11:08 PM
Using VCC as a reference makes sense for ratiometric measurements (like reading the position of a pot). The A/D readings will scale as VCC changes, but since a ratiometric signal also scales with VCC, the effect is canceled out.

For absolute measurements, either the internal reference or a shunt-type external reference connect to the AREF pin should be used. VCC can change, causing the A/D readings to change, even if the input voltage is perfectly constant.

Here's my guess.... maybe as code measures the 10 pins, VCC stays fairly constant. Then perhaps as it transmits the 10 numbers, the USB port consumes more power while its transmitter is active, causing the VCC to lower slightly. Or perhaps it lowers and then raises before setting back to nominal, as the LDO regulator's feedback loop responds? Either way, when the loop repeats, the effect of the previously altered VCC tends to be seen on the first measurement?

Or perhaps using the A/D changes VCC slightly, where the first measurement depends on VCC before the A/D activity, and then the other 9 have a slightly altered VCC because the A/D's circuitry (probably the high speed comparator doing the successive approximation) consumes more current while active?

Just to keep things in perspective, we're talking about a change slightly under 2 steps near the middle of 4096 scale. Assuming the input voltage really is constant, and the ADC works, that corresponds to approximately a 0.1% change in VCC during the time 10 measurements are made.

You *MUST* use the internal reference or a stable external shunt reference to achieve high performance for absolute voltage measurements. I'm actually amazed it's working so well using VCC. If you connect VCC to power other circuitry with fluctuating current requirements, or even if you write more sophisticated code that exercises the on-chip perhipherals, the performance using VCC as a reference will likely become worse.

Jp3141
01-13-2013, 01:40 AM
Here's my guess.... maybe as code measures the 10 pins, VCC stays fairly constant. Then perhaps as it transmits the 10 numbers, the USB port consumes more power while its transmitter is active, causing the VCC to lower slightly. Or perhaps it lowers and then raises before setting back to nominal, as the LDO regulator's feedback loop responds? Either way, when the loop repeats, the effect of the previously altered VCC tends to be seen on the first measurement?

Or perhaps using the A/D changes VCC slightly, where the first measurement depends on VCC before the A/D activity, and then the other 9 have a slightly altered VCC because the A/D's circuitry (probably the high speed comparator doing the successive approximation) consumes more current while active?

Just to keep things in perspective, we're talking about a change slightly under 2 steps near the middle of 4096 scale. Assuming the input voltage really is constant, and the ADC works, that corresponds to approximately a 0.1% change in VCC during the time 10 measurements are made.


Paul is correct -- here is a scope shot of the 3.3V line (w.r.t. GND) with markers (blue trace) at start and stop of USB writing. Before this is the ADC activity ((you can see 10 conversions).
139

Here is the relevant portion of the code:
// read the input on analog pin 0:
sensorValue10 += analogRead(A9);
sensorValue9 += analogRead(A8);
sensorValue8 += analogRead(A7);
digitalWrite(1, HIGH);
sensorValue7 += analogRead(A6);
digitalWrite(1, LOW);
sensorValue6 += analogRead(A5);
sensorValue5 += analogRead(A4);
sensorValue4 += analogRead(A3);
sensorValue3 += analogRead(A2);
sensorValue2 += analogRead(A1);
sensorValue1 += analogRead(A0);

// delay((SAMPLING_INTERVAL*1000 - 200)/NUM_SAMPLES);
}

elapsedSeconds += SAMPLING_INTERVAL;
digitalWrite(0, HIGH);

Serial.print(elapsedSeconds);
Serial.print(", ");
Serial.print(sensorValue1/NUM_SAMPLES);
Serial.print(", ");
Serial.print(sensorValue2/NUM_SAMPLES);
Serial.print(", ");
Serial.print(sensorValue3/NUM_SAMPLES);
Serial.print(", ");
Serial.print(sensorValue4/NUM_SAMPLES);
Serial.print(", ");
Serial.print(sensorValue5/NUM_SAMPLES);
Serial.print(", ");
Serial.print(sensorValue6/NUM_SAMPLES);
Serial.print(", ");
Serial.print(sensorValue7/NUM_SAMPLES);
Serial.print(", ");
Serial.print(sensorValue8/NUM_SAMPLES);
Serial.print(", ");
Serial.print(sensćorValue9/NUM_SAMPLES);
Serial.print(", ");
Serial.print(sensorValue10/NUM_SAMPLES);
Serial.print(", ");

Serial.println();
digitalWrite(0, LOW);


while (sinceLastInput < SAMPLING_INTERVAL * 10) {};

At conversion #3, I bring pin 1 high, at conversion 4 I bring it low. Pin 0 goes high when USB starts and low when it ends.

Ignore the very large (full screen) spike at the 3rd conversion -- this comes from capacitive coupling to the scope.

However, you can see definite 3.3V ripple of over 1 mV corresponding to each ADC conversion. Also see that before the ADC conversion sequence, 3.3V is slightly higher than during.

AGND is even noisier (roughly 40 mV spikes) during ADC conversion.

Edit -- I just looked at AREF (which is 3.3 V in this mode) -- it has a 10 mV droop during the ADC conversions:
140

Paul -- what's the recommended cap on AREF ? You have 0.1 uF & 470 ohm.

darkness
01-13-2013, 11:18 AM
Thanks guys for the input. I have tried to wired up a shunt regulator and ended up with more problems than I started. Hope to get some advice.

I took out my Teensy and soldered a single core wire to the AREF pin. I also fashioned up a DIP board to hook up a TL1431 (http://www.ti.com/product/tl1431). Using a voltmeter to measure the output voltage from the cathode end of the regulator, the output was a nice 2.50V. However, immediately upon connecting the AREF wire to the cathode end, the voltage drops to 2.43V. It seems like somehow the AREF pin is sinking current resulting in the voltage drop. Also, the ADC reading was completely haywire (the spread was more than 200 ADC units).

The circuit that I used for the shunt is Figure 1 from the datasheet (http://www.ti.com/lit/ds/symlink/tl1431.pdf) (page 6). The input end is connected to the 5V Vcc from Teensy, R is chosen to be 330 ohm (datasheet says to keep I_KA between 1 to 100 mA). V_KA is connected directly into AREF. The circuit is as shown below:

http://i280.photobucket.com/albums/kk182/darkytoothpaste/2013-01-13-1900_zpse5f50529.jpg

I suspect that the problem may be due to my circuit (poor electronics knowledge? ;)). Is that a need to buffer the reference voltage from the shunt prior to connecting it into AREF?

For the software side, the only change I did was to change the DEFAULT reference to EXTERNAL.

Minor update:
I just used a voltmeter to test if I had accidentally shorted anything (esp. between AREF and A9 since they are side by side). I was surprised to find that the 3.3V pin is "continuous" with the AREF pin! (i.e, the beeper on the voltmeter sounded when I connected them). I measured the resistance between them and it was 470 ohm. Is this normal?

Jp3141
01-13-2013, 04:17 PM
So did you tie REF to Cathode and just put this from AREF to GND ?

The 470 is correct -- see http://www.pjrc.com/teensy/schematic.html

The TL1431 needs about 1 mA (0.45 mA typ.). So i think you should be able to connect just this (REF&Cathode) to AREF -- no other components needed.

I don't know what changing the reference from DEFAULT to EXTERNAL should do.

darkness
01-14-2013, 01:02 AM
I tried to do a search on the teensy codes and found that choosing DEFAULT and EXTERNAL actually makes no difference to the code (they have the same #define codes).

For the TL1431, all I did was to tie REF, cathode and AREF all to the same pin. Anode is connected directly to ground. Vcc (5.12V as measured from voltmeter) is connected to the AREF pin via a 330 ohm resistor (measured out to be 325 ohm from a voltmeter).

I looked at the schematic as the link above but I don't understand how it is supposed to work. Assuming that the 3.3V is connected via a 470 ohm resistor to VREFh, when I connect the 2.5V reference directly to VREFh, it would generate a current to flow through the 470 ohm resistor (right?). However, that current does not seem to have a place to go (assuming that VREFh has an infinite input resistance). I'm confused... :confused:

Jp3141
01-14-2013, 02:48 AM
THe K20 refrence manual (http://cache.freescale.com/files/32bit/doc/ref_manual/K20P64M50SF0RM.pdf?fpsp=1&WT_TYPE=Reference Manuals&WT_VENDOR=FREESCALE&WT_FILE_FORMAT=pdf&WT_ASSET=Documentation) helps a little -- see p608 and p626++.

In the schematic, VDDA is also 3.3 V from VOUT33. It is decoupled (filtered) with the ferrite. VREFH is connectedto this with the 470 ohm, and with no other connections, will also be 3.3 V. When you connect your 2.5 VREF to the AREF pin, a current of (5.12 - 2.5)/330 = 7.9 mA will flow from the 5.12 supply. In addition, a current of (3.3 - 2.5) /470 = 1.7 mA will flow from the 3.3 V supply (VDDA) and both will flow through your TL1431 to GND -- total = 9.6 mA.

The TL1431 doesn't actually need that much current (although it is not a problem) -- you can probably get by with removing the 5 V connection and just depending on the existing 470ohm.

I think this should have maintained 2.5 V on VREFH. When you just had 5.12 V and 330 ohm, do you still have 2.500 V on REF&Cathode ? If so, and you touch this connection to the VREFH pin (not VDDA) via a DVM measuring current, you should see a current of about 1.7 mA -- do you ?

For optimal performance, you should connect the GND (Anode) to AGND.

darkness
01-14-2013, 04:02 AM
Jp3141, thank you for staying with me on this thread. Your explanation on the shunt is very clear, now I understand how the currents are flowing in my circuit.

On my specific implementation, with the 5V Vcc connected to the TL1431 through the 330 ohm, the output was 2.50V (as expected). The problem is that when I plug the blue wire (the AREF wire) into cathode, the voltage drops to 2.43V, it no longer is able to maintain 2.50V. As for the current measurement, I would have to give it a try when I'm home tonight when I have access to my circuit. I would also give the AGND connection a try as well as removing Vcc and relying solely on the 1.7mA path from Vout33.

Jp3141
01-14-2013, 05:37 AM
You must be doing something wrong (!) -- before connecting, you have one circuit with 2.5 V (the TL1431), and another circuit (Teensy VREFH) with 3.3V. When you connect, how can you end up with a lower voltage (2.43) ?

Perhaps the TL1431 is oscillating -- do you have a decoupling cap across it & physically close (anything will work, try 0.1 uF or larger).
Does the 2.43 change when you touch the pin with 1 finger ? -- that's a sure sign of an oscillation.

darkness
01-14-2013, 05:46 AM
Lol, I'm sure something is wrong that's why I'm asking for help. :o You are right in that logically, the voltage cannot be lower than what I started with (be it 3.3V or 2.5V). However, I'm completely baffled as to the results that I'm seeing.

Sorry for probing more info but where should I be connecting the decoupling cap? Between the cathode and anode? Or should it be between AREF and AGND? I do have a few caps available that I can try (0.01uF, 0.1uF, 1uF and 100uF).

I think you are right in that there is some kind of oscillation. In the earlier post I mentioned that the ADC output has a spread of over 200 ADC units. What I didn't mention is that the output seems to exhibit some kind of oscillating behaviour in that there are multiple peaks at various ADC values, instead of a standard Gaussian spread indicative of noise.

Jp3141
01-14-2013, 06:23 AM
Connect the cap directly between Cathode & Anode. Try your 100 uF. If you can keep all the wires short - << 10 cm.

The datasheet (p.11, fig. 15) says that 0.1 uF isn't good -- that's what is on AREF on the Teensy board.

In a tidier layout with shorter wires, you shouldn't need this.

darkness
01-14-2013, 06:45 AM
Thanks Jp3141. I missed out that chart in the datasheet completely! :p

In the datasheet, the x-axis is in mF and not uF. I hope it's a printing error on the datasheet as 0.1 uF is way way to the left of the charts. In fact, it seems that 100 uF will be smacked right in the centre of the unstable region(?). In any case, I will give it a try tonight and report back. Really appreciate your kindness and patience in the guidance given.

Jp3141
01-14-2013, 02:24 PM
No, I think it's uF -- notice the resistors are 'W' -- this happens when the document uses a Symbol font for ” amd the ohm symbol, but then it gets converted to a normal font.

darkness
01-14-2013, 02:53 PM
I got both good and bad news.

The good news is, using a 33uF or 100uF works! It solves the oscillating problem and provided a stable reference.

Now the bad news, it seems like there is still some inherent characteristics across each of the channels. I have tried reading from A0 to A9, then A9 to A0, and also inserting delays between reads. In all three cases, the inherent "offsets" were there. But at least now, they are consistent regardless of the read sequence or whether delays are used between reads. This is unlike previously when Vout3.3 was used.

This is a typical set of output. The "shape" of the histogram is the same in all 3 cases, so I'm just going to attached one set for reference.



A0 A1 A2 A3 A4 A5 A6 A7 A8 A9
2208 0 0 1 0 0 0 1 1 0 0
2209 1 0 0 0 0 1 1 0 0 1
2210 2 1 0 0 0 1 0 2 0 0
2211 7 0 0 2 2 2 6 7 1 1
2212 11 2 0 7 2 14 18 16 2 3
2213 23 6 10 12 15 22 49 39 10 22
2214 67 34 29 50 26 43 89 96 29 48
2215 120 57 48 68 79 106 171 166 42 93
2216 253 126 127 180 176 224 362 367 123 209
2217 459 217 224 327 316 402 691 707 247 401
2218 962 419 501 626 639 821 1197 1280 424 728
2219 1687 797 948 1144 1208 1395 2138 2326 865 1369
2220 2847 1416 1486 1982 2136 2402 3532 3924 1485 2527
2221 4544 2466 2558 3449 3610 4053 6046 7221 2605 4011
2222 8154 3971 4112 5952 6087 6988 11130 13313 4526 6916
2223 14799 6741 6867 10911 11495 12677 17420 18813 7979 13263
2224 20277 12652 12597 17141 17781 18432 19207 18537 14785 19489
2225 18335 19582 19127 19197 19095 18414 15150 13132 20054 19390
2226 11425 19885 19786 15049 14249 13126 9049 7549 18150 12677
2227 5776 13264 13120 9389 8664 7807 4660 3824 11754 6920
2228 2867 6871 6781 4838 4727 4116 2230 1937 6114 3679
2229 1337 3364 3397 2477 2481 2026 1051 992 2960 1739
2230 663 1697 1794 1241 1218 1104 555 485 1629 903
2231 301 830 864 603 647 562 240 235 747 441
2232 144 446 406 308 304 259 121 141 351 213
2233 91 184 240 135 136 105 53 56 179 88
2234 36 94 90 56 67 67 23 30 97 42
2235 16 52 61 39 24 27 23 14 32 27
2236 12 29 28 23 17 10 10 7 21 9
2237 4 9 11 12 14 11 0 6 6 8
2238 0 5 4 4 6 3 0 0 3 3
2239 2 5 3 1 2 2 0 0 3 2
2240 1 1 2 0 0 0 0 0 0 1
2241 0 0 1 0 0 1 0 0 0 0



http://i280.photobucket.com/albums/kk182/darkytoothpaste/freq_shunt_zps5a6b3400.png


Since the characteristics is consistent, I can correct for the various "offset" in code for this particular piece of hardware. The only disadvantage is that if I switch to another Teensy, I will probably need to "recalibrate" it again.

I will also try out the code on my Arduino Leonardo to see if there are differences in behaviour. The only thing is that I need to get down to connecting up all the breadboard again and to rewrite the code for Arduino... ;)

darkness
01-14-2013, 03:19 PM
This is the output from Leonardo. The ADC values was only 555 and 556 with zeros in all other ADC values, very clean!



A0 A1 A2 A3 A4 A5 A6 A7 A8 A9
555 5232 5275 5258 5314 5332 5323 5120 5165 5173 5185
556 301 258 275 219 201 210 413 368 360 348


To be fair, this is 10 bits compared to the 12 bits on the Teensy. I will try to do a 10 bit comparison on the Teensy.

darkness
01-14-2013, 05:37 PM
This is the results from Teensy 10 bits:



A0 A1 A2 A3 A4 A5 A6 A7 A8 A9
552 0 0 0 0 0 0 4 0 0 0
553 34 7 12 24 10 14 58 31 5 3
554 6466 881 1204 2946 2013 1913 8591 4393 1073 1640
555 211560 68158 72838 121360 99432 88197 230714 163874 67512 107588
556 426702 442136 435664 441671 443433 436505 406384 441517 437690 463432
557 67493 193456 193115 140892 160828 176649 66432 100618 196822 136572
558 1360 8903 10662 6671 7835 10208 1435 3161 10396 4344
559 9 80 125 58 69 135 8 28 124 40
560 2 3 5 4 6 4 0 4 3 6
561 0 2 1 0 0 1 0 0 1 1


http://i280.photobucket.com/albums/kk182/darkytoothpaste/freq_10bits_zpscd32c57d.png

As can be seen, it maintains the same characteristic "offset" as the 12-bit results.

Thanks for all the help provided. Now I can get down to coding the actual project that I'm working on. Cheers!!

Jp3141
01-14-2013, 08:33 PM
Good luck.

There is some info on the Freescale web site about the ADC and how to get optimal performance (I can't find it right now) -- it mentions dips in the supply etc.

Note that the TL1431 accuracy (0.4 %) would correspond to about the variations you are seeing -- i.e. without a better reference, you won't have a more precise system.

PaulStoffregen
01-14-2013, 09:38 PM
I ordered some TL1431's from Digikey today. It'll be at least a few days until they arrive. I'm currently working on the flight sim USB stuff, and I play to port and test IRremote and OneWire later this week (easy, since I'm familiar with their code and I have the hardware ready), so I wouldn't be able to actually do anything for a few days anyway.

If this is still unresolved next week, please let me know and I'll hook at a TL1431 and try to reproduce the problem.

Jp3141
01-14-2013, 10:43 PM
I'll let 'darkness' answer for his final results, but I think it should be OK. He will need at least 10 ”F from AREF to AGND though (you have 0.1 ”F which will oscillate with the TL1431).

Ultimately, people might find the LM-285 types easier to use -- available in a TO-92 with just 2 pins needed.

darkness
01-18-2013, 08:27 AM
Paul, I consider this issue closed. Basically, as Jp3141 pointed out, I did not include a capacitor of at least 10uF to stabilise the TL1431. The inclusion of either a 33uF or 100uF capacitor (of which I happen to have on hand) solved the oscillation problem. Jp3141, just to give closure to this issue, I did write in to TI and they confirmed that there is indeed a printing error on the X-axis of that chart.

As I have posted on post #22 (http://forum.pjrc.com/threads/15718-Interesting-observation-on-the-ADC-of-Teensy-3-0?p=18676&viewfull=1#post18676) for the 12 bit result and post #24 (http://forum.pjrc.com/threads/15718-Interesting-observation-on-the-ADC-of-Teensy-3-0?p=18686&viewfull=1#post18686) for the 10 bit result on the Teensy 3, there are some inherent noise problem that I can't overcome. Using the Arduino Leonardo (post #23) gave a squeaky clean output which had almost zero noise (no tails at all on the frequency histogram plot of the ADC results).

However, in all fairness, the output of the ADC is still usable. The maximum difference in the channel means across A0 to A9 in 12 bit mode is 1.96 units (out of the max 4095 units). The standard deviation is about the same across every channel and is around 2.36. The kurtosis of the distribution is > 0 which implies excessively long tails in the distribution (i.e., increased frequency of ADC readings far beyond the average reading). This may imply that there seem to be some random uniform noise in the ADC reading as oppose to the expected Gaussian distribution.

How I intend to overcome this problem is to simply read multiple values (say, maybe 50 readings??) and then average them up (to minimise the random noise). Given a std dev of 2.36, it should still produce very usable results for my application (which I only need 1 reading per second to measure the battery voltage). As for the differences in means across the channels, since they are around ~2 ADC units which is (2/4095 x 2.5 V) = 1.22 mV, I guess I shouldn't be too worried since the component tolerances that I'm using is around 1% anyway which is higher than these channel differences.

I'm very glad that I went with the Teensy instead of the Arduino. I do not think I will get this kind of responsive, personalised and experienced tech support if I had posted this in the Arduino forums. :o

LarryP
01-28-2013, 06:16 PM
@Darkness,

First off, thanks for posting detailed data + the code that generated it!

I've wrestled with several A2D systems (remember when those were entire boards?) in which the Mux, particularly the Mux's settling time was not sufficient for it to settle to within 1 LSB, before the conversion begins. (And this "feature" was buried deep in the specs.) Insufficient Mux settling can present as sequence-dependent errors or (IMHO, even worse) voltage-dependent errors, especially if there's a big deltaV between channels that are read in sequence. I haven't looked into the details of the K20 chip's A2D, but if you can increase the Mux settling time, that might help reduce inter-channel artifacts. If you cannot change the Mux settling time, you might try reading a channel and discarding the first reading (or two) to get the Mux/Sample-and-hold settled better, and then immediately re-read that exact same channel. But I agree that making Vref stable (and accurate for making absolute measurements) is vital.

darkness
01-29-2013, 04:10 AM
LarryP, thank you for your insightful post, I will give the idea of throwing away the initial readings a try.

Constantin
03-15-2013, 07:56 PM
Three things come to mind - a better reference, a better power supply, and potentially a better load /sample time.

For reference purposes, I like the LM4132A (http://www.ti.com/lit/ds/symlink/lm4132.pdf) - 0.05% initial accuracy but a $3.37 price.

I also prefer a more stable external power supply for the Teensy. This requires you to cut the Vin/VUSB pad connection and deliver 3.3V directly to the pins in question. FWIW, I am using a TC1262 LDO voltage regulator (http://ww1.microchip.com/downloads/en/DeviceDoc/21373C.pdf) with several hundred uF of capacitor on both sides (input and output) along with some small ceramic 0.1uF caps to keep the power supply going into the Teensy as stable as possible. I also like to have the voltage regulator off-chip because this is one less source of heat inside the chip and likely much more stable / capable also (500mA, if you believe the data sheet).

If you dig through the ADC section of the K20 manual (i.e. around page 600), you can see that the ADC sampling time can be programmed to help deal with higher-impedance loads. FWIW, the test 'load' that Freescale used was a mere 8 Ohms. Many sensor manufacturers recommend the use of a buffer / unitary gain op amp / adc driver for that reason. A TI paper that I referenced elsewhere on this site suggests that having a sampling time of about 31 time constants (i.e. RC) should allow measurements to within 1/16th of a LSB at 16 bits.

Given that the max capacitance of the ADC in the Teensy 3 is about 10pF, calculating said sample time is pretty easy if you know your load impedance. IIRC, the maximum recommended source impedance is 5k Ohm and the MUX adds another 5.6k to the overal impedance.

darkness
03-16-2013, 04:18 AM
Constantin, thanks for your insights. I don't really need a 0.05% accuracy for my application, simply becoz I did not use higher precision components in my circuits (particularly, the resistors were 1% rated). But I found your comment regarding the sampling time rather interesting. Are you able to provide further guidance on how I can change the sampling time of the Teensy? So far, what I have been doing is only to average out multiple readings.

One issue regarding the impedence of my circuitry is that it should technically be very low. I connected a NiMH battery directly to the sampling points (A0 to A9) with a smoothing capacitor across the channel to ground. I'm not sure if that would be of any meaning to increasing the sampling time.

Constantin
03-16-2013, 04:43 AM
See page 612 of the programming guide - it shows the expected sample time as a function of resolution (lower bits = higher speed) as well as impedance (i.e. higher impedance = longer required sampling time). The sampling time is set using the ADLSMP in ADCx_CFG1, ADHSC and the ADLSTS bits in ADCx_CFG2. This allows significant fine tuning. FWIW, all my differential inputs are 4k7 Ohm type with 1.5nF capacitors.

Averaging readings is certainly a valid approach also.