sample code for LTC2440 24-bit ADC

Anything not related to a specific project.

sample code for LTC2440 24-bit ADC

Postby jbeale » Fri Jun 29, 2012 1:20 pm

In case it is useful ...

Code: Select all
/*
  Interface between Arduino DM board and Linear Tech LTC2440 24-bit ADC
  Nov. 12 2010 John Beale

   LTC2440  <---------->  Arduino
   11: /CS <- to digital pin 10  (SS pin)
    7: MOSI <- to digital pin 11 (MOSI pin)
   12: MISO -> to digital pin 12 (MISO pin)
   13: SCLK <- to digital pin 13 (SCK pin)
   10: /EXT - ground
    1: GND - ground
    2: VDD3 - 5V supply

*/

#include <SPI.h>  // include the SPI library

// set I/O pins used in addition to clock, data in, data out
const byte slaveSelectPin = 10;  // digital pin 10 for /CS
const byte resetPin = 9;  // digital pin 9 for /RESET

const int nsamples = 5;  // how many ADC readings to average together

// SPI_CLOCK_DIV16 gives me a 1.0 MHz SPI clock, with 16 MHz crystal on Arduino

void setup() {
 
    Serial.begin(115200);      // set up serial comm to PC at this baud rate
   
    pinMode (slaveSelectPin, OUTPUT);
    pinMode (resetPin, OUTPUT);
    digitalWrite(slaveSelectPin,HIGH);  // chip select is active low
    digitalWrite(resetPin,HIGH);  // reset is active low

    SPI.begin(); // initialize SPI, covering MOSI,MISO,SCK signals
    SPI.setBitOrder(MSBFIRST);  // data is clocked in MSB first
    SPI.setDataMode(SPI_MODE0);  // SCLK idle low (CPOL=0), MOSI read on rising edge (CPHI=0)
    SPI.setClockDivider(SPI_CLOCK_DIV16);  // system clock = 16 MHz, chip max = 1 MHz
   
    Serial.println("LTC2440 Test");
}

// =============================================================================
// Main Loop:
// acquire 'nsamples' readings, convert to units of volts, and send out on serial port

void loop() {

int i;
long secs;
float mins;
double volts;
long in;         // incoming serial 32-bit word
long sum = 0;

    for (i=0; i<nsamples; i++) {
      in = SpiRead();
      in &= 0x1FFFFFFF; // force high three bits to zero
      in = in>>5;   // truncate lowest 5 bits
      sum += in;
      delay(198);      // (msec). Total Looptime: +2 msec (overhead for comms)
    }

    // volts =  in * 2.5 / 8.388607;  // 0x7fffff = 8388607
    volts = sum * (0.2980232594);  // microvolts
    volts = volts / nsamples;

    mins = (float) millis() / 60000;   // elapsed time in minutes
    Serial.print(mins); 
    Serial.print(", ");
    Serial.println(volts);

} // end main loop


// =================================================================
// SpiRead() -- read out 4 bytes from LTC2440 chip via SPI interface
// =================================================================

long SpiRead(void) {

  long result = 0;
  long b;
 
//  long result2 = 0;// MOSI/SDI pin 7 HIGH => 7 Hz, best resolution

  digitalWrite(slaveSelectPin,LOW);   // take the SS pin low to select the chip
  delayMicroseconds(1);              // probably not needed, only need 25 nsec delay
 
  b = SPI.transfer(0xff);   // B3
  result = b<<8;
  b = SPI.transfer(0xff);   // B2
  result |= b;
  result = result<<8;
  b = SPI.transfer(0xff);   // B1
  result |= b;
  result = result<<8;
  b = SPI.transfer(0xff);   // B0
  result |= b;
 
  // take the SS pin high to de-select the chip:
  digitalWrite(slaveSelectPin,HIGH);
  return(result);
}
jbeale
Full Member
Full Member
 
Posts: 143
Joined: Thu Jan 13, 2011 6:48 pm

