T3 example using LTC2400 (24-bit ADC)

Status
Not open for further replies.

JBeale

Well-known member
In case of interest. The Linear Tech LTC2400 is the easiest to use 24-bit ADC I've found (in a SO-8 package, not much to go wrong).

Code:
/*
 Interface Teensy 3 with Linear Tech LTC2400 24-bit ADC (7.5 Hz sample rate)
 by J.Beale  March 26, 2016 

 Signal  ADC    Teensy
 ---------------------
 CS:     pin 5  pin 7
 MISO:   pin 6  pin 12
 SCK:    pin 7  pin 13
 ---------------------
 */

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

#define VREF (5.000)     // reference voltage
#define SAMPLES (50)   // how many samples to group together for stats

const int chipSelectPin = 7;
const int SDO = 12;    // SPI Input line (high->low = data ready)

unsigned int cnt;    // simple loop counter

void setup() {
  Serial.begin(115200);
  SPI.begin();
  pinMode(chipSelectPin, OUTPUT);
  cnt = 0;
  
  delay(2000);  // because Windows doesn't notice the serial port that fast
  Serial.println("count,sec,value,stdev");
  Serial.println("# LTC2400 v0.3 Mar.26 2016 jpb");
}

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

double datSum = 0;  // reset our accumulated sum of input values to zero
double sMax;
double sMin;
long n;            // count of how many readings so far
double x,mean,delta,sumsq,m2,variance,stdev;  // to calculate standard deviation   
                
  sMax = -VREF;  // set max to minimum possible reading
  sMin = 2*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++) {
    x = readWord() * VREF / (1<<28);  // analog reading in units of Volts
    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()


// Read data from Linear Tech LTC2400  (24-bit ADC) using SPI
// The data word is actually 28 bits, although lowest 4 bits are noise
unsigned long int readWord() {
  byte inByte = 0;           // incoming byte from the SPI
  byte bytesToRead = 4;      // read this many bytes from SPI
  unsigned long int result = 0;   // result to return
  boolean EXR = 0;
  boolean SGN = 0;

  // LTC2400 SPI clock can go up to 2 MHz
  SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
  digitalWrite(chipSelectPin, LOW);

  while (digitalRead(SDO) == 1) {}   // wait for MISO to fall low => conversion ready

  result = SPI.transfer(0x00);
  SGN = result & 0x20;           // Sign bit
  EXR = result & 0x10;           // Extended Range bit
  result &= 0x0f;                // mask off high 4 bits

  for (byte i=0; i<3; i++) {     // read remaining 3 bytes of 32-bit output word
    result <<= 8;
    result |= SPI.transfer(0x00);
  }
  digitalWrite(chipSelectPin, HIGH);  // put chip in sleep mode
  SPI.endTransaction();  // release control of SPI port

  return(result);  // return 28-bit ADC result
}  // readWord()

Using 4x NiMH AA cells to provide a quiet +5V supply, with 2x 1.000k 0.1% resistors as a 2:1 divider to put the input at 0.5 Vref, and running the above code I see the output readings have about 1.7 microvolts RMS noise, that is less than 0.5 ppm of the 5V full scale. Not bad at all, and I didn't even separate Vref from Vcc. Note: if I use the +5V USB for Vref instead of the battery supply, I get about 100 uV rms noise.

Code:
count,sec,value,stdev
# LTC2400 v0.3 Mar.26 2016 jpb
0,8.81,2.5004500,1.58
1,15.51,2.5004497,1.65
2,22.21,2.5004504,1.40
3,28.91,2.5004499,1.77
4,35.61,2.5004503,1.71
5,42.31,2.5004501,1.30
6,49.01,2.5004502,1.62
7,55.70,2.5004505,1.59
8,62.40,2.5004501,1.23
9,69.10,2.5004506,1.51
10,75.80,2.5004502,1.35

I soldered the 2x1k input divider to the board, because you can't get microvolt low noise connections using breadboard contacts.
IMG_5645.JPG
 
Status
Not open for further replies.
Back
Top