LTC2400 Signal/Voltage Creep?

Hello All,

I'm building a little pcb with the LTC2400 as a primer to interfacing with some complex ADC's, but I've run into a small problem...

Here is the background:

This project is based on this:
http://interface.khm.de/index.php/lab/experiments/connect-a-ltc2400-high-precision-24-bit-analog-to-digital-converter/

-Arduino-
Arduino Duemilanove atmega 328
Running off USB power (no external power source) & Windows 7 laptop
Arduino IDE 1.0.6

-Board-
Radioshack double sided PCB 1.25"x1"
2x Panasonic 10uf electrolytic capacitors (round through hole)
1x Radioshack 0.1uf film capacitor (flat through hole)
1x lp2950-33 (TO92) Datasheet
1x lt2400 (SOIC8) Datasheet

Here is the eagle schematic & board layout:
(be nice, this is my first time using eagle)

for reference, the ltc2400 pin out

Here is the code:

credit again goes to aforementioned link

/* LTC2400 24 Bit ADC Test
* Connect an LTC2400 24 Bit ADC to the Arduino Board in SPI Mode
*
*
*
* KHM 2009 /  Martin Nawrath
* Kunsthochschule fuer Medien Koeln
* Academy of Media Arts Cologne

*/
#include <Stdio.h>

#ifndef cbi
#define cbi(sfr, bit)     (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit)     (_SFR_BYTE(sfr) |= _BV(bit))
#endif

#define LTC_CS 2         // LTC2400 Chip Select Pin  on Portb 2
#define LTC_MISO  4      // LTC2400 SDO Select Pin  on Portb 4
#define LTC_SCK  5       // LTC2400 SCK Select Pin  on Portb 5

void setup() {

 cbi(PORTB,LTC_SCK);      // LTC2400 SCK low
 sbi (DDRB,LTC_CS);       // LTC2400 CS HIGH

 cbi (DDRB,LTC_MISO);
 sbi (DDRB,LTC_SCK);

 Serial.begin(57600);
 // init SPI Hardware
 sbi(SPCR,MSTR) ; // SPI master mode
 sbi(SPCR,SPR0) ; // SPI speed
 sbi(SPCR,SPR1);  // SPI speed
 sbi(SPCR,SPE);   //SPI enable

 Serial.println("LTC2400 ADC Test");

}
float volt;
float v_ref=3.3;          // Reference Voltage, 5.0 Volt for LT1021 or 3.0 for LP2950-3

long int ltw = 0;         // ADC Data ling int
int cnt;                  // counter
byte b0;                  //
byte sig;                 // sign bit flag
char st1[20];             // float voltage text

/********************************************************************/
void loop() {

 cbi(PORTB,LTC_CS);             // LTC2400 CS Low
 delayMicroseconds(1);
 if (!(PINB & (1 << 4))) {    // ADC Converter ready ?
   //    cli();
   ltw=0;
   sig=0;

   b0 = SPI_read();             // read 4 bytes adc raw data with SPI
   if ((b0 & 0x20) ==0) sig=1;  // is input negative ?
   b0 &=0x1F;                   // discard bit 25..31
   ltw |= b0;
   ltw <<= 8;
   b0 = SPI_read();
   ltw |= b0;
   ltw <<= 8;
   b0 = SPI_read();
   ltw |= b0;
   ltw <<= 8;
   b0 = SPI_read();
   ltw |= b0;

   delayMicroseconds(1);

   sbi(PORTB,LTC_CS);           // LTC2400 CS Low
   delay(200);

   if (sig) ltw |= 0xf0000000;    // if input negative insert sign bit
   ltw=ltw/16;                    // scale result down , last 4 bits have no information
   volt = ltw * v_ref / 16777216; // max scale

   Serial.print(cnt++);
   Serial.print(";  ");
   printFloat(volt,6);           // print voltage as floating number
   Serial.println("  ");

 }
 sbi(PORTB,LTC_CS); // LTC2400 CS hi
 delay(20);

}
/********************************************************************/
byte SPI_read()
{
 SPDR = 0;
 while (!(SPSR & (1 << SPIF))) ; /* Wait for SPI shift out done */
 return SPDR;
}
/********************************************************************/
//  printFloat from  tim / Arduino: Playground
// printFloat prints out the float 'value' rounded to 'places' places
//after the decimal point
void printFloat(float value, int places) {
 // this is used to cast digits
 int digit;
 float tens = 0.1;
 int tenscount = 0;
 int i;
 float tempfloat = value;

 // if value is negative, set tempfloat to the abs value

   // make sure we round properly. this could use pow from
 //<math.h>, but doesn't seem worth the import
 // if this rounding step isn't here, the value  54.321 prints as

 // calculate rounding term d:   0.5/pow(10,places)
 float d = 0.5;
 if (value < 0)
   d *= -1.0;
 // divide by ten for each decimal place
 for (i = 0; i < places; i++)
   d/= 10.0;
 // this small addition, combined with truncation will round our

 tempfloat +=  d;

 if (value < 0)
   tempfloat *= -1.0;
 while ((tens * 10.0) <= tempfloat) {
   tens *= 10.0;
   tenscount += 1;
 }

 // write out the negative if needed
 if (value < 0)
   Serial.print('-');

 if (tenscount == 0)
   Serial.print(0, DEC);

 for (i=0; i< tenscount; i++) {
   digit = (int) (tempfloat/tens);
   Serial.print(digit, DEC);
   tempfloat = tempfloat - ((float)digit * tens);
   tens /= 10.0;
 }

 // if no places after decimal, stop now and return
 if (places <= 0)
   return;

 // otherwise, write the point and continue on
 Serial.print(',');

 for (i = 0; i < places; i++) {
   tempfloat *= 10.0;
   digit = (int) tempfloat;
   Serial.print(digit,DEC);
   // once written, subtract off that digit
   tempfloat = tempfloat - (float) digit;
 }
}