Re: sample code for LTC2440 24-bit ADC

Postby jbeale » Fri Jun 29, 2012 1:32 pm

I should add: to reach the specified noise performance of this part (200 nV RMS) you must have an absolutely clean layout, heavy ground copper and the grounds must be connected in the right way. At first I had > 1 uV RMS, then I removed some bypass caps (dumping current into a sensitive ground area?) and it got quite a bit better to 250 nV but even after some effort, I could not quite reach the spec level with my SSOP->DIP adaptor board. At this level the "excess noise" of resistors (1/f noise) becomes relevant. Physically large metal-film resistors are generally good (low noise). Small cheap SMT resistors are usually noisy.

with the caps:
https://picasaweb.google.com/lh/photo/o ... directlink
after removing bypass caps:
https://picasaweb.google.com/lh/photo/B ... directlink
jbeale
Full Member
Full Member
 
Posts: 143
Joined: Thu Jan 13, 2011 6:48 pm

Re: sample code for LTC2440 24-bit ADC

Postby TrevorWhite » Mon Jul 02, 2012 2:09 pm

Hi. Really interesting post.Thanks for sharing.

What equipment did you use to measure the noise with?

Thanks

Trev
TrevorWhite
Newbie
Newbie
 
Posts: 23
Joined: Mon Feb 08, 2010 4:28 pm

Re: sample code for LTC2440 24-bit ADC

Postby TrevorWhite » Mon Jul 02, 2012 2:15 pm

Sorry, just ready the comments on the first picture.
TrevorWhite
Newbie
Newbie
 
Posts: 23
Joined: Mon Feb 08, 2010 4:28 pm

Re: sample code for LTC2440 24-bit ADC

Postby tech2077 » Mon Jul 02, 2012 2:31 pm

Do you have any pictures of the setup?
tech2077
Newbie
Newbie
 
Posts: 7
Joined: Sun Jul 24, 2011 4:42 pm

Re: sample code for LTC2440 24-bit ADC

Postby jbeale » Mon Jul 02, 2012 6:55 pm

I don't have any photos (it was a rather crude setup anyway) and I don't have it set up right now... as you'll note from the code, this was from back in 2010. I only just posted the code now since a user here doing a LTC2440 sensor project sent me a PM to request it.
jbeale
Full Member
Full Member
 
Posts: 143
Joined: Thu Jan 13, 2011 6:48 pm

Re: sample code for LTC2440 24-bit ADC

Postby ajohansson1981 » Tue Jul 03, 2012 10:49 am

Thank you for this John.

This ADC is truly fantastic in terms of the extremely good noise and INL specs, versus how easy it is to setup. And John's code above worked on first try.

Here is some information for everyone's reference:
In terms of a basic working setup of this ADC, see my Attached Image below (PNG file).

(Note that almost this exact setup also applies to LTC2410, which has even better specs, but smaller maximum data output rate.)

As you can see in my layout in that image, a merely functional setup of LTC2440 is extremely easy -- and I got about 3 uV RMS noise doing so on the breadboard.

But getting it down to the specified 200nV RMS noise is what might be difficult and/or require a PCB layout. John has made some suggestions above for that.
If anyone gets their noise down to hundreds of nanovolt level, do report!

Also, you can look on the 1st page of the LTC2440 datasheet for a minimal circuit

In addition, Mark Thoren, a Linear Technology engineer, has written this nice article with recommendation circuits for LTC2440 and other sigma-delta ADCs. Google search for this: AN96 - Delta Sigma ADC Bridge Measurement Techniques.

Finally, take a look at the manual PDF of the LTC2440 Demo Board, also on Linear's website.

-Anders
Attachments
LTC2440_Setup01.PNG
LTC2440 Layout / Setup
ajohansson1981
Newbie
Newbie
 
Posts: 2
Joined: Tue Jul 03, 2012 10:16 am

Re: sample code for LTC2440 24-bit ADC

