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).
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.
I soldered the 2x1k input divider to the board, because you can't get microvolt low noise connections using breadboard contacts.
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.