Hello everyone!
I'm totally new to Arduino and SPI and my programming skills are purely basic.
I'm supposed to hook up a 24bit ADC to an Arduino Mega 2560 and started with a ltc2400 combined with a lt1021 5.0V voltage reference according to this tutorial:
It works perfectly fine. But now we realized, we need at least two, rather four channels in total for our experiments (heat flow measurements, need to acquire 2 temperatures and at least one voltage from the heat flow sensor, which is about a few mV). So I found the LTC2442 ADC which is similar to the LTC2400 but has four channels.
LTC2442 datasheet: http://docs-europe.electrocomponents.com/webdocs/10ed/0900766b810ed9bc.pdf
Then I tried to adapt the LTC2400-code to the LTC2442 by inserting a few commands i found on various websites and in this forum (e.g. Help needed with a 4 differential channels simultaneous ADC MAX11040k. - Networking, Protocols, and Devices - Arduino Forum ). But I'm not able to read any data from the ADC, all Output i get is "5.00000 V" for every channel.
Has anyone experience with this ADC or can tell me, what is wrong in my code? I'm pretty sure it's the SPI stuff...
If somebody has ideas on a better or easier solution for my experiment, I'm open for suggestions!
Thanks!
Dave
Here my current code:
// LTC2442 24 Bit 4 Channel ADC Test
#include <Stdio.h>
#include <SPI.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 0 // LTC2442 Chip Select Pin on Mega Pin 53
#define LTC_MISO 3 // LTC2442 SDO Pin on Mega Pin 50
#define LTC_SCK 1 // LTC2442 SCK Pin on Mega Pin 52
byte commandCH0 = B10110000; // Channel Selection
byte commandCH1 = B10110001;
byte commandCH2 = B10111000;
byte commandCH3 = B10111001;
byte commandResolution = B00010; // Resolution Selection
byte commandKeepRes = B00000; // keep previous Resolution Settings
void setup() {
SPI.setBitOrder(MSBFIRST);
cbi(PORTB,LTC_SCK); // LTC2442 SCK low
sbi (DDRB,LTC_CS); // LTC2442 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("LTC2442 4-channel ADC Test");
cbi (PORTB,LTC_CS);
SPI.transfer(commandCH0); //select first channel
SPI.transfer(commandResolution);
sbi(PORTB,LTC_CS);
delay(200);
}
float volt0;
float volt1;
float volt2;
float volt3;
float v_ref=5.0; // Reference Voltage, 5.0 Volt for LT1021
long int ltw0 = 0; // ADC Data long int
long int ltw1 = 0; // ADC Data long int
long int ltw2 = 0; // ADC Data long int
long int ltw3 = 0; // ADC Data long int
int cnt; // counter
byte b0; //
byte sig; // sign bit flag
char st1[20]; // float voltage text
/********************************************************************/
void loop() {
cbi(PORTB,LTC_CS); // LTC2442 CS Low
delayMicroseconds(1);
//if (!(PINB & (1 << PORTB2))) { // ADC Converter ready ? doesnt work, not sure if this is necessary/possible with ltc2442
ltw0=0;
ltw1=0;
ltw2=0;
ltw3=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
ltw0 |= b0;
ltw0 <<= 8;
b0 = SPI_read();
ltw0 |= b0;
ltw0 <<= 8;
b0 = SPI_read();
ltw0 |= b0;
ltw0 <<= 8;
b0 = SPI_read();
ltw0 |= b0;
sbi(PORTB,LTC_CS); // LTC2442 CS high
delay(200);
cbi(PORTB,LTC_CS); // LTC2442 CS Low
SPI.transfer(commandCH1); // Send command for next channel
SPI.transfer(commandKeepRes);
sbi(PORTB,LTC_CS); // LTC2442 CS high
delay(200);
cbi(PORTB,LTC_CS); // LTC2442 CS Low
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
ltw1 |= b0;
ltw1 <<= 8;
b0 = SPI_read();
ltw1 |= b0;
ltw1 <<= 8;
b0 = SPI_read();
ltw1 |= b0;
ltw1 <<= 8;
b0 = SPI_read();
ltw1 |= b0;
sbi(PORTB,LTC_CS); // LTC2442 CS high
delay(200);
cbi(PORTB,LTC_CS); // LTC2442 CS Low
SPI.transfer(commandCH2); // Send command for next channel
SPI.transfer(commandKeepRes);
sbi(PORTB,LTC_CS); // LTC2442 CS high
delay(200);
cbi(PORTB,LTC_CS); // LTC2442 CS Low
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
ltw2 |= b0;
ltw2 <<= 8;
b0 = SPI_read();
ltw2 |= b0;
ltw2 <<= 8;
b0 = SPI_read();
ltw2 |= b0;
ltw2 <<= 8;
b0 = SPI_read();
ltw2 |= b0;
sbi(PORTB,LTC_CS); // LTC2442 CS high
delay(200);
cbi(PORTB,LTC_CS); // LTC2442 CS Low
SPI.transfer(commandCH3); // Send command for next channel
SPI.transfer(commandKeepRes);
sbi(PORTB,LTC_CS); // LTC2442 CS high
delay(200);
cbi(PORTB,LTC_CS); // LTC2442 CS Low
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
ltw3 |= b0;
ltw3 <<= 8;
b0 = SPI_read();
ltw3 |= b0;
ltw3 <<= 8;
b0 = SPI_read();
ltw3 |= b0;
ltw3 <<= 8;
b0 = SPI_read();
ltw3 |= b0;
sbi(PORTB,LTC_CS); // LTC2442 CS high
delay(200);
cbi(PORTB,LTC_CS); // LTC2442 CS Low
SPI.transfer(commandCH1); // Send command for next channel
SPI.transfer(commandKeepRes);
delayMicroseconds(1);
sbi(PORTB,LTC_CS); // LTC2442 CS HIGH
delay(200);
if (sig) ltw0 |= 0xf0000000; // if input negative insert sign bit
if (sig) ltw1 |= 0xf0000000; // if input negative insert sign bit
if (sig) ltw2 |= 0xf0000000; // if input negative insert sign bit
if (sig) ltw3 |= 0xf0000000; // if input negative insert sign bit
ltw0=ltw0/16; // scale result down , last 4 bits have no information
ltw1=ltw1/16; // scale result down , last 4 bits have no information
ltw2=ltw2/16; // scale result down , last 4 bits have no information
ltw3=ltw3/16; // scale result down , last 4 bits have no information
volt0 = ltw0 * v_ref / 16777216; // max scale
volt1 = ltw1 * v_ref / 16777216; // max scale
volt2 = ltw2 * v_ref / 16777216; // max scale
volt3 = ltw3 * v_ref / 16777216; // max scale
Serial.print(cnt++);
Serial.print("; ");
printFloat(volt0,6); // print voltage as floating number
Serial.print("; ");
printFloat(volt1,6); // print voltage as floating number
Serial.print("; ");
printFloat(volt2,6); // print voltage as floating number
Serial.print("; ");
printFloat(volt3,6); // print voltage as floating number
Serial.println(" ");
//}
sbi(PORTB,LTC_CS); // LTC2442 CS high
delay(20);
}
/********************************************************************/
byte SPI_read()
{
SPDR = 0;
while (!(SPSR & (1 << SPIF))) ; /* Wait for SPI shift out done */
return SPDR;
}
/********************************************************************/
void printFloat(float value, int places) {
int digit;
float tens = 0.1;
int tenscount = 0;
int i;
float tempfloat = value;
float d = 0.5;
if (value < 0)
d *= -1.0;
for (i = 0; i < places; i++)
d/= 10.0;
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;
}
}