Postby jbeale » Tue Jul 03, 2012 4:51 pm

Hey, I just opened an old box, and what do you know, the circuit is still there. As I said, not very pretty. I had series resistors on the digital lines to the Arduino on the theory it might reduce edge rates and hence digital noise coupling. Not sure there was much benefit though. You can also see a LTC1052 "zero-drift" chopper-stabilized amplifier on the right, not connected. I was using a LT1021B as a 5V reference (not shown).

Image
https://picasaweb.google.com/1099282360 ... 3269182194
jbeale
Full Member
Full Member
 
Posts: 143
Joined: Thu Jan 13, 2011 6:48 pm

Re: sample code for LTC2440 24-bit ADC

Postby AIW » Tue Jul 17, 2012 5:19 pm

Here is a link to another 24 Bit A/D from Linear (LTC2400) and utilizes a little bit diffent code. Also integrates a precision 5 volt reference chip. Be advised Linear is very good about sending out free samples if you would like to set this up. I got 2 or 3 free samples and used this setup for a thermistor min/max unit. I did add a unity gain opamp between the analog voltage source and the A/D input. It worked great.

http://interface.khm.de/index.php/lab/experiments/connect-a-ltc2400-high-precision-24-bit-analog-to-digital-converter/
User avatar
AIW
Newbie
Newbie
 
Posts: 29
Joined: Tue Sep 27, 2011 5:01 am
Location: Kansas City, MO

Re: sample code for LTC2440 24-bit ADC

Postby botsmaker » Fri Jul 27, 2012 11:14 pm

The sample code at the link with the ltc2400 (at the end of the post) had a bad compile. "PB4 is not declared" was the error. Does anyone know the fix.
botsmaker
Newbie
Newbie
 
Posts: 2
Joined: Fri Jul 27, 2012 11:04 pm

Re: sample code for LTC2440 24-bit ADC

Postby ajohansson1981 » Wed Aug 08, 2012 1:44 am

You have to just change PB4 to PORTB4 (and if necessary, PB5 to PORTB5, etc.)
botsmaker wrote:The sample code at the link with the ltc2400 (at the end of the post) had a bad compile. "PB4 is not declared" was the error. Does anyone know the fix.
ajohansson1981
Newbie
Newbie
 
Posts: 2
Joined: Tue Jul 03, 2012 10:16 am

Re: sample code for LTC2440 24-bit ADC

Postby botsmaker » Wed Aug 08, 2012 7:51 am

That fix it. It works now.
botsmaker
Newbie
Newbie
 
Posts: 2
Joined: Fri Jul 27, 2012 11:04 pm

Another 24-bit ADC: LTC2410

Postby jbeale » Tue Oct 23, 2012 5:00 pm

Below is a slightly modified version of Martin Nawrath's LTC2400 ADC code, which I am using with a LTC2410 (a fully-differential version of the 2400). This code should work as-is with a LTC2400 as well, except the output will be half the correct value, due to the difference in full-scale value and output normalization between the two chips.

The differential input is taken from a 4x10k full bridge using simple 1/4 watt resistors. My circuit has both Vcc and +Vref connected to +5V from a LM7805. The 2410 has an input range of -(Vref/2) to +(Vref/2) or in my case, -2.5 to +2.5V for a full-scale span of 5V.

I have Fo (pin 14) connected to GND for 60 Hz noise rejection, giving me a 134 msec output rate. Obtaining 100 samples takes about 134 seconds. The datasheet claims 0.8 uV(rms) noise for the LTC2410, and in my case I am seeing 1.3 uV(rms). With the full scale span being 5V, that means the RMS noise is 2.6E-7 of full scale, giving me 21.9 bits (rms) of resolution. The datasheet claim is 22.6 bits (rms) so I'm not too far off.