Here is an example of the creep, as output on serial monitor:

Here is a picture of the board:

Here is the basic rundown.

I copied the above mentioned link's schematic as closely as I could in order to make the board. In summary, it uses the Arduino 5v source to a 100ohm resistor, a 10uf capacitor, the voltage regulator stepping down the voltage to 3.3v. The regulated 3.3v source is then fed into a 0.1uf capacitor and then used as the LTC2400 reference voltage. The LTC2400 uses the same 5v source for vcc that the regulator does. ADC in for the LTC2400 uses another 10uf capacitor tied to ground. All grounds (including ADCout) are tied to a single arduino ground wire. Clock is tied to vcc for 50hz rejection. All capacitor's positive legs are tied to either 3.3v, 5v, or ADCin, all negative leads are attached to ground.

Finally, here's the problem:
In measuring voltages, I got some substantial creep in readings, (see photo above) even when the ADCin and ADCout lines are not connected to anything. Over a minute or so, I would see voltages go from 0-1v. I verified that these voltages were actually in the line by my separate volt meter. This setup would read the voltage of the AA battery to the hundred properly (verified by same method to hundredth of a volt), but would creep even when the battery was connected. Also, strangely, I would get readings of ~1.64v with nothing connected to the lines (which is exactly 1/2 of measured output voltage by the lp2950-33, 3.28v)

In trying to figure this out-
-I pulled the 10uf capacitor on the ADCin line, no major effect, still creeping.
-I pulled the 0.1uf capacitor from the reference line, output signal suffered by fluctuating hundredth of a voltage instead of ten thousandth of a volt, still creeping although less obvious due high fluctuations.
-When I connect the volt meter to the ADCin, ADCout(GND) lines, the creep drops, then restarts (even if the leads are still connected)
-When I connect the volt meter to the regulated 3.3v and GND lines, the creep drops, then restarts (even if the leads are still connected)
-When I connect the volt meter to arduino 5v and GND lines, creep does NOT drop

After this, I'm at a loss. Clearly something isn't right, and it doesn't seem code related, or related to the capacitors (since I removed them and the problem is still there).

Advice, ideas, comments?

A quick suggestion:

Looks like you might need a minimum load applied to the 3.3V regulator used as a reference. I would try loading the 3.3V reference with a 10K pull-down resistor.

From the LP2950 datasheet:

For the LP2950, no load stability is inherent in the design — a desirable feature in CMOS circuits that are put in
standby (such as RAM keep-alive applications). If the LP2951 is used with external resistors to set the output
voltage, a minimum load current of 1 μA is recommended through the resistor divider.

EDIT: Perhaps a 3.3V reference IC would be a better solution.

NOTE: The 100 ohm resistor in series with the 5V power input seems questionable - what is its purpose? If its for current limiting, I think a polyswitch (resettable fuse) would be a better solution.

A 10k resistor between the 3.3v line and GND did the trick. No more creep!

Thanks dlloyd!

I put the 0.1uf and it restored the readings to about a millivolt resolution checked against the volt meter.

To answer your other questions dlloyd:
1.)I'm not sure why there is a resistor before the 5v source, that part is copied from the original schematic. I'm learning some of the basics of circuit board design both in readings and practice and I'll give the fuse/polyswitch a shot! Thanks.
2.)In the future I plan on using some reference IC's instead of this regulators.

However, there is one lingering problem..

-With and without the 0.1uf capacitor the reading with nothing connected to ADCin & ADCout rests at ~1.6v. Once something is connected, it reflects the proper reading.

I reconnected the 10uf capacitor, and the arduino starts at 0v and slowly creeps to 1.6v where it rests.

I tried connecting a 10k ohm resistor to pull down the ADCin, and the signal just pegged negative. -0.41v

Anyone have idea how I might solve this.

-With and without the 0.1uf capacitor the reading with nothing connected to ADCin & ADCout rests at ~1.6v. Once something is connected, it reflects the proper reading.

I think this is normal, as on page 22 of this datasheet, it shows the equivalent analog input circuit, where Vin should drift to approx 1/2 VREF due to the 5K/5K RSW voltage divider.

I tried connecting a 10k ohm resistor to pull down the ADCin, and the signal just pegged negative. -0.41v

The datasheet mentions that it has an extended range (-12.5% to 112.5%)VREF. So it looks like this would also be normal as -0.125 x 3.3 = -0.4125V.

Thanks again dlloyd. I swear, I read those datasheets. Sometimes it's hard to parse out what information is relevant when your new to this.