The circuit was in a plastic box to shield from drafts, but a metal shielding box might reduce noise further. I mounted the SSOP-16 chip on an ebay adaptor I had handy, which turned out to have pins 1-8 some non-100-mil-multiple spacing from pins 9-16, so I had to use it SIP-style on the breadboard, as you see below. I used copper foil under the chip to try for a solid ground (pins 1,7,8,9,10,15,16 are all ground pins on this device).

Photos: LTC2410 on adaptor and adaptor assy in breadboard.

Note: I saw 3 uV(rms) noise when Vcc came from a noisy 5V USB rail, even though +Vref was still using the cleaner LM7805 output, so there is some noise coupling from the Vcc supply.

Sample output from program (last column is the standard deviation of 100 readings, in microvolts).
Code: Select all
count,sec,value,stdev
# LTC2410 v0.1 Oct.23 2012  jpb
0,13.59,0.0063365,1.29
1,26.98,0.0063367,1.38
2,40.38,0.0063368,1.35
3,53.77,0.0063368,1.30
4,67.16,0.0063368,1.46
5,80.55,0.0063369,1.36
6,93.94,0.0063368,1.25
7,107.33,0.0063368,1.28
8,120.72,0.0063372,1.32
9,134.12,0.0063372,1.18
10,147.51,0.0063371,1.14
11,160.90,0.0063369,1.24
12,174.29,0.0063371,1.30

Arduino code which generated above output:
Code: Select all
/* *********** LTC2410 24 Bit ADC Test  *************
* Connect an LTC2410 24 Bit ADC to the Arduino Board in SPI Mode
* by John Beale, Oct. 23 2012
* based on code for LTC2400 by KHM 2009 /  Martin Nawrath
* from http://interface.khm.de/index.php/lab/experiments/
*/

// define clear-bit and set-bit macros
#ifndef cbi
#define cbi(sfr, bit)     (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit)     (_SFR_BYTE(sfr) |= _BV(bit))
#endif

// Setup SPI pins at standard Arduino locations (specific to ATmega328p chip)
#define LTC_CS 2         // LTC2410 Chip Select Pin on PortB.2 (pin16: D10, CS)
#define LTC_MISO  4      // LTC2410 SDO Select Pin  on PortB.4 (pin18: D12, MISO)
#define LTC_SCK  5       // LTC2410 SCK Select Pin  on PortB.5 (pin19: D13, SCK)

// ADC-related constants
#define VREF (5.0)       // ADC Reference, Volts
#define SAMPLES (100)    // how many readings to combine for average and standard deviation

void setup() {

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

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

Serial.begin(115200);   // serial port baud rate
// 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("count,sec,value,stdev");
Serial.println("# LTC2410 v0.1 Oct.23 2012  jpb");
cbi(PORTB,LTC_CS);           // LTC2410 CS Low
delay(200);                  // acquire first reading
SPI_read();                  // throw it away (1st one has big offset)
sbi(PORTB,LTC_CS);           // LTC2410 CS High
delay(1);                 
cbi(PORTB,LTC_CS);           // LTC2410 CS Low
} // end setup()

/********************************************************************/

int cnt;                  // ADC reading counter

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

float datSum = 0;  // reset our accumulated sum of input values to zero
float sMax;
float sMin;
long n;            // count of how many readings so far
float x,mean,delta,sumsq,m2,variance,stdev;  // to calculate standard deviation   
               
  sMax = -VREF;  // set max to minimum possible reading
  sMin = VREF;   // set min to max possible reading
  sumsq = 0; // initialize running squared sum of differences
  n = 0;     // have not made any ADC readings yet
  mean = 0; // start off with running mean at zero
  m2 = 0;
             
  for (int i=0;i<SAMPLES;i++) {
    while (PINB & (1 << PORTB4)) {}  // busy loop waiting for ADC to be ready     
    x = readADC();    // get analog reading in units of volts
//    Serial.println(x,6);
    datSum += x;
    if (x > sMax) sMax = x;
    if (x < sMin) sMin = x;
                      // from http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
    n++;
    delta = x - mean;
    mean += delta/n;
    m2 += (delta * (x - mean));
  }
  variance = m2/(n-1);  // (n-1):Sample Variance  (n): Population Variance
  stdev = 1E6*sqrt(variance);  // Calculate standard deviation in microvolts

  float tsec = millis()/1000.0;  // elapsed time in seconds
  Serial.print(cnt++);
  Serial.print(",");
  Serial.print(tsec,2);      // elapsed time, seconds
  Serial.print(",");
  Serial.print(mean,7);      // average reading, volts
  Serial.print(",");
  Serial.print(stdev,2);     // standard deviation, microvolts
  Serial.println();

} // end loop()


// ******************************************************************************
// readADC():  read 32-bit word from Linear Tech LTC2410 and return volts
// currently ignoring the "overrange" and "underrange" condition flags

float readADC(void) {

float volt;               // ADC reading in real-world units (volts)
long int ltw = 0;         // full 32-bit ADC data word
byte b0;                  // one byte in ADC data word
byte sig;                 // sign bit flag

   ltw=0;  // 32-bit data word
   sig=0;  // sign bit

   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;

   sbi(PORTB,LTC_CS);           // LTC2410 CS hi: start of new ADC conversion
   delayMicroseconds(5);
   cbi(PORTB,LTC_CS);           // LTC2410 CS Low: allow detection of "conversion done" bit on MISO pin
 
   if (sig) ltw |= 0xf0000000;    // if input is negative, insert sign bit
   ltw=ltw/16;                    // scale result down , last 4 bits have no information
   volt = ltw * VREF / (2 * 16777216); // +Vfullscale = +Vref/2, max scale (2^24 = 16777216)
   return(volt);
   
} // end readADC()   


/********************************************************************/
byte SPI_read()
{
SPDR = 0;
while (!(SPSR & (1 << SPIF))) ; /* Wait for SPI shift out done */
return SPDR;
}
jbeale
Full Member
Full Member
 
Posts: 143
Joined: Thu Jan 13, 2011 6:48 pm

Another try using LTC2440 24-bit ADC

Postby jbeale » Thu Oct 25, 2012 8:32 pm

Success! I finally got the datasheet-specified noise performance from the LTC2440 ADC. I made a new circuit with more attention to very low-impedance grounds, and I built it SIP-style with the digital side having pins, and the analog portion on its own ground plane without directly contacting the breadboard. My signal is as before, two 1k resistors forming a divider from +Vref to -Vref (GND) and a 10 ohm resistor between +IN and -IN to give me a signal of about (5V/2.01k)*10 ohms = 25 mV with a common-mode voltage of 2.5 V. This circuit shows 198 nV (rms) noise, right at the spec level (200 nV) for the 6.9 Hz output rate. You can see after turning on the circuit, my 24.948 mV signal drifts down by less than one microvolt (!) and then levels off, over the course of 45 minutes. That is < 40 ppm stability.

What would I expect the drift to be? I assume the dominant error is thermal drift of the 1k resistors. Taking a wild guess, say a 1/4 watt resistor is 400 C/W, and at 2.5 mA current each 1k resistor dissipates I^2*R = 6.25 mW, so dT = 2.5 C temperature rise. I think these parts are spec'd to be 100 ppm/C, so looks like they're at least 4x better than their spec limit- not too bad.

The earlier prototype (first few posts in this thread) used the adaptor board DIP-style with the analog connections on the solderless breadboard, and it never got below 250 nV (rms) with semi-periodic sudden signal jumps of about 1 uV. I believe that was related to the mechanical pressure contacts making the wire connections inside the breadboard; they are not suited to clean signals at the microvolt level.

LTC2440-Oct25.png

Photo of new circuit on adaptor board:
LTC2440-prototype-2.JPG

chip on adaptor board: https://picasaweb.google.com/1099282360 ... 0911690210
adaptor board on breadboard: https://picasaweb.google.com/1099282360 ... 7608211970

The code is slightly different, this time I used the BUSY;READY/ signal from the chip to read out the ADC the moment it is done converting, rather than hard-coding the delay using the Arduino's clock.

Example Code for LTC2440:
Code: Select all
/*
  Interface between Arduino DM board and Linear Tech LTC2440 24-bit ADC
  Oct. 24 2012 John Beale

   LTC2440  <---------->  Arduino
   10: /EXT : ground (use external serial clock)
   11: /CS <- to digital pin 10  (SS pin)
   12: MISO -> to digital pin 12 (MISO pin)
   13: SCLK <- to digital pin 13 (SCK pin)
   15: BUSY -> to digital pin 9 (low when result ready)

   1,8,9,16: GND :  all grounds must be connected
   2: Vcc :   +5V supply
   3: REF+ :  +5V reference
   4: REF- :  GND
   5: IN+  :  Input+
   6: IN-  :  Input-
   7: SDI  : +5V  (select 6.9 Hz output rate, or GND for 880 Hz rate)
   14: Fo : GND  (select internal 9 MHz oscillator)

*/

#include <SPI.h>  // include the SPI library
#include <digitalWriteFast.h> // from http://code.google.com/p/digitalwritefast/downloads/list
// I had to update the WriteFast library for Arduino 1.0.1: replace "#include wiring.h" and "#include WProgram.h"
//   with "#include <Arduino.h>"  in libraries/digitalwritefast/digitalWriteFast.h

#define VREF (5.0)    // ADC voltage reference
#define PWAIT (198)   // milliseconds delay between readings
#define SLAVESELECT 10  // digital pin 10 for CS/
#define BUSYPIN 9     // digital pin 9 for BUSY or READY/


const int nsamples = 50;  // how many ADC readings to average together

// SPI_CLOCK_DIV16 gives me a 1.0 MHz SPI clock, with 16 MHz crystal on Arduino

void setup() {

Serial.begin(115200);  // set up serial comm to PC at this baud rate
   
pinMode (SLAVESELECT, OUTPUT);
pinMode (BUSYPIN, INPUT);
digitalWriteFast(SLAVESELECT,LOW);   // take the SS pin low to select the chip
delayMicroseconds(1);
digitalWriteFast(SLAVESELECT,HIGH);   // take the SS pin high to start new ADC conversion

SPI.begin(); // initialize SPI, covering MOSI,MISO,SCK signals
SPI.setBitOrder(MSBFIRST);  // data is clocked in MSB first
SPI.setDataMode(SPI_MODE0);  // SCLK idle low (CPOL=0), MOSI read on rising edge (CPHI=0)
SPI.setClockDivider(SPI_CLOCK_DIV16);  // set SPI clock at 1 MHz. Arduino xtal = 16 MHz, LTC2440 max = 20 MHz
Serial.println("# LTC2440 v1.1 Oct.25 2012  jpb"); 
Serial.println("min,uVolts,pkpk,stdev");
for (int i=0;i<2;i++) {  // throw away the first few readings, which seem to be way off
  SpiRead();
}
} // end setup()

// =============================================================================
// Main Loop:
// acquire 'nsamples' readings, convert to units of volts, and send out on serial port

void loop() {

int i;
long secs;
float mins;
long in; // incoming serial 32-bit word
float uVolts;  // average reading in microvolts

float datSum;  // accumulated sum of input values
float sMax;
float sMin;
long n;            // count of how many readings so far
float x,mean,delta,sumsq,m2,variance,stdev,pp;  // to calculate standard deviation   

  sMax = -VREF;  // set max to minimum possible reading
  sMin = VREF;   // set min to max possible reading
  sumsq = 0; // initialize running squared sum of differences
  n = 0;     // have not made any ADC readings yet
  datSum = 0;  // accumulated sum of readings starts at zero
  mean = 0; // start off with running mean at zero
  m2 = 0;
 
  for (i=0; i<nsamples; i++) {
    x = SpiRead();
    datSum += x;
    if (x > sMax) sMax = x;
    if (x < sMin) sMin = x;
                      // from http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
    n++;
    delta = x - mean;
    mean += delta/n;
    m2 += (delta * (x - mean));

  } // end for (i..)

  variance = m2/(n-1);  // (n-1):Sample Variance  (n): Population Variance
  stdev = 1E6*sqrt(variance);  // Calculate standard deviation in microvolts
  pp = 1E6 * (sMax - sMin);   // peak-to-peak difference of readings, in uV
 
  uVolts = datSum * (1E6) / n;

mins = (float) millis() / 60000;   // elapsed time in minutes
Serial.print(mins,3);
Serial.print(", ");
Serial.print(uVolts,3);
Serial.print(", ");
Serial.print(pp,3);
Serial.print(", ");
Serial.print(stdev,3);
Serial.println();

} // end main loop


// =================================================================
// SpiRead() -- read 4 bytes from LTC2440 chip via SPI, return Volts
// =================================================================

float SpiRead(void) {

  long result = 0;
  byte sig = 0;    // sign bit
  byte b;
  float v;
 
  while (digitalReadFast(BUSYPIN)==HIGH) {}  // wait until ADC result is ready
 
  digitalWriteFast(SLAVESELECT,LOW);   // take the SS pin low to select the chip
  delayMicroseconds(1);  // probably not needed, only need 25 nsec delay

  b = SPI.transfer(0xff);   // B3
  if ((b & 0x20) ==0) sig=1;  // is input negative ?
  b &=0x1f;    // discard bits 25..31
  result = b;
  result <<= 8; 
  b = SPI.transfer(0xff);   // B2
  result |= b;
  result = result<<8;
  b = SPI.transfer(0xff);   // B1
  result |= b;
  result = result<<8;
  b = SPI.transfer(0xff);   // B0
  result |= b;
   
  digitalWriteFast(SLAVESELECT,HIGH);   // take the SS pin high to bring MISO to hi-Z and start new conversion
 
  if (sig) result |= 0xf0000000;    // if input is negative, insert sign bit (0xf0.. or 0xe0... ?)       
  v = result;
  v = v / 16.0;                             // scale result down , last 4 bits are "sub-LSBs"
  v = v * VREF / (2 * 16777216); // +Vfullscale = +Vref/2, max scale (2^24 = 16777216)
  return(v); 
}
Last edited by jbeale on Tue Oct 30, 2012 1:17 pm, edited 1 time in total.
jbeale
Full Member
Full Member
 
Posts: 143
Joined: Thu Jan 13, 2011 6:48 pm

Re: sample code for LTC2440 24-bit ADC

Postby jbeale » Fri Oct 26, 2012 2:18 pm

Just an observation, it looks like the last two bits of the 32-bit output word from the LTC2440 are always fixed, despite Table 2 in the data sheet saying otherwise. I sent the below note to Linear Tech support, we'll see what they say. I can't really complain, since the 200 nV noise level of the part matches what they claim.

I am evaluating the LTC2440 with SDI held high, for the 6.9 Hz output data rate. I do see the specified 200 nV (rms) noise performance which the datasheet claims, so the part appears to be working as designed. I notice that b4, b3,and b2 fluctuate, but two least significant bits in the 32-bit output word are always fixed. Bit 1 is always low, and bit 0 is always high. This is true both with internal SCK (pin 10 held high), and with external SCK. Is this expected? Table 2 on p. 12 of the datasheet shows bit 0 can be high or low depending on the input, and also says the "sub LSBs" below bit 5 can be included in averaging, and in "ultrahigh resolution modes... sub LSBs... represent useful information".
jbeale
Full Member
Full Member
 
Posts: 143
Joined: Thu Jan 13, 2011 6:48 pm

Next

Return to General discussion